submit php: standards in php world. Михайло Морозов
TRANSCRIPT
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
Deprecated PSR-0
➔ Autoloading Standard
➔ Provided SplClassLoader implementation which is able to load PHP 5.3
classes
'\Zend\Mail\Message' =>
'/path/to/project/lib/vendor/Zend/Mail/Message.php',
'\Zend_Config_Json' =>
'/path/to/project/lib/vendor/Zend/Config/Json.php'
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
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-FixerCustom config (.php_cs)
$finder = Symfony\CS\Finder\DefaultFinder::create()
->in('src')
->notPath('tests');
$config = Symfony\CS\Config\Config::create();
$config->level(null);
$config->fixers(
array(
'line_after_namespace',
'linefeed',
'php_closing_tag',
'short_array_syntax',
'unused_use'
)
);
$config->finder($finder);
return $config;
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 Logger Interfacenamespace Psr\Log;
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 \Monolog\Handler\SlackHandler(
getenv('SLACK_TOKEN'),
getenv('SLACK_ROOM')
);
},
'slack.logger' => function($app) {
return new Monolog\Logger('slack', [$app['slack.handler']]);
}
];
$container = new \Pimple\Container($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 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
\Symfony\Core\Request Symfony\Core ./vendor/Symfony/Core/ ./vendor/Symfony/Core/Request.php
\Aura\Web\Response\Status Aura\Web /path/to/aura-web/src/ /path/to/aura-web/src/Response/Status.php
PSR-4 Autoloading via Composer
{
"autoload": {
"psr-4": {
"Monolog\\": "src/",
"Vendor\\Namespace\\": ""
}
}
}
{
"autoload": {
"psr-4": { "": "src/" }
}
}
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 \Slim\App;
$app->get('/foo', function ($req, $res, $args) {
return $res->withHeader(
'Content-Type',
'application/json'
);
});
$app->run();
PSR-7 examples
$response = new Zend\Diactoros\Response();
$response->getBody()->write("Hello\n");
$response->getBody()->write("world\n");
$response = $response
->withHeader('Content-Type', 'text/plain')
->withAddedHeader('X-Show-Something', 'something');
Caching examples using Stash (tedivm/stash)
$driver = new Stash\Driver\FileSystem();
$pool = new Stash\Pool($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
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