Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Epic PHP #5

Roma
March 13, 2014

Epic PHP #5

Слайды к пятому занятию курса Epic PHP (http://epixx.ru/epic-php/).
Темы: основы ООП, дизайн и паттерны, composer,

Roma

March 13, 2014
Tweet

More Decks by Roma

Other Decks in Programming

Transcript

  1. Epic PHP #5
    Рома Лапин, Evercode Lab

    View full-size slide

  2. Основы ООП

    View full-size slide

  3. Объекты?
    Стратегию ООП лучше всего описать как
    смещение приоритетов в процессе
    программирования от функциональности
    приложения к структурам данных. Это позволяет
    программисту моделировать в создаваемых
    приложениях реальные объекты и ситуации.

    View full-size slide

  4. ООП
    • Инкапсуляция

    • Полиморфизм

    • Наследование

    View full-size slide

  5. Class
    class ComplicatedClass

    {

    !
    public $someVar = 'a default value';

    !
    public function displayVar() {

    echo $this->someVar;

    }

    }

    View full-size slide

  6. Class
    • Может содержать свои константы,
    переменные (свойства) и функции
    (методы)

    • Название класса не может быть
    зарезервированным словом PHP

    • Название может начинаться с буквы или
    символа подчеркивания и состоять из
    букв, цифр и _.

    View full-size slide

  7. $this
    Псевдопеременная, доступная, когда метод
    вызывается в контексте объекта. Является ссылкой
    на вызывающий объект.

    View full-size slide

  8. new
    $instance = new ComplicatedClass();

    !
    $className = 'Foo';

    $instance = new $className(); // Foo()

    View full-size slide

  9. new
    • Создает экземпляр класса

    • В контексте класса можно создать
    объект, используя new self или new
    parent

    View full-size slide

  10. Class vs Object?

    View full-size slide

  11. Class vs Object?

    View full-size slide

  12. Свойства
    // invalid property declarations:

    public $var1 = 'hello ' . 'world';

    public $var3 = 1+2;

    public $var4 = self::myStaticMethod();

    public $var5 = $myVar;

    !
    // valid property declarations:

    public $var6 = myConstant;

    public $var7 = array(true, false);

    View full-size slide

  13. Задание

    View full-size slide

  14. Задание
    Создайте класс SuperHero. Придумайте, какие у него
    могут быть свойства.

    View full-size slide

  15. extends
    class ExtendClass extends ComplicatedClass

    {

    function displayVar()

    {

    echo "Extending class\n";

    parent::displayVar();

    }

    }

    !
    $extended = new ExtendClass();

    $extended->displayVar();

    View full-size slide

  16. extends
    • Наследоваться можно только от одного
    класса

    • Свойства и методы могут быть
    переопределены (если не заданы как final
    в родителе)

    • Сигнатура параметров переопределямых
    методов должна совпадать (кроме
    конструктора), иначе — E_STRICT

    View full-size slide

  17. Задание
    Создайте базовый класс Сharacter. Унаследуйте от
    него наш SuperHero и новый класс SuperVillain.
    Вынесите в Character общие свойства для героев и
    злодеев, а в них оставьте только уникальные поля.

    View full-size slide

  18. Задание

    View full-size slide

  19. Константы
    class MyClass

    {

    const constant = 'constant value';

    !
    function showConstant() {

    echo self::constant . "\n";

    }

    }

    !
    echo MyClass::constant . "\n";

    !
    $classname = "MyClass";

    echo $classname::constant . "\n"; // As of PHP 5.3.0

    !
    $class = new MyClass();

    $class->showConstant();

    !
    echo $class::constant."\n"; // As of PHP 5.3.0

    View full-size slide

  20. Константы
    • доступны как часть класса

    • доступны во всех областях видимости

    • могут содержать только скалярные
    значения

    • способствуют более чистому коду

    • работают быстрее констант,
    определенных через define()

    View full-size slide

  21. Constructor
    class BaseClass {

    function __construct() {

    print "In BaseClass constructor\n";

    }

    }

    !
    class SubClass extends BaseClass {

    function __construct() {

    parent::__construct();

    print "In SubClass constructor\n";

    }

    }

    !
    class OtherSubClass extends BaseClass {

    // inherits BaseClass's constructor

    }

    View full-size slide

  22. Constructor
    // In BaseClass constructor

    $obj = new BaseClass();

    !
    // In BaseClass constructor

    // In SubClass constructor

    $obj = new SubClass();

    !
    // In BaseClass constructor

    $obj = new OtherSubClass();

    View full-size slide

  23. Constructor
    • вызывается при создании объекта

    • родительский конструктор надо вызывать
    явно: parent::__construct()
    • если не переопределен, наследуется от
    класса родителя (если там он не private)

    • при переопределении параметры могут
    меняться

    View full-size slide

  24. Задание
    Добавьте нашим героям и злодеям конструкторы,
    чтобы при создании объекта задавались основные
    свойства. Общие параметры должны задаваться
    только в конструкторе родительского класса.

    View full-size slide

  25. Destructor
    class MyDestructableClass {

    function __construct() {

    print "In constructor\n";

    $this->name = "MyDestructableClass";

    }

    !
    function __destruct() {

    print "Destroying " . $this->name . "\n";

    }

    }

    !
    $obj = new MyDestructableClass();

    View full-size slide

  26. Destructor
    • будет вызван, как только на объект не
    останется ссылок

    • либо при завершении работы скрипта

    • родительский destructor надо вызывать
    явно: parent::__destruct()

    • будет вызван даже при остановке
    скрипта с помощью exit()

    View full-size slide

  27. PPP & F
    • Public

    • Private

    • Protected

    • Final — может применять к методам и
    классу целиком

    View full-size slide

  28. PPP
    class MyClass

    {

    public $public = 'Public';

    protected $protected = 'Protected';

    private $private = 'Private';

    !
    function printHello()

    {

    echo $this->public;

    echo $this->protected;

    echo $this->private;

    }

    }

    View full-size slide

  29. PPP
    $obj = new MyClass();

    echo $obj->public; // Works

    echo $obj->protected; // Fatal Error

    echo $obj->private; // Fatal Error

    $obj->printHello(); // Shows Public, Protected and Private

    View full-size slide

  30. PPP
    class MyClass2 extends MyClass

    {

    // We can redeclare the public and protected method, but not private

    protected $protected = 'Protected2';

    !
    function printHello()

    {

    echo $this->public;

    echo $this->protected;

    echo $this->private;

    }

    }

    View full-size slide

  31. PPP
    $obj2 = new MyClass2();

    echo $obj2->public; // Works

    echo $obj2->private; // Undefined

    echo $obj2->protected; // Fatal Error

    $obj2->printHello(); // Shows Public, Protected2, Undefined

    View full-size slide

  32. Задание.
    Проверьте, правильно ли у вас расставлены уровни
    доступа у свойств и методов в созданных ранее
    классах. Добавьте свойств с недостающими
    уровнями видимости.

    View full-size slide

  33. Задание.
    На удивление в PHP можно получить доступ к
    private и protected свойствам и методам объкта из
    объекта такого же класса.

    !
    Попробуйте сами написать код, подтверждающий
    это. Если не получится, то найдите в документации
    и напишите подобный.

    View full-size slide

  34. Paamayim Nekudotayim
    ::

    View full-size slide

  35. static

    class Foo

    {

    public static $my_static = 'foo';

    !
    public function staticValue() {

    return self::$my_static;

    }

    }

    !
    class Bar extends Foo

    {

    public function fooStatic() {

    return parent::$my_static;

    }

    }

    View full-size slide

  36. static
    print Foo::$my_static . "\n";

    !
    $foo = new Foo();

    print $foo->staticValue() . "\n";

    print $foo->my_static . "\n"; // Undefined "Property" my_static

    !
    print $foo::$my_static . "\n";

    $classname = 'Foo';

    print $classname::$my_static . "\n"; // As of PHP 5.3.0

    !
    print Bar::$my_static . "\n";

    $bar = new Bar();

    print $bar->fooStatic() . "\n";

    View full-size slide

  37. static
    • доступны именно как часть класса

    • вызываются без создания объекта

    • вызов статичного свойства с помощью
    объектной нотации — Notice

    • по умолчанию public

    • использовать $this внутри статичных
    методов нельзя

    View full-size slide

  38. abstract
    abstract class AbstractClass

    {

    // Force Extending class to define this method

    abstract protected function getValue();

    abstract protected function prefixValue($prefix);

    !
    // Common method

    public function printOut() {

    print $this->getValue() . "\n";

    }

    }

    View full-size slide

  39. abstract
    class ConcreteClass1 extends AbstractClass

    {

    protected function getValue() {

    return "ConcreteClass1";

    }

    !
    public function prefixValue($prefix) {

    return "{$prefix}ConcreteClass1";

    }

    }

    View full-size slide

  40. abstract
    • Класс должен быть объявлен
    абстрактным, если содержит или
    наследует хотя бы один абстрактный
    метод без имплементации

    • класс может иметь только одного предка

    • реализует ограничения для дизайна
    группы классов

    View full-size slide

  41. Задание.
    Сделайте класс Character абстрактным и объявите в
    нем несколько абстрактных методов методов и
    один-два уже реализованных (общих для героев и
    злодеев). Абстрактные методы реализуйте в классах-
    наследниках.

    Например: saveWorld(), fight(), makeSomethingBad(),
    muahahahaha(), think(), putOnMask(), useSuperPower(),
    sayCatchPhrase() и т.д.

    View full-size slide

  42. interface
    Интерфейсы позволяют создавать код, который
    определяет, какие методы должны реализовывать
    классы без необходимости определять саму
    реализацию методов.

    View full-size slide

  43. interface
    interface iTemplate

    {

    public function setVariable($name, $var);

    public function getHtml($template);

    }

    View full-size slide

  44. interface
    class Template implements iTemplate

    {

    private $vars = array();



    public function setVariable($name, $var)

    {

    $this->vars[$name] = $var;

    }



    public function getHtml($template)

    {

    foreach($this->vars as $name => $value) {

    $template = str_replace('{' . $name . '}', $value, $template);

    }

    return $template;

    }

    }

    View full-size slide

  45. interface
    • все метода интерфейса — public, иначе
    просто бессмысленно :)

    • класс может имплементить больше
    одного интерфейса

    • но у этих интерфейсов не должно быть
    методов с одинаковыми именами

    View full-size slide

  46. interface
    • интерфейсы могут наследоваться

    • интерфейсы могут содержать константы

    • сигнатуры методов интерфейса и класса
    должны совпадать

    View full-size slide

  47. Задание.
    Создайте два интерфейса: один супергеройский,
    другой суперзлодейский. Объявите в них
    обязательные методы. Пусть наши классы будут
    реализовывать каждый свой интерфейс.

    !
    Варианты методов: doEvil(), muahaha(), scaryFace(),
    saveTheWorldAgainBeforeBreakfast()

    View full-size slide

  48. Instanceof
    Позволяет определить является ли объект
    экземпляром класса или интерфейса с учетом
    наследования.

    View full-size slide

  49. Instanceof
    class ParentClass

    {

    }

    !
    class MyClass extends ParentClass

    {

    }

    !
    $a = new MyClass();

    !
    var_dump($a instanceof MyClass);

    var_dump($a instanceof ParentClass);

    View full-size slide

  50. Instanceof
    interface MyInterface

    {

    }

    !
    class MyClass implements MyInterface

    {

    }

    !
    $a = new MyClass();

    !
    var_dump($a instanceof MyClass);

    var_dump($a instanceof MyInterface);

    View full-size slide

  51. Задание.
    У нас уже есть три класса и два интерфейса.
    Создайте несколько объектов и проверьте
    являются ли они инстансами каждого класса и
    интерфейса.

    View full-size slide

  52. Object Iteration
    class MyClass

    {

    public $var1 = 'value 1';

    public $var2 = 'value 2';

    public $var3 = 'value 3';

    !
    protected $protected = 'protected var';

    private $private = 'private var';

    !
    function iterateVisible() {

    echo "MyClass::iterateVisible:\n";

    foreach($this as $key => $value) {

    print "$key => $value\n";

    }

    }

    }

    View full-size slide

  53. Object Iteration
    $class = new MyClass();

    !
    foreach($class as $key => $value) {

    print "$key => $value\n";

    }

    echo "\n";

    !
    !
    $class->iterateVisible();

    View full-size slide

  54. Magic methods

    View full-size slide

  55. Magic methods
    • __toString()

    • __call()

    • __get()

    • __set()

    View full-size slide

  56. Задание.
    Задайте классам героев и злодеев магические
    методы. Пусть в них просто выводится что-нибудь
    жизнеутверждающее и нетленное.

    View full-size slide

  57. Клонирование

    View full-size slide

  58. Клонирование
    $class = new MyClass();

    !
    $copy = $class;

    !
    do_some_stuff($copy);

    !
    /*

    $class и $copy остались ссылками на один и тот же объект и будут
    изменены оба

    */

    View full-size slide

  59. Клонирование
    $class = new MyClass();

    !
    $copy = clone $class;

    !
    do_some_stuff($copy);

    !
    /*

    $class и $copy будут разными объектами. Изменения в $copy не будут
    влиять на изменения в $class

    */

    View full-size slide

  60. Клонирование
    public function __clone() {

    /*

    если при клонировании нужны особые условия

    */

    }

    View full-size slide

  61. Сравнение объектов
    • == — одинаковые атрибуты, значения и
    реализуют один и тот же класс

    • === — ссылки на один и тот же инстанс
    класса

    View full-size slide

  62. Проблемы
    • Коллизии имен между пользовательским
    кодом и классами/функциями/
    константами самого PHP или стороннего
    используемого кода.

    • Слишком длинные имена, которыми
    решалась предыдущия проблема

    View full-size slide

  63. Namespaces

    namespace my\name;

    !
    class MyClass {}

    function myfunction() {}

    const MYCONST = 1;

    !
    $a = new MyClass;

    $c = new \my\name\MyClass;

    View full-size slide

  64. Namespaces
    $a = strlen('hi');

    !
    $d = namespace\MYCONST;

    !
    $d = __NAMESPACE__ . '\MYCONST';

    echo constant($d);

    View full-size slide

  65. Namespaces
    • namespace — первое, что есть в php
    файле после открывающего тэга

    • Один и тот же namespace может быть
    объявлен в нескольких файлах

    • Пространства имен могут формировать
    иерархию

    View full-size slide

  66. Namespaces
    • к глобальному пространству имен всегда
    можно обратиться добавив перед
    вызовом \

    • __NAMESPACE__ — константа
    содержащая имя текущего пространства
    имен

    View full-size slide

  67. Импортируем
    use My\Full\Classname as Another, My\Full\NSname;

    !
    $obj = new Another; // создает объект класса My\Full\Classname

    !
    NSname\subns\func(); // вызывает функцию My\Full\NSname\subns\func

    View full-size slide

  68. Интерпретируем
    • имя указано без\ в начале — класс будет
    искаться в текущем namespace

    • при его отсутствии — Fatal error

    • Для функций и констант без полного
    имени ненайденных в текущем
    namespace будет попытка найти их в
    глобальном пространстве имен (fallback).

    View full-size slide

  69. PSR-0
    • \Zend\Acl => /vendor/Zend/Acl.php

    • \Doctrine\Common\IsolatedClassLoader
    => /vendor/Doctrine/Common/
    IsolatedClassLoader.php

    • https://github.com/php-fig/fig-standards/
    blob/master/accepted/PSR-0.md

    View full-size slide

  70. Интерпретируем

    View full-size slide

  71. Задание.
    Организуем наш код как взрослые.

    Для приложения — отдельный каталог epicoop

    Весь код классов — в epicoop/src.

    Главный namespace — Epicphp

    Расположение классов соответствует PSR-0

    index.php — epicoop/web

    В index.php подключаем все нужные классы

    View full-size slide

  72. Exceptions
    function inverse($x) {

    if (!$x) {

    throw new Exception('Division by zero.');

    }

    else return 1/$x;

    }

    !
    try {

    echo inverse(5) . "\n";

    echo inverse(0) . "\n";

    } catch (Exception $e) {

    echo 'Caught exception: ', $e->getMessage(), "\n";

    }

    View full-size slide

  73. Exceptions
    • Унифицированный метод обработки
    ошибок

    • По сути являются объектами,
    создаваемыми (“выбрасываемыми”) в
    случае ошибки

    • Все исключения в throw должны быть
    инстансами класса Exception или его
    наследников

    View full-size slide

  74. Exceptions
    • Каждый try должен иметь хотя бы один
    catch

    • блоков catch может быть несколько (для
    разных классов исключений)

    • После “выкинутого” код не выполняется
    до первого найденного catch

    • Исключение не поймано — Fatal error

    View full-size slide

  75. Exceptions
    • Внутренние функции PHP используют
    error reporting и только новые ООП
    расширения исользуют exceptions, но это
    можно переопределить

    • http://www.php.net/manual/en/
    spl.exceptions.php

    View full-size slide

  76. Проблемы
    • Много классов в ООП приложениях

    • Как правило, один класс — один файл

    • До использования каждый класс надо
    подключить

    • Получались частоколы require и include

    • Много ошибок из-за забытых файлов

    View full-size slide

  77. Проблемы

    View full-size slide

  78. __autoload()
    function __autoload($class_name)

    {

    require_once "/www/library/{$class_name}.php";

    }

    !
    $a = new friend();

    View full-size slide

  79. __autoload()
    function __autoload($name) {

    echo "Want to load $name.\n";

    throw new Exception("Unable to load $name.");

    }

    !
    try {

    $obj = new NonLoadableClass();

    } catch (Exception $e) {

    echo $e->getMessage(), "\n";

    }

    View full-size slide

  80. spl_autoload_register
    Позволяет сделать несколько автолоадеров на случай разных
    концепций загрузки файлов.

    !
    function my_autoloader($class) {

    include 'classes/' . $class . '.class.php';

    }

    !
    spl_autoload_register('my_autoloader');

    View full-size slide

  81. Задание.
    Убираем из index.php все require и создаем
    функцию автолоадинга. Проверяем, что при
    создании объектов классов ошибок нет.

    View full-size slide

  82. Standard PHP Library
    (SPL)

    View full-size slide

  83. SPL
    Входит в состав PHP и содержит коллекцию
    полезных классов и интерфейсов.

    View full-size slide

  84. SPL
    • Iterators

    • Datastructures

    • Interfaces

    • Exceptions

    • “и кое-что еще...” ©

    • http://php.net/spl

    View full-size slide

  85. Управление
    зависимостями

    View full-size slide

  86. Проблемы
    • На PHP написано много кода

    • На самом деле много

    • Вам столько даже представить сложно

    • И я не шучу

    • С чего бы мне шутить

    View full-size slide

  87. Проблемы
    • Посреди тон кода есть куча полезностей

    • Фреймворки

    • Библиотеки

    • Компоненты

    • Да, большинство простых проблем уже
    решены за вас

    View full-size slide

  88. Проблемы
    • И вы будете использовать чужие
    фреймворки, библиотеки, компоненты...

    • Много, это точно

    • Но их же надо как-то искать?

    • Устанавливать?

    • Обновлять?

    View full-size slide

  89. Composer
    Composer является блестящим менеджером
    зависимостей для PHP. Укажите список
    зависимостей вашего проекта, в файле
    composer.json и с несколькими простыми
    командами, Composer автоматически скачает
    зависимости вашего проекта и установит
    автозагрузку для вас.

    View full-size slide

  90. Composer
    • Множество совместимых библиотек

    • Их можно искать: https://packagist.org/

    • Взрывное развитие и популярность у
    разработчиков

    • Если вашей библиотеки нет в packagist и
    ее не поставить через composer, то
    вашей библиотеки просто нет

    View full-size slide

  91. Composer
    curl -s https://getcomposer.org/installer | php

    !
    php composer.phar require twig/twig:~1.8

    !
    php composer.phar install

    View full-size slide

  92. Composer

    require 'vendor/autoload.php';

    !
    /*

    проблема автолоадинга только что была решена за вас бесплатно и без
    СМС!

    */

    View full-size slide

  93. composer.json
    {

    "require": {

    "silex/silex": "1.0.*",

    "swiftmailer/swiftmailer": ">=4.1.2,<4.2-dev",

    "twig/twig": ">=1.8,<2.0-dev",

    "symfony/twig-bridge": "2.1.*",

    "symfony/form": "2.1.*",

    "symfony/validator": "2.1.*",

    "symfony/config": "2.1.*",

    "symfony/translation": "2.1.*",

    "rmzamora/google-api-php": "dev-master",

    "zendframework/zendgdata": "2.0.*",

    "symfony/security": "2.1.*"

    },

    "minimum-stability": "dev",

    !
    "autoload": {

    "psr-0": {

    "App": "src/"

    }

    }

    }

    View full-size slide

  94. Composer
    • composer.json

    • composer.lock

    • php composer.phar update

    • http://getcomposer.org/doc/00-intro.md

    • Composer умеет ставить либы из PEAR

    View full-size slide

  95. Задание.
    Установите композер в наш epicoop.

    Найдите в packagist symfony/finder, symfony/config,
    symfony/http-foundation. Установите их через
    composer.

    View full-size slide

  96. Дизайн и паттерны

    View full-size slide

  97. Дизайн и паттерны

    View full-size slide

  98. Code Reuse
    • Мы решаем одни и те же проблемы
    каждый день

    • Мы решаем те же пробемы, что и наши
    “соседи” каждый день

    • Мы решаем одинаковые проблемы на
    разных проектах

    • И мы ленивые, но хотим делать хорошо!

    View full-size slide

  99. Дизайн и паттерны
    • Правильные и конкретные решения для
    общих проблем

    • Общий язык для общения между
    разработчиками

    View full-size slide

  100. Singleton
    public static function getInstance()

    {

    static $instance = null;

    if (null === $instance) {

    $instance = new static;

    }

    !
    return $instance;

    }

    !
    protected function __construct()

    {

    }

    View full-size slide

  101. Singleton
    $obj = Singleton::getInstance();

    \var_dump($obj === Singleton::getInstance()); // bool(true)

    View full-size slide

  102. Singleton
    • убедиться, что в системе только один
    инстанс определенного класса

    • применения: обертки соединений (база
    данных, файлы, внешние источники
    данных)

    • Не рекомендуется к использованию в
    последнее время

    View full-size slide

  103. Registry
    • Расширение Singleton

    • По сути явлется хранилищем для данных
    и инстансов других объектов

    • И обеспечивает, что это хранилище в
    системе одно

    • Zend_Registry

    View full-size slide

  104. Factory
    • Предоставляет собой общий интерфейс
    к набору классов со схожей
    функциональностью, но разной начинкой

    • Создает инстанс нужного класса

    • например, фабрика для выбора
    хранилища данных, службы доставки,
    платежной системы

    View full-size slide

  105. Front controller
    • Одна (!) точка входа для всех запрсов
    приложения

    • Совсем одна

    • Одна-одинешенька

    • Как Уилл Смит в «Я Легенда»

    • Пока не встретил женщину, из-за
    которой умер

    View full-size slide

  106. Front controller

    View full-size slide

  107. Front controller
    • index.php

    • + настройка сервера (например, .htaccess)

    • код, ответственный за загрузку
    зависимостей, обработку запроса,
    отправку ответа, весь он в одном месте

    • способствует модульности

    View full-size slide

  108. MVC
    • во всех фреймворках страны

    • т.е. во всех современных фреймворках на
    самом деле

    View full-size slide

  109. MVC
    • Model

    • View

    • Controller

    View full-size slide

  110. MVC
    • Model — данные и обработка

    • View — шаблоны (html, xml, markup...) и
    никакой логики

    • Controller — обработка запроса,
    отправка данных из модели во вьюшку

    View full-size slide

  111. Задание.
    Переделайте ваше CRUD приложение с
    использованием объектов и паттернов.

    !
    Код вне объектов может быть только в index.php.

    Html должен быть в отдельных файлах. Логики там
    содержаться не должно, максимум вывод
    переменных, циклы для списков и if необходимые
    для определения логики вывода.

    !
    Не бойтесь ошибиться. Не попробовав, вы никогда
    не поймете, как оно работает на самом деле.

    View full-size slide

  112. Задание.
    Переделайте ваше CRUD приложение с
    использованием объектов и паттернов.

    !
    Код вне объектов может быть только в index.php.

    Html должен быть в отдельных файлах. Логики там
    содержаться не должно.

    !
    Не бойтесь ошибиться. Не попробовав, вы никогда
    не поймете, как оно.

    View full-size slide