---
title: PHP For Beginners
kind: note
description: Link Laracasts Learn Laravel Path PHP For Beginners 01 - How to Choose a Programming Language 02 - Tools of the Trade Recommended editors PhpStorm Visual Studio Code PHP extension All-in-One PHP…
words: 335
readingMinutes: 2
created: '2023-04-08T00:00:00.000Z'
updated: '2026-06-29T13:10:58+02:00'
website: https://laracasts.com/series/php-for-beginners-2023-edition
---
## Link

<https://laracasts.com/series/php-for-beginners-2023-edition>

<span class="dead-link">Laracasts</span> > [Learn Laravel Path](https://laracasts.com/path) > [PHP For Beginners](https://laracasts.com/series/php-for-beginners-2023-edition)
## [01 - How to Choose a Programming Language](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/1)
## [02 - Tools of the Trade](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/2)
- Recommended editors
  - [PhpStorm](https://www.jetbrains.com/phpstorm/)
  - [Visual Studio Code](https://code.visualstudio.com/)
    - [PHP extension](https://marketplace.visualstudio.com/items?itemName=DEVSENSE.phptools-vscode)
      > All-in-One [PHP](/notes/php) support - IntelliSense, Debug, Formatter, Code Lenses, Code Fixes, Linting, Refactoring, PHPUnit Tests, Web Server, and more.
  - [Sublime Text](https://www.sublimetext.com/)
- Terminals
  - macOS
    - Terminal.app
    - [Warp](https://www.warp.dev/)
    - [iTerm2](https://iterm2.com/)
  - Windows
    - [Windows Terminal](https://github.com/microsoft/terminal)
- Ways of installing PHP
  - macOS and Linux
    - [Homebrew](https://brew.sh/)
  - Windows
    - [Laragon](https://laragon.org/)
    - [WSL](https://learn.microsoft.com/en-us/windows/wsl/install)
    - [MAMP](https://www.mamp.info/en/windows/)
  - macOS, Windows & Linux
    - [XAMPP](https://www.apachefriends.org/download.html)
  - [Docker](https://www.docker.com/)
- Database clients
  - [TablePlus](https://tableplus.com/)
  - [phpMyAdmin](https://www.phpmyadmin.net/) (MySQL only)
## [03 - Your First PHP Tag](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/3)
```php
<?php echo "Hello world"; ?>
```
## [04 - Variables](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/4)
- Statements end with a `;`
- Strings are concatenated with a `.`
- Variables start with a `$` sign
- Strings can be single-quoted or double-quoted; variables are only evaluated in the latter
## [05 - Conditionals and Booleans](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/5)
- Conditions:
   ```php
   if (condition) {
     /* ... */
   }
   else {
     /* ... */
   }
   ```
   Alternative syntax with `:` and `endif`:
   ```php
   if (condition):
     /* ... */
   else:
     /* ... */
   endif;
   ```
- `<?=` is shorthand for `<?php echo` and the semicolon is optional in this case
## [06 - Arrays](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/6)
- Arrays are declared like `[` /\* ... \*/ `]`
- Loop:
   ```php
   foreach ($var as $i) {
     /* ... do something with $i ... */
   }
   ```
   Alternative syntax with `:` and `endforeach`, often used in views:
   ```php
   foreach ($var as $i):
     /* ... do something with $i ... */
   endforeach;
   ```
- When echo'ing a variable that should immediately be followed by some other text, we can wrap it in curly braces:
   ```php
   <?php echo "{$i}©"; ?>
   ```
## [07 - Associative Arrays](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/7)
- Array indices start at zero
- Arrays can be indexed:
   ```php
   $books[2]
   ```
- Arrays can be nested
- Associative arrays are indexed by key instead of numbers:
   ```php
   $book = [
     'name' => 'Do Androids Dream of Electric Sheep',
     'author' => 'Philip K. Dick'
   ];

   echo $book['name'];
   ```
## [08 - Functions and Filters](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/8)
- `=` assigns a value
- `==` compares equality of value
- `===` compares equality of value **and** type
- Function definition and parameters:
   ```php
   function filterByAuthor($books) {
     // ...
   }
   ```
- Returning data from a function:
   ```php
   return 'foo';
   ```
- `[] =` appends a value to an array:
   ```php
   $filteredBooks = [];
   $filteredBooks[] = $book;
   ```
## [09 - Lambda Functions](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/9)
- "Lambda functions" is the technical term for "anonymous functions", i.e. functions that are not named (`function foo(a) { }`, called `foo(b)`), but may still be assigned to variables (`$foo = function (a) { };`, called `$foo(b);`).
- `array_filter` is one of many useful functions included with PHP.
## [10 - Separate Logic From the Template](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/10)
- The last `?>` on the page may be omitted (unless there is HTML after it)
- Good idea to separate logic (e.g., accessing the database or other servers) from the HTML (also called the template or "view")
- For reuse or separation, code files can be "imported" using `require` or `include`
## [12 - Page Links](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/12)
- How _not_ to do things: duplication of code
## [13 - PHP Partials](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/13)
- Controllers are responsible for accepting and processing an incoming request and providing a response
## [14 - Superglobals and Current Page Styling](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/14)
- `var_dump` converts the value of e.g. arrays and outputs them as a string
- "Superglobals", such as `$_GET`, `$_POST`, `$_SERVER`, are available from anywhere
- `die()` exits processing
- Ternary operator `expr ? if_truthy : else` as a shorthand for if/else
## [15 - Make a PHP Router](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/15)
- A router maps the URI to the corresponding controller
- `parse_url()` splits a URI into path and query(string)
- `array_key_exists()` checks if an array has a given key
- `http_response_code()` sets the HTTP status code
- Remember: For variables to be substituted within strings, the string must be enclosed in double quotes, and the variable must be enclosed in (a single set of) curly brackets
- Set a default for a parameter to make it optional, e.g.:
```php
function foo($var = 12345) { /* ... */ }
```
## [16 - Create a MySQL Database](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/16)
Install [MySQL](/notes/mysql) 8.0 on [Ubuntu](/notes/ubuntu) 22.04 running in WSL:
```shell
sudo apt install -y mysql-server-8.0
sudo /etc/init.d/mysql start
```
Create a database for this course:
```shell
sudo mysql -e "CREATE DATABASE myapp;"
```
## [17 - PDO First Steps](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/17)
- Classes 101
  - Think of a class like a blueprint for anything
  - Functions within a class are called "methods"
  - The default visibility for a class method is "public", but it is good coding style to declare that explicitly
    - Other visibilities are e.g. "protected" and "private"
  - Instances of classes are called "objects"
  - Class members on objects are accessed with the `->` characters, e.g.:
      ```php
      class Person {
        public $name;
      }

      $person = Person();
      $person->name = 'John Doe';
      ```
  - Within a method (class function), the current object can be accessed using the `$this` keyword/variable
- Remember: The string concatenation character is `.` (a dot)
- Installing and enabling the PDO MySQL driver for the [CLI](/notes/cli) server (assuming PHP 8.1 on Ubuntu 22.04 installed using the [Ondřej Surý PPA](https://launchpad.net/~ondrej/+archive/ubuntu/php)):
    ```shell
    sudo apt install php8.1-mysql
    sudo phpenmod pdo_mysql
    ```
- `phpenmod`, `phpdismod` and `phpquery` are tools for enabling, disabling and viewing the status of PHP modules, they are included in the `php-common` package (on Ubuntu 22.04)
- Creating a MySQL user for the demo/course app:
    ```sql
    CREATE USER 'myapp'@'localhost' IDENTIFIED BY 'SOME_SUPER_SECURE_PASSWORD_GOES_HERE';
    GRANT ALL ON myapp.* TO 'myapp'@'localhost';
    FLUSH PRIVILEGES;
    ```
- For the demo to work, I had to change the `host` in the DSN from "localhost" to "127.0.0.1".
## [18 - Extract a PHP Database Class](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/18)
- The constructor method is called `__construct()` in PHP.
- If the PHP file only contains a class, the convention is to start the file name with a capital letter.
## [19 - Environments and Configuration Flexibility](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/19)
- The "scope resolution operator" `::` gives access to constants ("static values") defined in a class, e.g. we used it when referencing `PDO::FETCH_ASSOC`-
- `http_build_query()` converts an associative array to a querystring
- A PHP file can `return` something - and that return value can be assigned to a variable in another file using the `require` statement
  - Good for e.g. configuration values
## [20 - SQL Injection Vulnerabilities Explained](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/20)
- To avoid SQL injection, substitute any dynamic (user-provided) values in SQL statements with `?` or `:name` placeholders, and bind the actual values by providing them as an array to the `execute()` method
## [21 - Database Tables and Indexes](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/21)
- Unique indices prevent multiple rows from having the same value in the same column (e.g. multiple users having the same email address)
- Foreign keys reference other tables
- `ON UPDATE`/`ON DELETE` configure rules to keep the database integrity intact, e.g. here to automatically delete all of a user's notes when the user gets deleted
## [22 - Render the Notes and Note Page](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/22)
## [23 - Introduction to Authorization](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/23)
- Trying to fetch a non-existing result (no rows) from the database results in the return value `false`
## [24 - Programming is Rewriting](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/24)
## [25 - Intro to Forms and Request Methods](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/25)
- Good coding style / conventions:
  - Start all controllers/views/etc. related to the same "class"/topic with the same expression, e.g.:
  - If one controller relates to one view - call the files the same
  - A plural route ("/notes") should show a list of items of that type
  - A singular route ("/note/ID-SLUG") should show a single note with that ID/slug
- All form input fields should have a corresponding name, which will often be the same as the property/database column
- GET requests should be idempotent (not changing data on the server/database, except request logging obviously)
- POST request data can be accessed using the superglobal `$_POST`
## [26 - Always Escape Untrusted Input](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/26)
- Always assume that the user is guilty (i.e. malicious) until proven otherwise
- `htmlspecialchars()` converts HTML code to plain text (no risk of XSS when displaying it)
## [27 - Intro to Form Validation](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/27)
- Use client-side validation to provide faster feedback to the regular user, but server-side validation to avoid abuse by malicious actors (or users with Javascript disabled for some reason)
- `isset()` can be used to determine if a variable exists (including whether a key exists in an associate array) and is set to something else than `null`
- The "null coalescing operator" `??`, [introduced in PHP 7](https://www.php.net/manual/en/migration70.new-features.php), uses the following value _if_ the preceding one does not exist, e.g. the following snippets are equivalent:
  ```php
  <?= isset($_POST['body']) ? $_POST['body'] : '' ?>
  ```
  ```php
  <?= $_POST['body'] ?? '' ?>
  ```
- `strlen()` returns the length of a string
## [28 - Extract a Simple Validator Class](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/28)
- `trim()` removes whitespace from the beginning and end of a string
- `INF` is a global constant for "infinity", i.e. the largest number
- A "pure function" does not require any state from the outside ("self-contained"; only relying on its input to produce its output)
- Methods which are pure functions can be made "static", which means they can be called directly using the class and the `::` operator, without having to instantiate an object of the class first
- `filter_var()` can e.g. be used for validating that something looks like a valid email address
## [29 - Resourceful Naming Conventions](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/29)
- `__DIR__` gives the directory of the current file
## [30 - PHP Autoloading and Extraction](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/30)
- The path to the project root is often called `BASE_PATH`.
- Constants are declared using the `const` keyword and do _not_ start with a `$` sign.
- `extract()` turns an array into a set of (declared) variables
- `spl_autoload_register()` can be used to autoload classes and avoid the issue of having to require them (and the risk of requiring them twice, resulting in an error about duplicate declaration)
## [31 - Namespacing: What, Why, How?](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/31)
- The `namespace` keyword is used to declare a namespace in PHP
- Namespaces are used to prevent conflicts between classes that have the same name and can be used to organize code by grouping related classes together
- When using a namespaced file, use the `use` keyword to "import" it
- `str_replace()` replaces occurances of strings in strings with other strings
- `DIRECTORY_SEPARATOR` is a global constant that contains the current operating system's directory separator (e.g., `/` or `\`)
- By now it should be obvious that the convention is to name constants with all capital letters 😀
- Every class mentioned in a "namespaced" class is assumed to be in the same namespace
- To reference a class in the "global" namespace (i.e. without a namespace), prefix it with the `\` (backslash) character
- Instead, one can also `use` a class from the global namespace, which also serves as a sort of documentation (answering the question "which other classes are used within this class?")
## [32 - Handle Multiple Request Methods From a Controller Action?](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/32)
- Reminder: GET requests should be idempotent
- Browser forms only support the GET and POST (not PATCH, DELETE, etc.) [HTTP request methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods)
## [33 - Build a Better Router](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/33)
- _For now_, consider PATCH and PUT synonyms
- A `protected` property is not available outside the class
- To simulate DELETE requests using browser forms, it is common to override the intended method using a hidden field `_method`
- The `compact` method takes one or multiple strings and creates an associative array, where the strings are the keys and the values are `$`+string, e.g.
	```php
	$a = "b";
	$b = "c";
	compact('a', 'b');
	// ['a' => 'b', 'b' => 'c']
	```
## [34 - One Request, One Controller](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/34)
- Conventions
	- REST
		- To store something, make a POST request to the plural, e.g. `POST /notes`
		- To delete something, use the HTTP DELETE method, or if that is not feasible (e.g. because of not wanting to depend on [JavaScript](/notes/javascript)), use the HTTP POST method and a hidden form field called e.g. "\_method" that provides the intended HTTP method (e.g. "DELETE")
	- Laravel
		- To store something, call the controller action "store"
		- To delete something, call the controller action "destroy"
- Place the "happy path" (execution without errors) at the bottom of the code
## [35 - # Make Your First Service Container](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/35)
- The purpose of this lesson is to understand the concepts behind service containers. In the real world, a framework like <span class="dead-link">Symphony</span> or [Laravel](/notes/laravel) would provide this functionality.
- "bind" => "add something to the container"
	- Binds a key (string) to a factory function (builder, resolver)
- "resolve" => "get something from the container"
- `call_user_func` is a method that calls a function
- To throw an exception, use the `throw` keyword, e.g.
	```php
	throw new \Exception();
	```
- Static functions can be called without instantiating an object of a class
- A class has a static property `::class` that returns its fully namespaced name
- In addition to the naive container built in this lesson, Laravel service containers support singletons (get the same instance no matter how many times you resolve it) and automatic dependency resolution.
## [36 - Updating With PATCH Requests](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/36)
- Always think about "where could things get out of sync, what could I possibly consolidate (refactor)"
- Laravel conventions for CRUD controller names (with purpose; corresponding HTTP method; and SQL verb)
	- `create` (view create form; GET; N/A)
	- `destroy` (delete; DELETE; DELETE)
	- `edit` (show one, editable; GET; SELECT)
	- `index` (show all; GET; SELECT)
	- `show` (show one, read-only; GET; SELECT)
	- `store` (persist; POST; INSERT)
	- `update` (update existing; PATCH; UPDATE)
## [37 - PHP Sessions 101](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/37)
- Session variables are in `$_SESSION` superglobal
- Sessions are started using `session_start();`
- The default for storing sessions on the server is as files in the temporary directory
## [38 - Register a New User](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/38)
- Write comments before the actual code as a kind of to-do list right in the IDE
- After a redirect, `exit();` the current script
## [39 - Introduction to Middleware](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/39)
- Usually some pages should only be available to authenticated users - and some others only to anonymous users (such as the sign-up page)
- Middleware:
	- Think of middleware as a bridge between the request and the core of the application
	- Used for e.g. authentication
- `array_key_last()` can return the last key in an array
- The syntax `static::member` can be used to refer to static members of the current class
## [40 - Manage Passwords Like This For The Remainder of Your Career](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/40)
- Use `password_hash` to hash a password.
- The current default used by that function is "bcrypt".
## [41 - Log In and Log Out](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/41)
- The method `password_verify()` can be used to verify that a provided password matches a password hashed by `password_hash()`.
- A request to logout destroys (session) data on the server and should therefore use the DELETE HTTP method.
- `session_destroy()` destroys the session data on the server.
- `setcookie()` can be used to set a cookie, which includes deleting an existing cookie (by using the same name and setting an expiry time in the past).
- `session_get_cookie_params()` returns the values (path, domain, etc.) used for the session cookie (necessary when deleting it using `setcookie()`).
- When logging a user in, regenerate the session ID for security purposes using `session_regenerate_id(true);`.
## [42 - Extract a Form Validation Object](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/42)
- Separate code specific to the application from "core infrastructure" code (different folders and namespaces)
- `empty()` returns a boolean about whether the argument (array, etc.) is empty
## [43 - Extract an Authenticator Class](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/43)
- It is the controller's responsibility to return a view (don't put such code in utility classes).
- > 75% of programming is reading.
  \- <span class="dead-link">Jeffrey Way</span>
- When instantiating an object without passing constructor arguments, the parentheses after the class name are optional.
## [44 - The PRG Pattern (and Session Flashing)](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/44)
- "POST -> redirect -> GET" avoids the issue where the user navigates backwards and the browser asks whether they want to resubmit the form.
- `unset()` destroys a variable.
- "Flashing" means keeping data in the session for a short time, usually destroying it after the following request.
## [45 - Flash Old Form Data to the Session](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/45)
- `old` is conventionally used as a name for the session key that stores old form data for use after a redirect.
## [46 - Automatically Redirect Back Upon Failed Validation](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/46)
- In a static method, the keyword `static` refers to the class.
- The keyword `extends` is used to inherit from a parent `class`. (Also, `implements` indicates that a class implements an `interface`.)
- Exceptions can be thrown with the `throw` statement and caught with `try`/`catch`.
- In PHP 8, by prefixing the constructor's arguments with a visibility (e.g. `public`/`protected`), they no longer need to be assigned to instance attributes manually (see [Constructor Property Promotion](https://wiki.php.net/rfc/constructor_promotion)):
	```php
	public function __construct(public array $attributes)
	{
		// ...
	}
	```
- The `readonly` keyword means that a variable can only be assigned to once.
- Delegate instead of micromanaging (move functionality out of the controller)
## [47 - Composer and Free Autoloading](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/47)
- [Composer](/notes/composer) is a dependency manager *and* autoloader, so we can forget about `spl_autoload_register` 🤗
- "PSR" => "PHP Standard Recommendation"
- "PSR-4" => a spec for autoloading
- `composer init` to generate `composer.json` using a wizard (similar to how `npm i` generates `package.json`)
- `composer dump-autoload` to generate autoload files
- In `composer.json`->`autoload`->`psr-4`:
	- The key (namespace) needs to end with a namespace separator (backslash) (escaped in JSON using another backslash)
	- The value (folder path) needs to end with a folder separator (forward slash)
	- Only the top-level namespaces need to be mapped
## [48 - Install Two Composer Packages: Collections and PestPHP](https://laracasts.com/series/php-for-beginners-2023-edition/episodes/48)
- Ways to search for packages
	- [Packagist.org](https://packagist.org/) - ordered by popularity (number of downloads)
	- `composer search KEYWORD`
- [Collections](https://github.com/illuminate/collections) = like arrays, but with extra functions
- `composer require` to install packages and persist them in the source-controlled `composer.json` (and [`composer.lock`](https://stackoverflow.com/questions/10674641/composer-lock-how-does-it-work))
- `composer require --dev` for packages that are not used in production (but only during development/testing)
- Recommended unit test runner: [Pest](https://pestphp.com/)
- Test files should end with the suffix "Test"(.php)
- > [Arrow functions](https://www.php.net/manual/en/functions.arrow.php) were introduced in PHP 7.4 as a more concise syntax for [anonymous functions](https://www.php.net/manual/en/functions.anonymous.php).
- Unit tests allow us to refactor with more confidence that things will still work as `expect`ed.