Статьи

Под капотом компонентной архитектуры Yii, часть 1

В течение долгого времени было много шума вокруг использования фреймворков, и есть много отличных фреймворков PHP на выбор. Я был поражен простотой и мощью базового класса CComponent в рамках Yii. Что делает класс?

  • Свойства — добавляет свойства getter и setter к классам
  • Конфигурация — включает элегантную систему каскадного конфигурирования на уровне класса и приложений.
  • События — добавляет возможность вызывать и вызывать пользовательские события
  • Поведения — добавляет возможность использовать поведение (также называемое дополнениями)

Каждый класс в платформе происходит от класса CComponent , что означает, что все подклассы работают как компоненты и могут вызывать и обрабатывать события, а также могут использоваться и настраиваться повторно. Это очень много для такого маленького класса!

Я хотел бы поделиться с вами основным компонентом, CComponent в основе инфраструктуры Yii, и я организовал CComponent класса CComponent трех статей. В этой статье я расскажу, как Yii использует магические методы PHP для создания свойств класса и элегантной системы конфигурации. В следующей статье я расскажу, как вы можете использовать программирование на основе событий и как класс компонента Yii реализует это, чтобы упростить вызов и обработку событий. В заключительной статье будет рассказано о поведении (также называемом дополнительными модулями), о том, что это такое, как вы можете их использовать и как Yii реализует их.

Итак, начнем с нашей первой темы.

свойства

Свойство определяет настраиваемый аспект класса; он предоставляет интерфейс класса, позволяющий вам манипулировать им, чтобы делать ставки. Например, свойствами класса загрузки изображений могут быть «путь к файлу» и «максимально допустимый размер файла». Этими свойствами можно управлять и манипулировать, написав методы setter и getter, такие как setFilePath() и getFilePath() , или просто добавив открытое свойство класса, например public $filePath .

Тем не менее, есть небольшая проблема с этим. Если вы определяете свойства как общедоступные переменные, у вас потенциально есть много областей в приложении, которые могут ссылаться на свойство напрямую, и вы не можете контролировать, какие другие части приложения могут ему назначаться. При настройке свойства filePath я могу сначала проверить, является ли это правильный путь, и filePath сообщение об ошибке, если это не так. Для этого мне нужно создать метод setFilePath() . Использование $uploaderObject->filePath = "/file/path/" просто не сокращает его.

Класс компонентов Yii реализует магические функции __get() и __set() которые реализуют чертовски простое соглашение, позволяющее создавать методы получения и установки, но при этом обращаться к свойствам, как если бы они были открытыми переменными. По сути, Yii предполагает, что метод, начинающийся с «get» или «set», ссылается на свойство с тем же именем, что и метод без префикса «get» или «set». Это позволяет вам легко расширить ваш код на более поздний срок. Вы можете пойти дальше и добавить свои публичные переменные, когда впервые начнете создавать свой класс; не беспокойтесь о добавлении методов получения и установки. Затем вы можете добавить методы getter и setter и сделать исходное свойство приватным, но вам не нужно реорганизовывать оставшуюся часть кода.

 <?php echo $uploaderObject->filePath; 

на самом деле позвонит:

 <?php echo $uploader->getFilePath(); 

и используя …

 <?php $uploaderObject->filePath = "my/path"; 

позвоню:

 <?php $uploaderObject->setFilePath("my/path"); 

Конечно, вы все равно можете getFilePath() вызывать getFilePath() или setFilePath() если хотите.

Давайте посмотрим, как Yii достигает этого.

Магия йии

CComponent класс CComponent Yii, вы обнаружите два магических метода, ответственных за это волшебство. Давайте начнем с первой функции __get() .

 <?php public function __get($name){ $getter = "get" . $name; if (method_exists($this, $getter)) { return $this->$getter(); } throw new CException("Property '$name' is not defined."); } 

Когда вы вызываете echo $uploader->filePath; PHP ищет общедоступное свойство filePath . Если он не находит его (или если он закрытый), PHP делегирует магический метод __get() . PHP вызывает функцию __get() и передает ей имя свойства. В этом примере $name будет хранить значение «filePath». Затем Yii делает следующее:

  • Добавляет текст «get» к значению переменной $name и присваивает его переменной $getter , делая $getter равным «getfilePath» (помните, что имена функций в PHP не чувствительны к регистру).
  • Проверяет, есть ли метод с именем getfilePath() определенный в этом объекте.
  • Вызывает метод, если он существует. Код $this->$getter(); это действительно вызов $this->getfilePath() в этом примере.
  • Если метод не найден, то будет выдано исключение с жалобой, как вы уже догадались, свойство не может быть найдено.

