Разделы
Теги | RSS © 2008 – 2017
Контакты
email: igor@veselov.sumy.ua
skype: utz0r2
» » » Страница 3

9. Коротко ООП PHP - Создание комментариев documentor


Считаеться что писать комментарии в коде, это плохо. Код должен быть понятен сам по себе. А единственные комментарии которые должны присутвовать это документирование с помощью докблоков ( всегда начинаеться с /** )
/**
 * It is
 * a PHP docblock
 */

Стандарт PHPDoc взят с языка Java. Важной составляющей докблоков являются теги и аннотации.
В PHP с помощью докблоков можно документировать такие элементы:
- функции;
- константы;
- классы;
- интерфейсы;
- трейты;
- константы классов;
- свойства;
- методы.
/**
 * Rabbit Class
 *
 * @version 0.1.0
 */
class Rabbit implements RabbitInterface
{
    const STATUS_RUNNING = 'running';
 
    /**
     * @var string $status Status
     */
    private $status;
 
    /**
     * Set `running` status for the rabbit
     *
     * @return $this
     */
    public function run()
    {
        $this->status = self::STATUS_RUNNING;
 
        return $this;
    }
}

@api (метод) — обозначает стабильные публичные методы, которые не будут менять свою семантику до следующего мажорного релиза.
@author (в любом месте) — указывает имя и имейл автора, который написал следующий код.
@copyright (в любом месте) — используется, чтоб поставить свой копирайт в коде.
@deprecated (в любом месте) — полезный тег, символизирует, что данный элемент исчезнет в будущих версиях. Обычно рядом пишут, какой код следует использовать взамен. Также большинство IDE подсвечивают использование устаревших методов отдельным стилем. Когда нужно подчистить устаревший код для нового релиза, то легко искать по этому тегу.
@example (в любом месте) — используется для размещения ссылки на файл или веб-страницу, где показан пример использования кода. На данный момент phpDocumentor заявляет о неполной поддержки возможностей этого тега.
@filesource (файл) — этот тег можно размещать только на самом начале php-файла, так как тег применим только к файлу и включит весь код файла в сгенерированную документацию.
@global (переменная) — на данный момент этот тег не поддерживается, возможно, будет реализован в следующих версиях, когда он будет переосмыслен.
@ignore (в любом месте) — докблок, где указан этот тег, не будет обрабатываться во время генерации документации, даже если в нем есть другие теги.
@internal (в любом месте) — чаще всего используется вместе с тегом @api, чтоб показать, что код предназначен для внутренней логики этой части программы. Элемент, обозначенный этим тегом, не будет включен в документацию.
@license (файл, класс) — что же он еще может делать, если не указывать тип лицензии для написанного кода.
@link (в любом месте) — используется для вставки ссылок, но, как пишет документация, полностью функциональность тега пока не поддерживается.
@method (класс) — применяется к классу и служит для описания магических методов, которые обрабатываются магической функцией __call().
@package (файл, класс) — разбиение кода на логические подгруппы. Когда вы помещаете классы в один namespace, вы тем самым показывает их функциональную схожесть. Если классы лежат в разных неймспейсах, но имеют одинаковый логический признак, их можно сгруппировать с помощью этого тега, например, если у вас классы работающие с корзиной заказа разбросаны по разным местам. Но лучше отказаться от такой практики, по код стайлу Symfony, например, этот тег не должен использоваться.
@param (метод, функция) — предназначен для описания входящих параметров функции. Важно также отметить, что если вы уже взялись описывать входящие параметры для конкретной функции через докблоки, то нужно описывать все, а не только первый или второй.
@property (класс) — так же, как и @method, этот тег размещается в докблоке для класса, но описывает свойства, доступ к которым будет обрабатываться через магические методы __get() и __set().
@property-read, @property-write (класс) — аналогично предыдущему тегу, но обрабатывают только один магический метод, __get() или __set() соответственно.
@return (метод, функция) — предназначен для описания значения, которое возвращает функция. Можно указать его тип, и PhpStorm подхватит его и будет выдавать подсказки, но об этом чуть позже.
@see (в любом месте) — с помощь этого тега можно вставлять ссылки на внешние ресурсы, как и с помощью @link, но также вставлять относительные ссылки на классы и методы.
@since (в любом месте) — можно указать версию, в которой появился кусок кода.
@source (в любом месте, кроме начала файла) — с помощью этого тега можно помещать в документацию участки исходного кода (задается строка начала и конца).
@throws (метод, функция) — используется для указания исключений, которые могут быть вызваны в данной функции.
@todo (в любом месте) — самый оптимистически тег, используется программистами, чтоб напомнить себе доделать что-то, когда-то в каком-то участке кода. IDE умеют распознавать этот тег и группируют все участки кода в отдельном окне, удобно для будущего поиска. Это общепринятый стандарт и используется очень часто.
@uses (в любом месте) — предназначен для отображения связи между разными участками кода. Он чем-то похож на @see, но разница в том, что @see создает однонаправленную ссылку, т.е. после перехода на новую страницу документации у вас не будет ссылки назад, а @uses в процессе его обработки ставит обратную ссылку, т.е. ссылку для обратной навигации.
@var (переменная) — используется для указания типа и описания переменных, как тех, что встречаются внутри функций, так и свойств класса. Следует учесть разницу между этим тегом и тегом @param. Тег @param используется только в докблоках для функций и описывает входящие параметры, а @var используется для документирования обычных переменных.
@version (в любом месте) — обозначает текущую версию программы, в которой появился данный класс, метод и т.д.

8. Коротко ООП PHP - Пространства имен (namespace use)


Пространства имен PHP предоставляют возможность группировать логически связанные классы, интерфейсы, функции и константы.
В PHP пространства имен используются для решения двух проблем, с которыми сталкиваются авторы библиотек и приложений при создании повторно используемых элементов кода, таких как классы и функции:
1. Конфликт имен между вашим кодом и внутренними классами/функциями/константами PHP или сторонними.
2. Возможность создавать псевдонимы (или сокращения) для Ну_Очень_Длинных_Имен, чтобы облегчить первую проблему и улучшить читаемость исходного кода.
Вот статья которая доступным языком объясняет простраства имен, зачем, как и почему https://habrahabr.ru/post/212773/

7. Коротко ООП PHP - Автозагрузка (autoload). Что такое PSR


PSR (Proposing a Standards Recommendation - Предлагаемые рекомендации стандартов). Группа разработчиков путем голосования создают стандарты для php.
Данные стандарты абсолютно независимы друг от друга и разработчик сам может выбирать следовать им или нет.
http://www.php-fig.org/psr/ здесь список на мемент написания статьи, PSR-0 устаревший, с 1,2,3,4,6,7 стандарты приняты, и 5,8,9,10,11 в черновиках еще.
PSR-0: устаревший смотреть PSR-4.
PSR-1: Основные стандарты кодирования
Секция описывает общие правила оформления кода:
- Использование только тэгов <?php и <?=
- Только UTF-8 без BOM для пхп кода
- Не стоит мешать разный функционал в одном файле
- NS и классы должны следовать psr-0
- классы объявляются в `StudlyCase`
- методы объявляются в lower `camelCase`
- константы объявляются в ТАКОМ_ВИДЕ
PSR-2: Стандарты оформления кода
Собственно представляет собой требования к оформлению кода:
- код должен пользовать 4 пробела вместо ТАБ для отделения кода
- длина строки не более 80 символов, ну 120 в крайнем случае
- пустая строка после объявления NS и USE блока
- открывающая скобка `{` объявления класса и методов должна находится на следующей строке, а закрывающая `}` на следующей строке после кода
- для всех свойств и методов обязательно указывать видимость;
ключевые слова `abstract` и `final` указываются до объявления видимости, а `static` после
- После управляющих ключевых слов (команд языка) должен ставиться пробел, не ставится после вызова методов и функций
- Открывающие скобки `{` для команд ставятся на одной строке с ключевым словом, а закрывающая `}` на следующей строке после кода
- Скобки команд `()` не должны начинаться и заканчиваться пробелами
Остальные стандарты можете посмотреть на http://www.php-fig.org/psr/
Пример автозагрузчиков на основе PSR-4 https://github.com/php-fig/fig-standards/blob/master/accepted/ru/PSR-4-autoloader-examples.md

6. Коротко ООП PHP - Исключения (throw catch exception)


Исключения это условия вызывающееся обычно когда ошибка. Они показывают на то, что в процессе выполнения скрипта пошло что-то не так, при этом выполнение скрипта не обязательно останавливается.
<?php

// функция 1 делим на число
function inverse($x) {
	// делить на ноль нельзя
    if ( !$x ) {
        throw new Exception('Деление на ноль.');
    }
    return 1/$x;
}

try {
    echo inverse(5) . "\n";
    echo inverse(0) . "\n";
} catch (Exception $e) {
    echo 'Выброшено исключение: ',  $e->getMessage(), "\n";
}

// Продолжение выполнения
echo "Hello World\n";
В php 7 появился новый класс Throwable, который является родительским интерфейсом для всех объектов, выбрасывающихся с помощью выражения throw, включая классы Error и Exception.

5. Коротко ООП PHP - Абстрактные классы (abstract) и интерфейсы объектов (interface), их отличие


Методы, объявленные абстрактными, несут, по существу, лишь описательный смысл и не могут включать реализации. При наследовании от абстрактного класса, все методы, помеченные абстрактными в родительском классе, должны быть определены в классе-потомке; кроме того, область видимости этих методов должна совпадать (или быть менее строгой).
Интерфейсы объектов позволяют создавать код, который указывает, какие методы должен реализовать класс, без необходимости описывания их функционала. Тела методов интерфейсов должны быть пустыми.
Интерфейс - это абстрактный класс, у которого все методы не реализованы, все публичные и нет переменных класса.
Абстрактный класс - это как ЗАГОТОВКА.
Интерфейс - это как КОНТРАКТ, что обязан выполнять класс.
А теперь в чем же отличие:
- Интерфейсы, в отличии от абстрактных классов, поддерживают множественное наследование. Т.е. класс-потомок может реализовывать 2 или более интерфейсов одновременно: class A implements Int1, Int2, но class A extends AbstrB
- Интерфейс содержит исключительно объявления методов, но не содержит реализации.
- Интерфейс не может включать в себя свойства
- Класс-потомок обязан реализовывать все методы интерфейса
- В интерфейсе все методы открытые
abstract
<?php

abstract class Car {
	public $x;
	public $y;

    public function __construct($x, $y) {
      $this->x = $x;
      $this->y = $y;
    }
	
	abstract public function move ($x, $y);

}

class BMW extends Car {
	
    public function move($x, $y) {
		echo "Движение BMW из координат ($this->x, $this->y) в координаты ($x, $y)<br />";
		$this->x = $x;
		$this->y = $y;
    }
	
}

$auto = new BMW(10, 20);
echo $auto->x;
echo "<br />";
echo $auto->y;
echo "<br />";
$auto->move(5, 15);
interface
<?php

interface Parsed {
	public function Parsed($blah);
}

interface DotSyntax {
	public function UsesDotSyntax();
}

interface Compiled {
	public function isCompiled();
}



class Java implements DotSyntax, Compiled {
	public function __construct() {
		echo 'Java was created<br/>';
		$this->UsesDotSyntax();
		$this->isCompiled();
	}

	public function UsesDotSyntax() {
		echo 'Yes, UsesDotSyntax<br/>';
	}

	public function isCompiled() {
		echo 'Yes, isCompiled<br/>';
	}
}

class PHP implements Parsed {
	public function __construct() {
		echo 'PHP was created<br/>';
		$this->Parsed('Yes, Parsed<br/>');
	}
	public function Parsed($blah) {
		echo $blah;
	}
}

$php = new PHP();
$java = new Java();

4. Коротко ООП PHP - Магические методы (magic methods) __


Магиеские методы - "магия" данных методов сводится к тому, что они могут перехватывать (отсюда их второе название - методы-перехватчики) сообщения, посланные неопределенным (по сути - несуществующим) методам и свойствам
Всегда начинаются с двойного подчеркивания.
__construct() - этот метод запускается автоматически при созданнии экземпляра класса
__destruct() - метод запускается автоматически при уничтожении обьекта
__call(), __callStatic() - перехватывают обращение к несуществующему методу в контексте объекта и в статическом контексте
__get(), __set() - выполняется при чтении/записи данных из недоступных свойств
__isset() - будет выполнен при использовании isset() или empty() на недоступных свойствах
__unset() - будет выполнен при вызове unset() на недоступном свойстве
__sleep() - вызывается, когда объект подвергается сериализации при помощи функции serialize()
__wakeup() - вызывается при восстановлении объекта при помощи функции unserialize()
__toString() - метод, с помощью которого можно обращаться к классу как к строке
__invoke() - вызывается при попытке использовать объект в качестве функции
__set_state() - метод, который вызывается для классов, экспортирующих значения свойств функцией var_export()
__clone() - вызывается при клонировании объекта
__debugInfo() - метод вызывается функцией var_dump(), когда необходимо вывести список свойств объекта
<?php
class Car {

	function __construct() {
		echo 'Конструктор, вызывается автоматически во время создания экземпляра класса <br/>';
	}

	function __destruct() {
		echo 'Деструктор, вызывается автоматически во время уничтожения экземпляра класса <br/>';
	}

    function __call($name, $arguments) {
        // значение $name регистрозависимо
        echo "Вызов метода '$name' " . implode(', ', $arguments). "<br/>";
    }

    static function __callStatic($name, $arguments) {
        echo "Вызов статического метода '$name' " . implode(', ', $arguments). "<br/>";
    }

	function __get($param) {
		echo "Выполнить из за чтения данных из недоступных свойств: $param <br/>";
	}
	
	function __set($name, $value) {
		echo "Выполнить метод из за записи данных в недоступные свойства: $name -> $value <br/>";
		return $this->{$name} = $value; 
	}

    function __isset($name) {
        echo "Установлено ли '$name'? <br/>";
        // return isset($this->data[$name]);
    }

    function __unset($name) {
        echo "Уничтожение '$name' <br/>";
        // unset($this->data[$name]);
    }
	
	function __sleep() {
		echo "Объект подвергается сериализации при помощи функции serialize <br/>";
    }	
	
	// function __wakeup() {
		// echo "Объект подвергается восстановлении при помощи функции unserialize <br/>";
    // }	
	
	function __toString() {
		return "Мы вызвали " . __METHOD__ . "<br/>";
	}
	
	function __invoke($vars) {
		return "Нельзя вызывать класс как функцию <br/>";
	}
	
	function __set_state($an_array) {
		return print_r($an_array) . "<br/>";
	}

	function __clone()	{
		echo 'Вызывается при клонировании объекта <br/>';
	}

	function __debugInfo() {
		echo 'Вызывается при var_dump <br/>';
	}
	
}

$car = new Car();	// __construct
$car->runTest('в контексте объекта');	// __call
car::runTest('в статическом контексте объекта'); // __callStatic
$car->asdfasdf;	// __get
$car->asdfasdf = 'test';	// __set
isset($car->a); // __isset
isset($car->b); // __unset
$a = serialize($car); // __sleep
// unserialize($a); // __wakeup
echo $car; // __toString
echo $car('Пиу'); // __invoke
eval('$b = ' . var_export($car, true) . ';'); 
var_dump($b); // __set_state
$car2 = clone $car; // __clone
var_dump($car2); // __debugInfo
«»
Вверх