Учебники

Yii — Модели

Модели — это объекты, представляющие бизнес-логику и правила. Чтобы создать модель, вы должны расширить класс yii \ base \ Model или его подклассы.

Атрибуты

Атрибуты представляют бизнес-данные. Они могут быть доступны как элементы массива или свойства объекта. Каждый атрибут является общедоступным свойством модели. Чтобы указать, какими атрибутами обладает модель, вы должны переопределить метод yii \ base \ Model :: attribute () .

Давайте посмотрим на модель ContactForm базового шаблона приложения.

<?php
   namespace app\models;
   use Yii;
   use yii\base\Model;
   /**
   * ContactForm is the model behind the contact form.
   */
   class ContactForm extends Model {
      public $name;
      public $email;
      public $subject;
      public $body;
      public $verifyCode;
      /**
      * @return array the validation rules.
      */
      public function rules() {
         return [
            // name, email, subject and body are required
            [['name', 'email', 'subject', 'body'], 'required'],
            // email has to be a valid email address
            ['email', 'email'],
            // verifyCode needs to be entered correctly
            ['verifyCode', 'captcha'],
         ];
      }
      /**
      * @return array customized attribute labels
      */
      public function attributeLabels() {
         return [
            'verifyCode' => 'Verification Code',
         ];
      }
      /**
      * Sends an email to the specified email address using the information 
         collected by this model.
      * @param  string  $email the target email address
      * @return boolean whether the model passes validation
      */
      public function contact($email) {
         if ($this->validate()) {
            Yii::$app->mailer->compose()
               ->setTo($email)
               ->setFrom([$this->email => $this->name])
               ->setSubject($this->subject)
               ->setTextBody($this->body)
               ->send();
            return true;
         }
         return false;
      }
   }
?>

Шаг 1 — Создайте функцию с именем actionShowContactModel в SiteController со следующим кодом.

public function actionShowContactModel() { 
   $mContactForm = new \app\models\ContactForm(); 
   $mContactForm->name = "contactForm"; 
   $mContactForm->email = "user@gmail.com"; 
   $mContactForm->subject = "subject"; 
   $mContactForm->body = "body"; 
   var_dump($mContactForm); 
}

В приведенном выше коде мы определяем модель ContactForm , устанавливаем атрибуты и отображаем модель на экране.

Шаг 2. Теперь, если вы введете http: // localhost: 8080 / index.php? R = site / show-contact-model в адресной строке веб-браузера, вы увидите следующее.

Показать контактный вид

Если ваша модель выходит из yii \ base \ Model , то все ее переменные-члены (публичные и нестатические) являются атрибутами. В модели ContactForm есть пять атрибутов — имя, адрес электронной почты, тема, тело, verifyCode, и вы можете легко добавлять новые.

Метки атрибутов

Вам часто нужно отображать метки, связанные с атрибутами. По умолчанию метки атрибутов автоматически генерируются методом yii \ base \ Model :: generateAttributeLabel () . Чтобы вручную объявить метки атрибутов, вы можете переопределить метод yii \ base \ Model :: attributeLabels () .

Шаг 1 — Если вы откроете http: // localhost: 8080 / index.php? R = site / contact, вы увидите следующую страницу.

Форма обратной связи

Обратите внимание, что метки атрибутов совпадают с их именами.

Шаг 2 — Теперь измените функцию attributeLabels в модели ContactForm следующим образом.

public function attributeLabels() {
   return [
      'name' => 'name overridden',
      'email' => 'email overridden',
      'subject' => 'subject overridden',
      'body' => 'body overridden',
      'verifyCode' => 'verifyCode overridden',
   ];
}

Шаг 3. Если вы снова откроете http: // localhost: 8080 / index.php? R = site / contact , вы заметите, что метки изменились, как показано на следующем рисунке.

Контакт изменен

Сценарии

Вы можете использовать модель в разных сценариях. Например, когда гость хочет отправить контактную форму, нам нужны все атрибуты модели. Когда пользователь хочет сделать то же самое, он уже вошел в систему, поэтому нам не нужно его имя, так как мы можем легко взять его из БД.

Чтобы объявить сценарии, мы должны переопределить функцию scenarios () . Он возвращает массив, ключи которого являются именами сценариев, а значения являются активными атрибутами . Активные атрибуты — это те, которые нужно проверить. Они также могут быть массово назначены .

Шаг 1 — Измените модель ContactForm следующим образом.

