Standards in
PHP world
About me
Michael Morozov
PHP-developer @ Binary Studio
Coach @ Binary Studio Academy
World Of Tanks Standards
Standards in PHP
➔ RFC (Requests For Comments)
➔ PSR (PHP Standard Recommendations)
RFC Lifecycle
Internet
Draft
Proposed
Draft
Draft
Standard
Internet
Standard
What about PSR?
PHP Standard Recommendations
➔ Set of conventions aimed to improve collaboration
between different projects in PHP-ecosystem
➔ Established and maintained by
https://github.com/php-fig/fig-standards
PSRs Classification
➔ Accepted
➔ Review
➔ Draft
➔ Deprecated
Deprecated PSR-0
➔ Autoloading Standard
➔ Provided SplClassLoader implementation which is able to load PHP 5.3
classes
'ZendMailMessage' =>
'/path/to/project/lib/vendor/Zend/Mail/Message.php',
'Zend_Config_Json' =>
'/path/to/project/lib/vendor/Zend/Config/Json.php'
Accepted PSRs
Accepted PSR-d+
➔ PSR-1: Basic Coding Standard
➔ PSR-2: Coding Style Guide
➔ PSR-3: Logger Interface
➔ PSR-4: Autoloading Standard
➔ PSR-6: Caching Interface
➔ PSR-7: HTTP Message Interface
Coding
Style
Code Style Holy Wars. Indentation
Code Style Holy Wars. Case
Code Style Holy Wars. Line Feeds
n or r or rn
Code Style Holy Wars. Right margin
80? 120?
3 screens?
80? 120?
Code Style Holy Wars. Eto translit, detka
$koli4estvo = 10;
$privet = 'Medved';
$Beschleunigung = 9.8;
PSR-1 & PSR-2 Intention
Reduce the cognitive friction when reading code
from other authors by standardized formatting.”
Coding Style Tools
➔ Ourselves
➔ PHP-CS-Fixer (https://github.com/FriendsOfPHP/PHP-CS-Fixer)
➔ PHP_CodeSniffer (https://github.com/squizlabs/PHP_CodeSniffer)
➔ PHP Mess Detector (https://phpmd.org/)
➔ phpcf (https://github.com/badoo/phpcf)
➔ StyleCI (https://styleci.io/)
➔ Our own implementation
PHP-CS-Fixer
➔ CLI utility
➔ Easy to integrate with code editor or CI
➔ Default fixers preset (psr1, psr2, symfony)
➔ Dry-run
➔ Extendability
How about to refine this ?
<?php namespace Submit; class DirtyClass {
private $privacy; protected $data;
public function __construct() {} public function getPrivacy()
{ return $this->privacy;}
}
OK, Let’s run:
$ php php-cs-fixer.phar fix /path/to/dir
<?php namespace Submit;
class FixMe
{
private $privacy;
protected $data;
public function __construct()
{
}
public function getPrivacy()
{
return $this->privacy;
}
}
PHP-CS-Fixer
Custom config
(.php_cs)
$finder = SymfonyCSFinderDefaultFinder::create()
->in('src')
->notPath('tests');
$config = SymfonyCSConfigConfig::create();
$config->level(null);
$config->fixers(
array(
'line_after_namespace',
'linefeed',
'php_closing_tag',
'short_array_syntax',
'unused_use'
)
);
$config->finder($finder);
return $config;
PHP-CS-Fixer as a separate CI ?
https://styleci.io/
What about legacy?
Code style in legacy code
➔ Skip vendor and legacy libs in code style tools
➔ Request single codebase re-formatting
➔ Force every team member using the same style
PSR-3: The “Right” Logging
PSR-3 Logger Interface
namespace PsrLog;
interface LoggerInterface
{
public function emergency($message, array $context = array());
public function alert($message, array $context = array());
public function critical($message, array $context = array());
public function error($message, array $context = array());
public function warning($message, array $context = array());
public function notice($message, array $context = array());
public function info($message, array $context = array());
public function debug($message, array $context = array());
public function log($level, $message, array $context = array());
}
Log All The Things with Monolog
$ composer require monolog/monolog
➔ Fully PSR-3 Compatible
➔ Write to files, sockets, chats, databases, web-services, mails
➔ Customize log format
➔ 42.3 M downloads. Just give it a try.
Monolog
Example
$bindings = [
'slack.handler' => function($app) {
return new MonologHandlerSlackHandler(
getenv('SLACK_TOKEN'),
getenv('SLACK_ROOM')
);
},
'slack.logger' => function($app) {
return new MonologLogger('slack', [$app['slack.handler']]);
}
];
$container = new PimpleContainer($bindings);
$container['slack.logger']->info('Hey, guys!');
$container['slack.logger']->emergency('Website is down!');
PSR-3 Based Loggers
➔ Monolog (https://github.com/Seldaek/monolog)
➔ zend-log (https://github.com/zendframework/zend-log)
➔ KLogger (https://github.com/katzgrau/klogger)
➔ Your logger implementation
➔ Oh, cmon. Just use Monolog
PSR-4 Auto
PSR-4 Autoloading
➔ Autoloading takes care about classes with fully-qualified class names
(FQCN)
➔ Classes, interfaces, traits considers as “class” (FooInterface::class)
<NamespaceName>(<SubNamespaceNames>)*<ClassName>
FQCN Namespace
prefix
Base directory Resulting file path
SymfonyCoreRequest SymfonyCore ./vendor/Symfony/Core/ ./vendor/Symfony/Core/Request.php
AuraWebResponseStatus AuraWeb /path/to/aura-web/src/ /path/to/aura-web/src/Response/Status.php
PSR-4 Autoloading via Composer
{
"autoload": {
"psr-4": {
"Monolog": "src/",
"VendorNamespace": ""
}
}
}
{
"autoload": {
"psr-4": { "": "src/" }
}
}
HTTP
Message
Interface
PSR-7 Main Concept
HTTP Requests and Responses
are abstracted in form of HTTP
messages
PSR-7 Interfaces schema
PSR-7 Component features
➔ Request, ServerRequest, Response, Uri are immutable
➔ Response Body is stream (like php://temp)
PSR-7 Known Implementations
➔ guzzlehttp/psr7 (https://packagist.org/packages/guzzlehttp/psr7)
➔ slim/http (https://packagist.org/packages/slim/http)
➔ zendframework/diactorous
(https://packagist.org/packages/zendframework/zend-diactoros)
➔ wandu/http (https://packagist.org/packages/wandu/http)
➔ symfony/psr-http-message-bridge
(https://packagist.org/packages/symfony/psr-http-message-bridge)
➔ zendframework/zend-psr7-bridge
(https://packagist.org/packages/zendframework/zend-psr7bridge)
PSR-7 examples
$app = new SlimApp;
$app->get('/foo', function ($req, $res, $args) {
return $res->withHeader(
'Content-Type',
'application/json'
);
});
$app->run();
PSR-7 examples
$response = new ZendDiactorosResponse();
$response->getBody()->write("Hellon");
$response->getBody()->write("worldn");
$response = $response
->withHeader('Content-Type', 'text/plain')
->withAddedHeader('X-Show-Something', 'something');
Caching with PSR-6
PSR-6: Caching interface
CacheItemPool
CacheItem
Caching examples using Stash (tedivm/stash)
$driver = new StashDriverFileSystem();
$pool = new StashPool($driver);
$item = $pool->getItem('path/to/data');
$info = $item->get();
if ($item->isMiss()) {
$info = loadInfo($id);
$item->set($userInfo, 120);
}
return $info;
Cache implementations
https://packagist.org/providers/psr/cache-implementation
Interesting Draft
PSRs
Draft PSRs
➔ PSR-12: Extended Coding Style Guide
➔ PSR-14: Event Manager
➔ PSR-15: HTTP Middlewares
Current Stage and Future of PHP-FIG
➔ Some members complained that they are forced to use or support
PSRs in their projects
➔ As a results they would like to have some “re-branding”
➔ This led to PHP Community-driven Standards and HTTP Interop
appearing
Summary
➔ Following coding standards disciplines & improves readability
➔ Sometimes usage of “code-smell” tools is beneficial and not routine
➔ Autoloading via Composer nowadays rocks
➔ There are some well-grounded techniques that can be a problem solution
(logging, caching, containers, etc.)
➔ Having abstraction layer in HTTP is more convenient than raw access to
superglobals
➔ PHP becomes more mature and more standardized
Questions ?
Thanks for
watching

Submit PHP: Standards in PHP world. Михайло Морозов

  • 1.
  • 2.
    About me Michael Morozov PHP-developer@ Binary Studio Coach @ Binary Studio Academy
  • 4.
    World Of TanksStandards
  • 5.
    Standards in PHP ➔RFC (Requests For Comments) ➔ PSR (PHP Standard Recommendations)
  • 6.
  • 7.
  • 8.
    PHP Standard Recommendations ➔Set of conventions aimed to improve collaboration between different projects in PHP-ecosystem ➔ Established and maintained by https://github.com/php-fig/fig-standards
  • 9.
    PSRs Classification ➔ Accepted ➔Review ➔ Draft ➔ Deprecated
  • 10.
    Deprecated PSR-0 ➔ AutoloadingStandard ➔ Provided SplClassLoader implementation which is able to load PHP 5.3 classes 'ZendMailMessage' => '/path/to/project/lib/vendor/Zend/Mail/Message.php', 'Zend_Config_Json' => '/path/to/project/lib/vendor/Zend/Config/Json.php'
  • 11.
  • 12.
    Accepted PSR-d+ ➔ PSR-1:Basic Coding Standard ➔ PSR-2: Coding Style Guide ➔ PSR-3: Logger Interface ➔ PSR-4: Autoloading Standard ➔ PSR-6: Caching Interface ➔ PSR-7: HTTP Message Interface
  • 13.
  • 15.
    Code Style HolyWars. Indentation
  • 16.
    Code Style HolyWars. Case
  • 17.
    Code Style HolyWars. Line Feeds n or r or rn
  • 18.
    Code Style HolyWars. Right margin 80? 120? 3 screens? 80? 120?
  • 19.
    Code Style HolyWars. Eto translit, detka $koli4estvo = 10; $privet = 'Medved'; $Beschleunigung = 9.8;
  • 20.
    PSR-1 & PSR-2Intention Reduce the cognitive friction when reading code from other authors by standardized formatting.”
  • 21.
    Coding Style Tools ➔Ourselves ➔ PHP-CS-Fixer (https://github.com/FriendsOfPHP/PHP-CS-Fixer) ➔ PHP_CodeSniffer (https://github.com/squizlabs/PHP_CodeSniffer) ➔ PHP Mess Detector (https://phpmd.org/) ➔ phpcf (https://github.com/badoo/phpcf) ➔ StyleCI (https://styleci.io/) ➔ Our own implementation
  • 22.
    PHP-CS-Fixer ➔ CLI utility ➔Easy to integrate with code editor or CI ➔ Default fixers preset (psr1, psr2, symfony) ➔ Dry-run ➔ Extendability
  • 23.
    How about torefine this ? <?php namespace Submit; class DirtyClass { private $privacy; protected $data; public function __construct() {} public function getPrivacy() { return $this->privacy;} } OK, Let’s run: $ php php-cs-fixer.phar fix /path/to/dir
  • 24.
    <?php namespace Submit; classFixMe { private $privacy; protected $data; public function __construct() { } public function getPrivacy() { return $this->privacy; } }
  • 25.
    PHP-CS-Fixer Custom config (.php_cs) $finder =SymfonyCSFinderDefaultFinder::create() ->in('src') ->notPath('tests'); $config = SymfonyCSConfigConfig::create(); $config->level(null); $config->fixers( array( 'line_after_namespace', 'linefeed', 'php_closing_tag', 'short_array_syntax', 'unused_use' ) ); $config->finder($finder); return $config;
  • 26.
    PHP-CS-Fixer as aseparate CI ? https://styleci.io/
  • 27.
  • 28.
    Code style inlegacy code ➔ Skip vendor and legacy libs in code style tools ➔ Request single codebase re-formatting ➔ Force every team member using the same style
  • 29.
  • 30.
    PSR-3 Logger Interface namespacePsrLog; interface LoggerInterface { public function emergency($message, array $context = array()); public function alert($message, array $context = array()); public function critical($message, array $context = array()); public function error($message, array $context = array()); public function warning($message, array $context = array()); public function notice($message, array $context = array()); public function info($message, array $context = array()); public function debug($message, array $context = array()); public function log($level, $message, array $context = array()); }
  • 31.
    Log All TheThings with Monolog $ composer require monolog/monolog ➔ Fully PSR-3 Compatible ➔ Write to files, sockets, chats, databases, web-services, mails ➔ Customize log format ➔ 42.3 M downloads. Just give it a try.
  • 32.
    Monolog Example $bindings = [ 'slack.handler'=> function($app) { return new MonologHandlerSlackHandler( getenv('SLACK_TOKEN'), getenv('SLACK_ROOM') ); }, 'slack.logger' => function($app) { return new MonologLogger('slack', [$app['slack.handler']]); } ]; $container = new PimpleContainer($bindings); $container['slack.logger']->info('Hey, guys!'); $container['slack.logger']->emergency('Website is down!');
  • 33.
    PSR-3 Based Loggers ➔Monolog (https://github.com/Seldaek/monolog) ➔ zend-log (https://github.com/zendframework/zend-log) ➔ KLogger (https://github.com/katzgrau/klogger) ➔ Your logger implementation ➔ Oh, cmon. Just use Monolog
  • 34.
  • 35.
    PSR-4 Autoloading ➔ Autoloadingtakes care about classes with fully-qualified class names (FQCN) ➔ Classes, interfaces, traits considers as “class” (FooInterface::class) <NamespaceName>(<SubNamespaceNames>)*<ClassName> FQCN Namespace prefix Base directory Resulting file path SymfonyCoreRequest SymfonyCore ./vendor/Symfony/Core/ ./vendor/Symfony/Core/Request.php AuraWebResponseStatus AuraWeb /path/to/aura-web/src/ /path/to/aura-web/src/Response/Status.php
  • 36.
    PSR-4 Autoloading viaComposer { "autoload": { "psr-4": { "Monolog": "src/", "VendorNamespace": "" } } } { "autoload": { "psr-4": { "": "src/" } } }
  • 37.
  • 38.
    PSR-7 Main Concept HTTPRequests and Responses are abstracted in form of HTTP messages
  • 39.
  • 40.
    PSR-7 Component features ➔Request, ServerRequest, Response, Uri are immutable ➔ Response Body is stream (like php://temp)
  • 41.
    PSR-7 Known Implementations ➔guzzlehttp/psr7 (https://packagist.org/packages/guzzlehttp/psr7) ➔ slim/http (https://packagist.org/packages/slim/http) ➔ zendframework/diactorous (https://packagist.org/packages/zendframework/zend-diactoros) ➔ wandu/http (https://packagist.org/packages/wandu/http) ➔ symfony/psr-http-message-bridge (https://packagist.org/packages/symfony/psr-http-message-bridge) ➔ zendframework/zend-psr7-bridge (https://packagist.org/packages/zendframework/zend-psr7bridge)
  • 42.
    PSR-7 examples $app =new SlimApp; $app->get('/foo', function ($req, $res, $args) { return $res->withHeader( 'Content-Type', 'application/json' ); }); $app->run();
  • 43.
    PSR-7 examples $response =new ZendDiactorosResponse(); $response->getBody()->write("Hellon"); $response->getBody()->write("worldn"); $response = $response ->withHeader('Content-Type', 'text/plain') ->withAddedHeader('X-Show-Something', 'something');
  • 44.
  • 46.
  • 47.
    Caching examples usingStash (tedivm/stash) $driver = new StashDriverFileSystem(); $pool = new StashPool($driver); $item = $pool->getItem('path/to/data'); $info = $item->get(); if ($item->isMiss()) { $info = loadInfo($id); $item->set($userInfo, 120); } return $info;
  • 48.
  • 49.
  • 50.
    Draft PSRs ➔ PSR-12:Extended Coding Style Guide ➔ PSR-14: Event Manager ➔ PSR-15: HTTP Middlewares
  • 51.
    Current Stage andFuture of PHP-FIG ➔ Some members complained that they are forced to use or support PSRs in their projects ➔ As a results they would like to have some “re-branding” ➔ This led to PHP Community-driven Standards and HTTP Interop appearing
  • 52.
    Summary ➔ Following codingstandards disciplines & improves readability ➔ Sometimes usage of “code-smell” tools is beneficial and not routine ➔ Autoloading via Composer nowadays rocks ➔ There are some well-grounded techniques that can be a problem solution (logging, caching, containers, etc.) ➔ Having abstraction layer in HTTP is more convenient than raw access to superglobals ➔ PHP becomes more mature and more standardized
  • 53.
  • 54.