Yii - Модели

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

Атрибуты

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

Давайте посмотрим на 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;
      }
   }
?>

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

public function actionShowContactModel() { 
   $mContactForm = new \app\models\ContactForm(); $mContactForm->name = "contactForm"; 
   $mContactForm->email = "[email protected]"; $mContactForm->subject = "subject"; 
   $mContactForm->body = "body"; var_dump($mContactForm); 
}

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

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

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

Ярлыки атрибутов

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

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

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

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

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

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

Сценарии

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

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

Step 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;
      }
   }
?>

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

Step 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,
   ]);
}

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

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

$model->scenario = ContactForm::SCENARIO_EMAIL_FROM_USER;

Массовое присвоение

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

Строки кода -

$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;

Первый намного чище. Заметить, чтоmassive assignment относится только к safe attributes. Это просто атрибуты текущего сценария, перечисленные вscenario() функция.

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

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

public function actionShowContactModel() {
   $mContactForm = new \app\models\ContactForm();
   $mContactForm->name = "contactForm"; $mContactForm->email = "[email protected]";
   $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 = "[email protected]";
   $mContactForm->subject = "subject"; $mContactForm->body = "body";
   return \yii\helpers\Json::encode($mContactForm);
}

Browser output -

{
   "name":"contactForm",
   "email":"[email protected]",
   "subject":"subject",
   "body":"body ",
   "verifyCode":null
}

Важные точки

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

  • Содержат бизнес-логику.
  • Содержат правила проверки.
  • Содержат атрибуты.
  • Не встраивать HTML.
  • Не запросы прямого доступа.
  • Не слишком много сценариев.