<?php
   namespace app\models;
   use Yii;
   use yii\base\Model;
   /**
   * ContactForm is the model behind the contact form.
   */
   class ContactForm extends Model {
      public $name;
      public $email;
      public $subject;
      public $body;
      public $verifyCode;
      const SCENARIO_EMAIL_FROM_GUEST = 'EMAIL_FROM_GUEST';
      const SCENARIO_EMAIL_FROM_USER = 'EMAIL_FROM_USER';
      public function scenarios() {
         return [
            self::SCENARIO_EMAIL_FROM_GUEST => ['name', 'email', 'subject', 
               'body', 'verifyCode'],
            self::SCENARIO_EMAIL_FROM_USER => ['email' ,'subject', 'body', 
               'verifyCode'],
         ];
      }
      /**
      * @return array the validation rules.
      */
      public function rules() {
         return [
            // name, email, subject and body are required
            [['name', 'email', 'subject', 'body'], 'required'],
            // email has to be a valid email address
            ['email', 'email'],
            // verifyCode needs to be entered correctly
            ['verifyCode', 'captcha'],
         ];
      }
      /**
      * @return array customized attribute labels
      */
      public function attributeLabels() {
         return [
            'name' => 'name overridden',
            'email' => 'email overridden',
            'subject' => 'subject overridden',
            'body' => 'body overridden',
            'verifyCode' => 'verifyCode overridden',
         ];
      }
      /**
      * Sends an email to the specified email address using the information 
         collected by this model.
      * @param  string  $email the target email address
      * @return boolean whether the model passes validation
      */
      public function contact($email) {
         if ($this -> validate()) {
            Yii::$app->mailer->compose()
               ->setTo($email)
               ->setFrom([$this->email => $this->name]) 
               ->setSubject($this->subject) 
               ->setTextBody($this->body)
               ->send();
            return true;
         }
         return false;
      }
   }
?>

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

Шаг 2 — Теперь измените функцию actionContact SiteController .

public function actionContact() {
   $model = new ContactForm();
   $model->scenario = ContactForm::SCENARIO_EMAIL_FROM_GUEST;
   if ($model->load(Yii::$app->request->post()) && $model->
      contact(Yii::$app->params ['adminEmail'])) {
         Yii::$app->session->setFlash('contactFormSubmitted');  
         return $this->refresh();
   }
   return $this->render('contact', [
      'model' => $model,
   ]);
}

Шаг 3 — Введите http: // localhost: 8080 / index.php? R = site / contact в веб-браузере. Вы заметите, что в настоящее время требуются все атрибуты модели.

Обязательные атрибуты модели

Шаг 4. Если вы измените сценарий модели в actionContact , как указано в следующем коде, вы обнаружите, что атрибут name больше не требуется.

$model->scenario = ContactForm::SCENARIO_EMAIL_FROM_USER;

Изменить сценарий

Massive Assignment

Массивное присваивание — это удобный способ создания модели из нескольких входных атрибутов с помощью одной строки кода.

Строки кода —

$mContactForm = new \app\models\ContactForm; 
$mContactForm->attributes = \Yii::$app->request->post('ContactForm');

Вышеуказанные строки кода эквивалентны —

$mContactForm = new \app\models\ContactForm; 
$postData = \Yii::$app->request->post('ContactForm', []); 
$mContactForm->name = isset($postData['name']) ? $postData['name'] : null; 
$mContactForm->email = isset($postData['email']) ? $postData['email'] : null; 
$mContactForm->subject = isset($postData['subject']) ? $postData['subject'] : null; 
$mContactForm->body = isset($postData['body']) ? $postData['body'] : null;

Первый намного чище. Обратите внимание, что массовое назначение применяется только к безопасным атрибутам . Это просто атрибуты текущего сценария, перечисленные в функции scene () .

Экспорт данных

Модели часто необходимо экспортировать в разных форматах. Чтобы преобразовать модель в массив, измените функцию actionShowContactModel в SiteController

public function actionShowContactModel() {
   $mContactForm = new \app\models\ContactForm();
   $mContactForm->name = "contactForm";
   $mContactForm->email = "user@gmail.com";
   $mContactForm->subject = "subject";
   $mContactForm->body = "body";
   var_dump($mContactForm->attributes);
} 

Введите http: // localhost: 8080 / index.php? R = site / show-contact-model в адресной строке, и вы увидите следующее —

Экспорт данных

Чтобы преобразовать модель в формат JSON , измените функцию actionShowContactModel следующим образом:

public function actionShowContactModel() {
   $mContactForm = new \app\models\ContactForm();
   $mContactForm->name = "contactForm";
   $mContactForm->email = "user@gmail.com";
   $mContactForm->subject = "subject";
   $mContactForm->body = "body";
   return \yii\helpers\Json::encode($mContactForm);
}

Вывод браузера

{
   "name":"contactForm",
   "email":"user@gmail.com",
   "subject":"subject",
   "body":"body ",
   "verifyCode":null
}

Важные моменты

Модели обычно намного быстрее, чем контроллеры в хорошо разработанном приложении. Модели должны —