%% generate tags start %%
#software-engineering
%% generate tags end %%
#software-engineering/php
## What is It?

PHP (recursive acronym for `PHP: Hypertext Preprocessor`) is a widely-used open source general-purpose scripting language that is especially suited for web development and can be embedded into HTML.
Nice, but what does that mean? An example:
**Example #1 An introductory example**
```php
<!DOCTYPE html>
<html>
<head>
<title>Example</title>
</head>
<body>
<?php
echo "Hi, I'm a PHP script!";
?>
</body>
</html>
```
Instead of lots of commands to output HTML (as seen in C or Perl), PHP pages contain HTML with embedded code that does "something" (in this case, output "Hi, I'm a PHP script!"). The PHP code is enclosed in special [start and end processing instructions `<?php` and `?>`](https://www.php.net/manual/en/language.basic-syntax.phpmode.php) that allow you to jump into and out of "PHP mode."
What distinguishes PHP from something like client-side JavaScript is that the code is executed on the server, generating HTML which is then sent to the client. The client would receive the results of running that script, but would not know what the underlying code was. You can even configure your web server to process all your HTML files with PHP, and then there's really no way that users can tell what you have up your sleeve.
## Php 101
> [!info] this guide also comes with a github repo: [HananoshikaYomaru/simplist-php (github.com)](https://github.com/HananoshikaYomaru/simplist-php)
Some of the good materials online you can learn php:
1. the offical doc
2. [PHP: The Right Way (phptherightway.com)](https://phptherightway.com/)
---
to start with php on mac, you need to install php:
```
brew install php
```
then check
```
php -v
```
**Running a PHP Script**
- Create a PHP file to test your setup. You can do this in your text editor. For example, create a file named `test.php` with the following content:
```php
<?php echo "Hello, World!"; ?>
```
- Run this script in the Terminal by navigating to the directory where the file is located and typing `php test.php`.
you can also try this
```php
<?php $expression = true; ?>
<?php if ($expression == true) : ?>
This will show if the expression is true.
<?php else : ?>
Otherwise this will show.
<?php endif; ?>
```
```
This will show if the expression is true.
```
```php
<?php
echo "a"; echo "b"; echo "c";
#The output will be "abc" with no errors
?>
```
```
abc
```
comments
```php
<?php
echo 'This is a test'; // This is a one-line c++ style comment
/* This is a multi line comment
yet another line of comment */
echo 'This is yet another test';
echo 'One Final Test'; # This is a one-line shell-style comment
?>
```
logging
```php
error_log("something")
```
---
what are the basic data type in php?
you can learn more from [PHP: Types - Manual](https://www.php.net/manual/en/language.types.php)
- [Introduction](https://www.php.net/manual/en/language.types.intro.php)
- [Type System](https://www.php.net/manual/en/language.types.type-system.php)
- [NULL](https://www.php.net/manual/en/language.types.null.php)
- [Booleans](https://www.php.net/manual/en/language.types.boolean.php)
- [Integers](https://www.php.net/manual/en/language.types.integer.php)
- [Floating point numbers](https://www.php.net/manual/en/language.types.float.php)
- [Strings](https://www.php.net/manual/en/language.types.string.php)
- [Numeric strings](https://www.php.net/manual/en/language.types.numeric-strings.php)
- [Arrays](https://www.php.net/manual/en/language.types.array.php)
- [Objects](https://www.php.net/manual/en/language.types.object.php)
- [Enumerations](https://www.php.net/manual/en/language.types.enumerations.php)
- [Resources](https://www.php.net/manual/en/language.types.resource.php)
- [Callbacks / Callables](https://www.php.net/manual/en/language.types.callable.php)
- [Mixed](https://www.php.net/manual/en/language.types.mixed.php)
- [Void](https://www.php.net/manual/en/language.types.void.php)
- [Never](https://www.php.net/manual/en/language.types.never.php)
- [Relative class types](https://www.php.net/manual/en/language.types.relative-class-types.php)
- [Value types](https://www.php.net/manual/en/language.types.value.php)
- [Iterables](https://www.php.net/manual/en/language.types.iterable.php)
- [Type declarations](https://www.php.net/manual/en/language.types.declarations.php)
- [Type Juggling](https://www.php.net/manual/en/language.types.type-juggling.php)
php has no static type check

This will have no problem by default in php
---
how to create a most minimal php app (a hello world app)?
```
php -S localhost:8000
```
the website will be set up.
`index.php` will map to `localhost:8000`.
`hello.php` will map to `localhost:8000/hello.php`.
### Todolist Using Php
see [[Todolist using php]]
### Static Typecheck
> [!question] is php strong typed language (a language with static type check)?
> if it is not strong typed, any way to strong type it / static type check it? 🤔

PHP is not considered a strongly typed language; it is a dynamically typed language. However, PHP has introduced features that allow for more type-specific programming, especially in its later versions:
1. **Scalar Type Declarations**: As of PHP 7, you can declare types for function arguments (like `int`, `float`, `string`, `bool`), enabling a form of type checking.
2. **Return Type Declarations**: Also introduced in PHP 7, you can specify the expected return type of functions.
3. **Property Type Declarations**: From PHP 7.4 onwards, you can declare types for class properties.
4. **Strict Typing**: By default, PHP will coerce values of the wrong type into the expected type if possible. However, you can enable strict mode by declaring `declare(strict_types=1)` at the top of your file. In strict mode, PHP will throw a `TypeError` if the given value does not match the type declaration exactly.
```php
<?php
declare(strict_types=1);
function addNumbers(int $a, int $b): int {
return $a + $b;
}
echo addNumbers(5, "10"); // This will cause a TypeError in strict mode
?>
```
In this example, `addNumbers` function is expected to receive two integers and return an integer. If you pass a different type, it will result in an error in strict mode.
#### Limitations
- **Runtime Type Checking**: Even with these features, PHP's type checking is performed at runtime, not at compile time as in statically typed languages.
- **Not Fully Strongly Typed**: These features do not make PHP a fully strongly typed language, but they do provide tools for more type-safe code.
#### Alternatives for Static Type Checking
For static type checking in PHP, you might consider tools like:
- **[PHPStan](https://github.com/phpstan/phpstan)**: A static analysis tool that can detect issues in your PHP code without running it. It focuses on finding bugs in your code.
- **[Psalm](https://psalm.dev/)**: Another static analysis tool that is useful for finding type-related errors in your code.
Both tools can be integrated into your development workflow to provide a layer of static type checking, helping you catch type errors and improve code quality in PHP projects.
### How to Install and Manage Packages in Php?
you need to use [[Composer]]. you will learn:
1. what is composer
2. how to use composer with a todo list app
### Project Structure of PHP App
A typical PHP project structure might look like this:
```
/project-root
/src
index.php
/OtherPHPClasses
/vendor
/public
index.php // Publicly accessible file that includes the main index.php from src
/config
config.php
/resources
/views
/lang
/storage
/logs
/cache
.htaccess
.gitignore
composer.json
composer.lock
```
- **src**: Contains the PHP source code.
- **vendor**: Managed by Composer, contains third-party dependencies.
- **public**: Contains the entry point `index.php` and assets like CSS, JS, images.
- **config**: Configuration files.
- **resources**: Views/templates, localization files.
- **storage**: For logs, cache files, and other generated files.
### Gitignore Recommendations
For a PHP project using git, your `.gitignore` should typically include:
```
/vendor/
/test.log
/.idea/ # If using JetBrains PhpStorm
/.vscode/ # If using Visual Studio Code
.DS_Store # macOS file system file
/node_modules/ # If you happen to use Node.js in your project
```
### Use Php with JavaScript
see [[use javascript in php]]. You will learn how to use Ajax with Php.
after that, you can read [[use PHP with nodejs]]
### Persistent Data Using Database
If you go through the example above, you will notice that we use session to store the data. But now we will go a little further, we want to store the data in local sqlite database. This is how we do it.
Switching from using PHP sessions to an SQLite database for your to-do list application is a great way to learn about database interactions in PHP. SQLite is a lightweight, file-based database, which makes it an excellent choice for small applications like this. Here's a minimal example of how you can modify your application to use an SQLite database:
#### Step 1: Set Up SQLite Database
1. **Create a SQLite Database File**:
- Create a new file in the root of your project, e.g., `todo.db`.
2. **Create a PHP Script to Initialize the Database**:
- Create a new PHP file, e.g., `init_db.php`, to set up your database and table.
- Run this script once to initialize your database.
```php
<?php
$db = new PDO('sqlite:todo.db');
// Create table
$db->exec("CREATE TABLE IF NOT EXISTS todos (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task TEXT,
done INTEGER DEFAULT 0
)");
```
#### Step 2: Modify Your PHP File to Use SQLite
Here's how you can adjust your `index.php` to use the SQLite database:
```php
<?php
require 'vendor/autoload.php';
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
$db = new PDO('sqlite:todo.db');
// Create a log channel
$log = new Logger('todo');
$log->pushHandler(new StreamHandler('./test.log'));
if ($_SERVER["REQUEST_METHOD"] == "POST" && !empty($_POST['new_todo'])) {
$stmt = $db->prepare("INSERT INTO todos (task) VALUES (:task)");
$stmt->execute([':task' => $_POST['new_todo']]);
$log->info('New task added: ' . $_POST['new_todo']);
if ($isAjaxRequest) {
echo json_encode(['success' => true]);
exit; // End the script execution for AJAX requests
}
}
// Handle the rest of your logic here...
?>
<!DOCTYPE html>
<html lang="en">
<!-- ... Your HTML and JavaScript remain the same ... -->
</html>
```
In this script, when a new to-do item is posted, it's inserted into the SQLite database instead of the session.
#### Step 3: Fetching Data from SQLite
When loading your to-do list, you'll need to fetch the items from the SQLite database:
```php
<?php
// ... Previous PHP code ...
$todos = $db->query("SELECT * FROM todos ORDER BY done, id DESC");
?>
<!-- ... In your HTML where you list the todos ... -->
<div id="todo-list">
<?php foreach ($todos as $todo) : ?>
<div class="todo-item">
<span class="<?= $todo['done'] ? 'strikethrough' : '' ?>">
<?= htmlspecialchars($todo['task']) ?>
</span>
<a href="?toggle=<?= $todo['id'] ?>">[<?= $todo['done'] ? 'Uncheck' : 'Check' ?>]</a>
<a href="?remove=<?= $todo['id'] ?>">[Remove]</a>
</div>
<?php endforeach; ?>
</div>
```
#### Step 4: Update and Delete Operations
You'll also need to adjust the logic for toggling the `done` status and removing items to update the SQLite database accordingly:
```php
// Toggle the done status
if ($_SERVER["REQUEST_METHOD"] == "GET" && isset($_GET['toggle'])) {
$stmt = $db->prepare("UPDATE todos SET done = NOT done WHERE id = :id");
$stmt->execute([':id' => $_GET['toggle']]);
}
// Remove a todo item
if ($_SERVER["REQUEST_METHOD"] == "GET" && isset($_GET['remove'])) {
$stmt = $db->prepare("DELETE FROM todos WHERE id = :id");
$stmt->execute([':id' => $_GET['remove']]);
}
```
#### Notes
- **Database Connection**: The `PDO` object is used for connecting to the SQLite database. Ensure your PHP environment has the [[PDO - php data object]] SQLite extension enabled.
- **Error Handling**: Add error handling to your database operations for a robust application.
- **Security**: Use prepared statements as shown to prevent SQL injection.
- **Database File**: The SQLite database file (`todo.db`) is a flat file and should be placed in a secure location, ideally outside of the public web directory.
- **File Permissions**: Ensure the web server has the necessary permissions to read and write to the SQLite file.
With these changes, your application now uses an SQLite database to store the to-do items, providing a more persistent and scalable solution than PHP sessions.
<code data-gist-id="5762b8ddbc7fb949457c69821a2c6f7a"></code>
### Using with Postgres
Switching to a PostgreSQL database for your to-do list application involves a bit more setup compared to SQLite, as PostgreSQL is a full-fledged relational database system. Here's how you can modify your application to use PostgreSQL:
#### Step 1: Install and Set Up PostgreSQL
1. **Install PostgreSQL**: If not already installed, download and install PostgreSQL from [the official website](https://www.postgresql.org/download/).
2. **Create a Database**: Once installed, create a new database for your application. You can do this using PostgreSQL's command line tools or a graphical tool like pgAdmin.
3. **Create a Table**: Connect to your database and create a table for your to-do items:
```sql
CREATE TABLE todos (
id SERIAL PRIMARY KEY,
task TEXT NOT NULL,
done BOOLEAN DEFAULT FALSE
);
```
#### Step 2: Modify Your PHP File to Use PostgreSQL
You'll need to adjust your `index.php` file to connect to PostgreSQL and perform database operations. Make sure the PHP PDO extension for PostgreSQL is installed and enabled in your environment.
```php
<?php
require 'vendor/autoload.php';
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
// Connect to the PostgreSQL database
$db = new PDO('pgsql:host=localhost;dbname=yourdbname', 'username', 'password');
// Create a log channel
$log = new Logger('todo');
$log->pushHandler(new StreamHandler('./test.log'));
// Add a new todo item
if ($_SERVER["REQUEST_METHOD"] == "POST" && !empty($_POST['new_todo'])) {
$stmt = $db->prepare("INSERT INTO todos (task) VALUES (:task)");
$stmt->execute([':task' => $_POST['new_todo']]);
$log->info('New task added: ' . $_POST['new_todo']);
// ... Rest of the code for AJAX ...
}
// ... Other operations like toggle and remove ...
?>
<!DOCTYPE html>
<html lang="en">
<!-- ... Your HTML and JavaScript remain the same ... -->
</html>
```
Replace `localhost`, `yourdbname`, `username`, and `password` with your PostgreSQL server's details.