1 of 72

PSR

Чуть больше, чем стиль оформления кода

Анатолий Притульский

PHP-developer at Travellizy

2 of 72

Ссылка на слайды

2/72

3 of 72

Про стандарты

3/72

4 of 72

USB

4/72

5 of 72

Стандарты в PHP

5/72

6 of 72

PSR

PHP Standards Recommendations

6/72

7 of 72

Оформление кода

  • Кодировка файлов UTF-8 без BOM-байта.
  • Классы объявляются в `StudlyCaps`
  • Методы объявляются в lower `camelCase`
  • Константы объявляются в ТАКОМ_ВИДЕ
  • Закрывающий тег ?> ДОЛЖЕН отсутствовать
  • ...

7/72

8 of 72

Code MUST use 4 spaces for indenting, not tabs.

8/72

9 of 72

PSR

Чуть больше, чем стиль оформления кода

9/72

10 of 72

Framework Interoperability Group

https://php-fig.org

10/72

11 of 72

Группа была основана в 2009 году

11/72

12 of 72

Первый стандарт принят в 2010 году

12/72

13 of 72

Участники PHP-FIG

Composer, Zend Framework, Yii framework, CakePHP, Slim, PHPixie, Joomla, Magento, Drupal, phpDocumentor и др.

https://www.php-fig.org/personnel/

13/72

14 of 72

Бывшие участники PHP-FIG

Symfony, Laravel, Guzzle, Doctrine, Propel и др.

https://www.php-fig.org/personnel/

14/72

15 of 72

Почему покидают PHP-FIG?

  • Дискуссии и споры
  • Наследие и поддержка
  • Личные предпочтения

15/72

16 of 72

PHP-FIG обсуждают новый стандарт

16/72

17 of 72

Стандарты

Это - полезно!

17/72

  • Понимание
  • Порядок
  • Переиспользование

18 of 72

Обзор PSR

https://www.php-fig.org/psr/

18/72

19 of 72

PSR-1 / PSR-2 / PSR-12

Basic Coding Standard

Coding Style Guide

Extended Coding Style Guide

19/72

20 of 72

PSR-1 / PSR-2 / PSR-12

PhpStorm Reformat Code

20/72

21 of 72

PSR-1 / PSR-2 / PSR-12

21/72

22 of 72

PSR-3

Logger Interface

22/72

23 of 72

PSR-3

Logger Interface

23/72

<?php

namespace 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());

}

24 of 72

24/72

25 of 72

PSR-3

Нет поддержки PSR-3?

25/72

26 of 72

PSR-3

Используем адаптер

https://github.com/samdark/yii2-psr-log-target

26/72

27 of 72

PSR-0 / PSR-4

Autoloading Standard

27/72

28 of 72

PSR-0 / PSR-4

Оо ???

28/72

class MyLib {

private $CI;

public function __construct()

{

$this->CI = &get_instance();

$this->CI->load->library('encrypt');

$this->CI->load->library('session');

$this->CI->load->library('url');

$this->CI->load->helper('captcha');

$this->CI->load->helper('cookie');

$this->CI->load->helper('email');

}

...

}

29 of 72

PSR-0

deprecated с 2014 года

29/72

function autoload($className)

{

$className = ltrim($className, '\\');

$fileName = '';

$namespace = '';

if ($lastNsPos = strrpos($className, '\\')) {

$namespace = substr($className, 0, $lastNsPos);

$className = substr($className, $lastNsPos + 1);

$fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;

}

$fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';

require $fileName;

}

spl_autoload_register('autoload');

30 of 72

PSR-4

Composer

https://getcomposer.org

30/72

31 of 72

PSR-4

Composer Autoloading

31/72

"autoload": {

"psr-4": {

"Acme\\": "src/"

}

}

}

32 of 72

PSR-6 / PSR-16

Caching Interface

Simple Caching Interface

32/72

33 of 72

PSR-16

Simple Caching Interface

33/72

<?php

interface CacheInterface

{

public function get($key, $default = null);

public function set($key, $value, $ttl = null);

public function delete($key);

public function clear();

public function getMultiple($keys, $default = null);

public function setMultiple($values, $ttl = null);

public function deleteMultiple($keys);

public function has($key);

}

34 of 72

PSR-6

Caching Interface

34/72

  • CacheItemInterface
  • CacheItemPoolInterface

https://www.php-fig.org/psr/psr-6/

35 of 72

PSR-6 / PSR-16

Symfony Cache

https://github.com/symfony/cache

35/72

36 of 72

PSR-6 / PSR-16

Zend Cache

https://github.com/zendframework/zend-cache

36/72

37 of 72

PSR-7

HTTP Message Interface

37/72

38 of 72

PSR-7

Zend Diactoros

PSR-7 HTTP message implementations

https://github.com/zendframework/zend-diactoros

38/72

39 of 72

39/72

40 of 72

