submit php: standards in php world. Михайло Морозов

54
Standards in PHP world

Upload: binary-studio

Post on 16-Apr-2017

145 views

Category:

Software


1 download

TRANSCRIPT

Standards in PHP world

About me

Michael Morozov

PHP-developer @ Binary StudioCoach @ Binary Studio Academy

World Of Tanks Standards

Standards in PHP

➔ RFC (Requests For Comments)

➔ PSR (PHP Standard Recommendations)

RFC Lifecycle

InternetDraft

ProposedDraft

DraftStandard

InternetStandard

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

'\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 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 \r\n

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-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;

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 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 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

\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/" }

}

}

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 \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 with PSR-6

PSR-6: Caching interface

CacheItemPoolCacheItem

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

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