Modern PHP: Difference between revisions
(18 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
== Composer == | |||
You should commit <code>composer.json</code> and <code>composer.lock</code> into version control. | |||
<code>composer install</code> will install the exact versions specified in <code>composer.lock</code>. This ensures that all developers working on the same project are using the same versions. <code>composer update</code> will update all installed packages to their latest versions and update the <code>composer.lock</code> file. | |||
<code>composer init</code> will start a new project. | |||
You can require a given version of PHP with: | |||
"require": { | |||
"php": "7.1.*" | |||
} | |||
You can restrict Composer to a maximum version of PHP with: | |||
"config": { | |||
"platform": { | |||
"php": "5.6.35" | |||
} | |||
} | |||
This can be useful if you are running Composer on a different platform to the one you deploy on (ideally development/local should match production but in real life this is often not the case). | |||
== Project directory structure == | |||
In the root directory: | |||
* <code>src</code> - PHP source code (classes). | |||
* <code>tests</code> - PHPUnit tests. | |||
* <code>composer.json</code> - Composer dependencies and configuration. | |||
* <code>phpunit.xml</code> - PHPUnit configuration. | |||
* <code>.travis.yml</code> - Continuous integration configuration. | |||
* <code>public</code> - Public files such as CSS, JavaScript etc. | |||
== Testing == | |||
The standard tool for testing PHP is PHPUnit. It can be installed with the following command: | |||
composer require --dev phpunit/phpunit | |||
The <code>--dev</code> flag ensures that PHPUnit is installed as a development dependency, because you don't want to run it in production (doing so would be a bad idea from a security perspective). | |||
== Strict typing == | |||
By default, PHP attempts to cast/coerce the data passed to a function into the type required. For example, if a function expects a string and you pass an integer, PHP will cast the integer to a string (e.g. 10 becomes '10'). Most of the time this doesn't present any problems, and it can make life easier to begin with when developing web applications (e.g. the contents of <code>$_GET</code> and <code>$_POST</code> are usually strings, so it saves you have to explicitly cast these to other types). | |||
However, occasionally this automatic casting can cause subtle bugs. To prevent this, you can enable strict typing by including the following line at the top of every PHP file: | |||
declare(strict_types=1); | |||
Unfortunately this line has to be added to every file in order to have full effect. Strict typing cannot be enabled by configuration options in <code>php.ini</code>, and it is not the same as <code>E_STRICT</code>. | |||
== Generators == | == Generators == | ||
Line 11: | Line 64: | ||
Generators are forward-only iterators, i.e. you can only request the next value, not the previous, next but one etc. They are useful for iterating sequential data sets such as reading a file line by line (in order). | Generators are forward-only iterators, i.e. you can only request the next value, not the previous, next but one etc. They are useful for iterating sequential data sets such as reading a file line by line (in order). | ||
== Traits == | |||
Traits are a mix of classes and interfaces. If a class uses a trait, it receives all the methods of that trait (including implementations, unlike with interfaces where the implementation must be provided by each class). | |||
== Autoloading == | |||
The original mechanism for autoloading was the magic function <code>__autoload()</code>. This is no longer recommended and is deprecated in PHP 7.x. | |||
The successor to <code>__autoload()</code> is <code>spl_autoload_register()</code>. This in turn has been replaced by PSR-0, then PSR-4. Composer will generate a PSR-4 autoloader for you, though you will still need to map the directories to namespaces (e.g. <code>src</code> to <code>MyApp\\</code>). You may need to use <code>spl_autoload_register()</code> as an intermediate step to transition to PSR-4. | |||
== Built-in web server == | == Built-in web server == | ||
Line 20: | Line 83: | ||
== Useful dependencies == | == Useful dependencies == | ||
* [https://github.com/nikic/FastRoute FastRoute] | * [https://github.com/nikic/FastRoute FastRoute] - seems to be the most popular routing library by far | ||
* <code>aura/router</code> or <code>league/route</code> | * <code>aura/router</code> or <code>league/route</code> | ||
* <code>aura/filter</code>, <code>respect/validation</code>, <code>symfony/validator</code> | |||
* <code>mbstring</code> extension, provides <code>mb_</code> functions such as <code>mb_strlen</code> | |||
* <code>filp/whoops</code> - pretty printing of exceptions and errors | |||
* <code>monolog/monolog</code> | |||
* <code>php-di/php-di</code> | |||
== Links == | == Links == | ||
Line 27: | Line 95: | ||
* [https://kevinsmith.io/modern-php-without-a-framework Modern PHP Without a Framework] | * [https://kevinsmith.io/modern-php-without-a-framework Modern PHP Without a Framework] | ||
* [https://kevinsmith.io/didnt-you-just-build-your-own-framework Didn't you just build your own framework?] | * [https://kevinsmith.io/didnt-you-just-build-your-own-framework Didn't you just build your own framework?] | ||
* [https://phpdelusions.net/pdo (The only proper) PDO tutorial] | |||
[[Category:PHP]] | [[Category:PHP]] |
Latest revision as of 11:58, 15 October 2021
Composer
You should commit composer.json
and composer.lock
into version control.
composer install
will install the exact versions specified in composer.lock
. This ensures that all developers working on the same project are using the same versions. composer update
will update all installed packages to their latest versions and update the composer.lock
file.
composer init
will start a new project.
You can require a given version of PHP with:
"require": { "php": "7.1.*" }
You can restrict Composer to a maximum version of PHP with:
"config": { "platform": { "php": "5.6.35" } }
This can be useful if you are running Composer on a different platform to the one you deploy on (ideally development/local should match production but in real life this is often not the case).
Project directory structure
In the root directory:
src
- PHP source code (classes).tests
- PHPUnit tests.composer.json
- Composer dependencies and configuration.phpunit.xml
- PHPUnit configuration..travis.yml
- Continuous integration configuration.public
- Public files such as CSS, JavaScript etc.
Testing
The standard tool for testing PHP is PHPUnit. It can be installed with the following command:
composer require --dev phpunit/phpunit
The --dev
flag ensures that PHPUnit is installed as a development dependency, because you don't want to run it in production (doing so would be a bad idea from a security perspective).
Strict typing
By default, PHP attempts to cast/coerce the data passed to a function into the type required. For example, if a function expects a string and you pass an integer, PHP will cast the integer to a string (e.g. 10 becomes '10'). Most of the time this doesn't present any problems, and it can make life easier to begin with when developing web applications (e.g. the contents of $_GET
and $_POST
are usually strings, so it saves you have to explicitly cast these to other types).
However, occasionally this automatic casting can cause subtle bugs. To prevent this, you can enable strict typing by including the following line at the top of every PHP file:
declare(strict_types=1);
Unfortunately this line has to be added to every file in order to have full effect. Strict typing cannot be enabled by configuration options in php.ini
, and it is not the same as E_STRICT
.
Generators
Generators are similar to iterators that calculate their values on demand, thus potentially using fewer resources. They can be created using the yield
keyword, e.g.:
function my_generator() { yield 1; yield 2; yield 3; }
Generators are forward-only iterators, i.e. you can only request the next value, not the previous, next but one etc. They are useful for iterating sequential data sets such as reading a file line by line (in order).
Traits
Traits are a mix of classes and interfaces. If a class uses a trait, it receives all the methods of that trait (including implementations, unlike with interfaces where the implementation must be provided by each class).
Autoloading
The original mechanism for autoloading was the magic function __autoload()
. This is no longer recommended and is deprecated in PHP 7.x.
The successor to __autoload()
is spl_autoload_register()
. This in turn has been replaced by PSR-0, then PSR-4. Composer will generate a PSR-4 autoloader for you, though you will still need to map the directories to namespaces (e.g. src
to MyApp\\
). You may need to use spl_autoload_register()
as an intermediate step to transition to PSR-4.
Built-in web server
PHP comes with a built-in web server which is useful for development purposes, although it should never be used in production.
- Configuration directives:
-c config/php.ini
Useful dependencies
- FastRoute - seems to be the most popular routing library by far
aura/router
orleague/route
aura/filter
,respect/validation
,symfony/validator
mbstring
extension, providesmb_
functions such asmb_strlen
filp/whoops
- pretty printing of exceptions and errorsmonolog/monolog
php-di/php-di