Тот же процесс применяется с магической __set() . Когда вы присваиваете setFilePath значение примерно так:

 <?php $uploader->filePath = 'my/path'; 

PHP сначала ищет публичную собственность. Если он не существует (или является частным), PHP вызывает волшебную __set() . Функция __set() работает аналогично __get() , хотя PHP также передает заданное вами значение, поэтому $value будет хранить «my / path» в примере.

 <?php public function __set($name, $value) { $setter = "set" . $name; if (method_exists($this, $setter)) { return $this->$setter($value); } if (method_exists($this, "get" . $name)) { throw new CException("Property '$name' is read only."); } else { throw new CException("Property '$name' is not defined."); } } 

Реализация функции __set() :

  • Добавляет значение $name к значению «set» и присваивает его переменной $setter которая становится «setfilePath».
  • Проверяет, существует ли метод с именем setfilePath .
  • Если метод существует, то он $this->setfilePath("my/path"); как $this->setfilePath("my/path"); ,
  • Если метод set не существует, выполняется проверка, если для свойства есть метод getter. Если есть, то свойство доступно только для чтения, и выдается исключение, указывающее столько же. Если нет метода get и метода set, возникает исключение, указывающее, что свойство не существует.

Всего за несколько строк кода Yii реализовал очень хорошую систему свойств, основанную на использовании магических функций PHP __get() и __set() .

конфигурация

Еще одним преимуществом использования этого метода определения свойств является то, что вы можете легко использовать массивы для настройки ваших классов, если вы того пожелаете:

 <?php $config = array( "myProperty" => 1234, "anotherProperty" => 5678); 

Вы можете настроить класс компонентов с помощью вышеуказанного массива, просто выполнив следующее:

 <?php foreach ($config as $property => $value) { $this->$property = $value; } 

Код использует ключи массива в качестве свойств, устанавливая их равными значению, определенному в массиве. Это удивительно просто, и именно так Yii сам управляет своей конфигурацией на уровне приложений. Вот пример очень простого демонстрационного файла конфигурации Yii:

 <?php return array( "name" => "My Amazing App", "timezone" => "Europe/London", "components" => array( "db" => array( "username" => "root", "password" => "" ), "user" => array( "allowAutoLogin" => true ) ) ); 

Массив передается в класс приложения Yii, который затем проходит через каждый ключ конфигурации. Класс приложения должен иметь свойства, определенные для «имени», «часового пояса» и «компонентов».

 <?php class MyApplication extends CComponent { public $name; public $timezone; public function setComponents(array $components) { // handle the array of components } } 

Ключ компонентов вызывает функцию setComponents() которая ожидает массив. Эта функция загружается в каждый класс и передает ему свой собственный массив конфигурации и так далее, пока все не настроит свои свойства конфигурации. Это невероятно быстро, абсолютно не навязчиво, и нет необходимости в отдельных методах настройки, разбросанных по всему коду.

Позже вы можете расширить свой класс, используя вместо этого методы setter и getter, если это необходимо.

 <?php class MyApplication extends CComponent { private $name; private $timezone; public setName($name) { // do something with the $name } public setTimezone($timezone) { // do something with $timezone } // TODO: Add getter functions public function setComponents(array $components) { // handle the array of components } } 

Резюме

В этой статье я дал вам краткий обзор того, как магические методы используются в классе компонентов Yii для создания свойств и простой, но мощной системы конфигурации. Конечно, Yii не останавливается на достигнутом. Он также реализует магические __isset() и __unset() , что означает, что вы можете использовать isset() чтобы определить, имеет ли свойство значение, и использовать unset() чтобы уничтожить свойство.

Во второй части я расскажу о событиях, еще одном ключевом принципе в создании многократно используемого кода в компонентной архитектуре. Я покажу вам, как вы можете использовать программирование на основе событий в PHP и как Yii позволяет своим подклассам компонента вызывать и обрабатывать события.

Изображение через Филипчука Олега Васильевича / Shutterstock