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.
- Не запросы прямого доступа.
- Не слишком много сценариев.