PHP For Beginners
https://laracasts.com/series/php-for-beginners-2023-edition
Laracasts > Learn Laravel Path > PHP For Beginners
- Recommended editors
- PhpStorm
- Visual Studio Code
- PHP extension
All-in-One PHP support - IntelliSense, Debug, Formatter, Code Lenses, Code Fixes, Linting, Refactoring, PHPUnit Tests, Web Server, and more.
- PHP extension
- Sublime Text
- Terminals
- macOS
- Windows
- Ways of installing PHP
- Database clients
- TablePlus
- phpMyAdmin (MySQL only)
<?php echo "Hello world"; ?>- 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
- Conditions:
Alternative syntax withif (condition) {/* ... */}else {/* ... */}
:andendif:if (condition):/* ... */else:/* ... */endif; <?=is shorthand for<?php echoand the semicolon is optional in this case
- Arrays are declared like
[/* … */] - Loop:
Alternative syntax withforeach ($var as $i) {/* ... do something with $i ... */}
:andendforeach, often used in views: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 echo "{$i}©"; ?>
- Array indices start at zero
- Arrays can be indexed:
$books[2]
- Arrays can be nested
- Associative arrays are indexed by key instead of numbers:
$book = ['name' => 'Do Androids Dream of Electric Sheep','author' => 'Philip K. Dick'];echo $book['name'];
=assigns a value==compares equality of value===compares equality of value and type- Function definition and parameters:
function filterByAuthor($books) {// ...}
- Returning data from a function:
return 'foo';
[] =appends a value to an array:$filteredBooks = [];$filteredBooks[] = $book;
- “Lambda functions” is the technical term for “anonymous functions”, i.e. functions that are not named (
function foo(a) { }, calledfoo(b)), but may still be assigned to variables ($foo = function (a) { };, called$foo(b);). array_filteris one of many useful functions included with PHP.
- 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
requireorinclude
- How not to do things: duplication of code
- Controllers are responsible for accepting and processing an incoming request and providing a response
14 - Superglobals and Current Page Styling
Section titled “14 - Superglobals and Current Page Styling”var_dumpconverts 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 : elseas a shorthand for if/else
- 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 keyhttp_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.:
function foo($var = 12345) { /* ... */ }Install MySQL 8.0 on Ubuntu 22.04 running in WSL:
sudo apt install -y mysql-server-8.0sudo /etc/init.d/mysql startCreate a database for this course:
sudo mysql -e "CREATE DATABASE myapp;"- 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.:class Person {public $name;}$person = Person();$person->name = 'John Doe'; - Within a method (class function), the current object can be accessed using the
$thiskeyword/variable
- Remember: The string concatenation character is
.(a dot) - Installing and enabling the PDO MySQL driver for the CLI server (assuming PHP 8.1 on Ubuntu 22.04 installed using the Ondřej Surý PPA):
Terminal window sudo apt install php8.1-mysqlsudo phpenmod pdo_mysql phpenmod,phpdismodandphpqueryare tools for enabling, disabling and viewing the status of PHP modules, they are included in thephp-commonpackage (on Ubuntu 22.04)- Creating a MySQL user for the demo/course app:
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
hostin the DSN from “localhost” to “127.0.0.1”.
- 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
Section titled “19 - Environments and Configuration Flexibility”- The “scope resolution operator”
::gives access to constants (“static values”) defined in a class, e.g. we used it when referencingPDO::FETCH_ASSOC- http_build_query()converts an associative array to a querystring- A PHP file can
returnsomething - and that return value can be assigned to a variable in another file using therequirestatement- Good for e.g. configuration values
20 - SQL Injection Vulnerabilities Explained
Section titled “20 - SQL Injection Vulnerabilities Explained”- To avoid SQL injection, substitute any dynamic (user-provided) values in SQL statements with
?or:nameplaceholders, and bind the actual values by providing them as an array to theexecute()method
- 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 DELETEconfigure rules to keep the database integrity intact, e.g. here to automatically delete all of a user’s notes when the user gets deleted
- Trying to fetch a non-existing result (no rows) from the database results in the return value
false
- 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
- 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)
- 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 thannull- The “null coalescing operator”
??, introduced in PHP 7, uses the following value if the preceding one does not exist, e.g. the following snippets are equivalent:<?= isset($_POST['body']) ? $_POST['body'] : '' ?><?= $_POST['body'] ?? '' ?> strlen()returns the length of a string
trim()removes whitespace from the beginning and end of a stringINFis 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
__DIR__gives the directory of the current file
- The path to the project root is often called
BASE_PATH. - Constants are declared using the
constkeyword and do not start with a$sign. extract()turns an array into a set of (declared) variablesspl_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)
- The
namespacekeyword 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
usekeyword to “import” it str_replace()replaces occurances of strings in strings with other stringsDIRECTORY_SEPARATORis 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
usea 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?
Section titled “32 - Handle Multiple Request Methods From a Controller Action?”- Reminder: GET requests should be idempotent
- Browser forms only support the GET and POST (not PATCH, DELETE, etc.) HTTP request methods
- For now, consider PATCH and PUT synonyms
- A
protectedproperty 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
compactmethod takes one or multiple strings and creates an associative array, where the strings are the keys and the values are$+string, e.g.$a = "b";$b = "c";compact('a', 'b');// ['a' => 'b', 'b' => 'c']
- 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), use the HTTP POST method and a hidden form field called e.g. “_method” that provides the intended HTTP method (e.g. “DELETE”)
- To store something, make a POST request to the plural, e.g.
- Laravel
- To store something, call the controller action “store”
- To delete something, call the controller action “destroy”
- REST
- Place the “happy path” (execution without errors) at the bottom of the code
- The purpose of this lesson is to understand the concepts behind service containers. In the real world, a framework like Symphony or 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_funcis a method that calls a function- To throw an exception, use the
throwkeyword, e.g.throw new \Exception(); - Static functions can be called without instantiating an object of a class
- A class has a static property
::classthat 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.
- 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)
- Session variables are in
$_SESSIONsuperglobal - Sessions are started using
session_start(); - The default for storing sessions on the server is as files in the temporary directory
- Write comments before the actual code as a kind of to-do list right in the IDE
- After a redirect,
exit();the current script
- 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::membercan be used to refer to static members of the current class
40 - Manage Passwords Like This For The Remainder of Your Career
Section titled “40 - Manage Passwords Like This For The Remainder of Your Career”- Use
password_hashto hash a password. - The current default used by that function is “bcrypt”.
- The method
password_verify()can be used to verify that a provided password matches a password hashed bypassword_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 usingsetcookie()).- When logging a user in, regenerate the session ID for security purposes using
session_regenerate_id(true);.
- 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
- It is the controller’s responsibility to return a view (don’t put such code in utility classes).
-
75% of programming is reading. - Jeffrey Way
- When instantiating an object without passing constructor arguments, the parentheses after the class name are optional.
44 - The PRG Pattern (and Session Flashing)
Section titled “44 - The PRG Pattern (and Session Flashing)”- “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.
oldis 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
Section titled “46 - Automatically Redirect Back Upon Failed Validation”- In a static method, the keyword
staticrefers to the class. - The keyword
extendsis used to inherit from a parentclass. (Also,implementsindicates that a class implements aninterface.) - Exceptions can be thrown with the
throwstatement and caught withtry/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):public function __construct(public array $attributes){// ...} - The
readonlykeyword means that a variable can only be assigned to once. - Delegate instead of micromanaging (move functionality out of the controller)
- 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 initto generatecomposer.jsonusing a wizard (similar to hownpm igeneratespackage.json)composer dump-autoloadto 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
Section titled “48 - Install Two Composer Packages: Collections and PestPHP”- Ways to search for packages
- Packagist.org - ordered by popularity (number of downloads)
composer search KEYWORD
- Collections = like arrays, but with extra functions
composer requireto install packages and persist them in the source-controlledcomposer.json(andcomposer.lock)composer require --devfor packages that are not used in production (but only during development/testing)- Recommended unit test runner: Pest
- Test files should end with the suffix “Test”(.php)
-
Arrow functions were introduced in PHP 7.4 as a more concise syntax for anonymous functions.
- Unit tests allow us to refactor with more confidence that things will still work as
expected.