40/72

41 of 72

PSR-11

Container Interface

41/72

42 of 72

PSR-11

Container Interface

42/72

<?php

interface ContainerInterface

{

public function get($id);

public function has($id);

}

43 of 72

43/72

44 of 72

PSR-11

  • HomePageHandler.php
  • HomePageHandlerFactory.php

44/72

<?php

class HomePageHandlerFactory

{

public function __invoke(ContainerInterface $container): RequestHandlerInterface

{

$router = $container->get(RouterInterface::class);

$template = $container->has(TemplateRendererInterface::class)

? $container->get(TemplateRendererInterface::class)

: null;

return new HomePageHandler(get_class($container), $router, $template);

}

}

45 of 72

PSR-11

Zend DI

https://github.com/zendframework/zend-di

45/72

46 of 72

46/72

47 of 72

PSR-13

Hypermedia Links

47/72

48 of 72

PSR-13

Общий способ представления

hypermedia links

48/72

49 of 72

PSR-13

Пример реализации

49/72

50 of 72

PSR-13

Hypermedia

то без чего ваше API не совсем REST

https://habr.com/ru/company/aligntechnology/blog/281206/

50/72

51 of 72

PSR-14

Event Dispatcher

51/72

52 of 72

PSR-14

52/72

namespace Psr\EventDispatcher;

interface EventDispatcherInterface

{

public function dispatch(object $event);

}

namespace Psr\EventDispatcher;

interface ListenerProviderInterface

{

public function getListenersForEvent(object $event) : iterable;

}

namespace Psr\EventDispatcher;

interface StoppableEventInterface

{

public function isPropagationStopped() : bool;

}

53 of 72

PSR-14

YiiSoft Event Dispatcher

https://github.com/yiisoft/event-dispatcher

53/72

54 of 72

54/72

55 of 72

PSR-14

Symfony Event Dispatcher

https://github.com/symfony/event-dispatcher

55/72

56 of 72

PSR-15

HTTP Handlers

56/72

57 of 72

PSR-15

Symfony Controller

57/72

<?php

class DefaultController extends AbstractController

{

/**

* @Route("/", name="homepage")

*/

public function index(): Response

{

$posts = $this->getDoctrine()->getRepository(Post::class)->findLatest();

return $this->render('default/index.html.twig', [

'posts' => $posts,

]);

}

}

58 of 72

PSR-15

Symfony Controller

58/72

<?php

class DefaultController extends AbstractController

{

public function list(): Response

{}

public function update(): Response

{}

public function create(): Response

{}

public function delete(): Response

{}

}

59 of 72

PSR-15

Goodbye Controllers,

hello request handlers

https://jenssegers.com/85/goodbye-controllers-hello-request-handlers

59/72

60 of 72

PSR-15

Request Handler

60/72

<?php

class CreateUserHandler

{

public function __construct(UserRepository $repository, Twig $twig)

{

// ...

}

public function __invoke(Request $request): Response

{

// ...

}

}

61 of 72

PSR-15

Request Handler

61/72

<?php

interface RequestHandlerInterface

{

public function handle(ServerRequestInterface $request): ResponseInterface;

}

<?php

interface MiddlewareInterface

{

public function process(

ServerRequestInterface $request,

RequestHandlerInterface $handler

): ResponseInterface;

}

62 of 72

PSR-15

Zend Expressive Handler

62/72

<?php

use Psr\Http\Message\ResponseInterface;

use Psr\Http\Server\RequestHandlerInterface;

use Zend\Diactoros\Response\JsonResponse;

use Psr\Http\Message\ServerRequestInterface;

class PingHandler implements RequestHandlerInterface

{

public function handle(ServerRequestInterface $request): ResponseInterface

{

return new JsonResponse(['ack' => time()]);

}

}

63 of 72

PSR-17

HTTP Factories

63/72

64 of 72

PSR-17

Создать Request

64/72

<?php

use Psr\Http\Message\UriInterface;

use Psr\Http\Message\RequestInterface;

interface RequestFactoryInterface

{

public function createRequest(string $method, $uri): RequestInterface;

}

65 of 72

PSR-17

Создать Response

65/72

<?php

use Psr\Http\Message\ResponseInterface;

interface ResponseFactoryInterface

{

public function createResponse(

int $code = 200,

string $reasonPhrase = ''

): ResponseInterface;

}

66 of 72

PSR-18

HTTP Client

66/72

67 of 72

PSR-18

HTTP Client

67/72

<?php

interface ClientInterface

{

public function sendRequest(RequestInterface $request): ResponseInterface;

}

68 of 72

68/72

69 of 72

69/72

70 of 72

PSR

рекомендации

(а не жесткие правила)

70/72

71 of 72

71/72

Абстракции не должны зависеть от деталей.

Детали должны зависеть от абстракций.

72 of 72

Вопросы

https://nepster.pro

72/72