В данном разделе опубликована информация, которая призвана решить спорные вопросы и определить порядок действий при их возникновении. Группой разработчиков мы собрали наиболее полный список рекомендаций, который поможет вам в создании новых модулей и приложений на Yii
Бизнес-логике не место в ActiveRecord, контроллере и тем более в представлении. Размещать бизнес-логику необходимо в отдельных классах с говорящими названиями “СущностьДействие”. В результате получаются “худые” контроллер и ActiveRecord. Данный подход повышает читабельность проекта в разы, а также позволяет производить тестирование бизнес-логики.
class UserCreator extends BaseObject
{
public $emailAccept = false;
public $beforeCreateEvent = UserEvent::EVENT_BEFORE_CREATE;
public $afterCreateEvent = UserEvent::EVENT_AFTER_CREATE;
public $validate = true;
public $role = DbManager::ROLE_USER;
protected $model;
/**
* UserCreator constructor.
* @param User $model
* @param array $config
*/
public function __construct(User $model, $config = [])
{
$this->model = $model;
parent::__construct($config);
}
/**
* @return false|User
*/
public function execute()
{
$event = new UserEvent();
Yii::$app->user->trigger($this->beforeCreateEvent, $event);
if(!$event->release) return false;
$transaction = Yii::$app->db->beginTransaction();
try {
if($this->emailAccept) {
$this->model->status = User::STATUS_INACTIVE;
$this->model->generateEmailAcceptToken();
}
$this->model->confirm = true;
$this->model->generateAuthKey();
if ($this->model->save($this->validate)) {
if($this->emailAccept && !self::sendMail($this->model)) {
return false;
}
$role = Yii::$app->authManager->getRole($this->role);
Yii::$app->authManager->assign($role, $this->model->id);
Yii::$app->user->trigger($this->afterCreateEvent, new UserEvent(['userId' => $this->model->id]));
$transaction->commit();
return $this->model;
}
} catch (\Exception $e) {
$transaction->rollBack();
}
return false;
}
/**
* @param User $model
* @return bool
*/
public static function sendMail(User $model)
{
return Yii::$app->mailer->compose([
'html' => '@common/modules/users/mail/emailAcceptToken-html',
'text' => '@common/modules/users/mail/emailAcceptToken-text'
], [
'model' => $model
])
->setFrom(Yii::$app->params['noReplyEmail'])
->setTo($model->email)
->setSubject(Module::t('register_form_email_subject'))
->send();
}
}
beforeSave
, afterSave
, beforeFind
, afterFind
в ActiveRecord для тяжелой бизнес-логики (например, запросы к сторонним ресурсам, парсинг Excel, тяжелых XML файлов и т.д).auth_item
и auth_item_child
в обход миграций. Все обновления в БД осуществляются только посредством оформления миграции.yii\db\Migration
.yii\db\Query
.
$users = (new Query())->select('id')->from('{{%user}}')->all();
Если в проекте используется СУБД MySQL для использования внешних ключей (Foreign keys) и транзакций, в качестве системы хранения данных (Storage engine) должна быть выбрана InnoDB. При создании таблицы в БД необходимо использовать следующую конструкцию:
$tableOptions = null;
if ($this->db->driverName === 'mysql') {
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=InnoDB';
}
$this->createTable('{{%auth2fa}}', [
'id' => $this->primaryKey(),
'user_id' => $this->integer(11)->notNull()->comment('Пользователь'),
'secret_key' => $this->string(16)->notNull()->comment('Секретный ключ'),
'created_at' => $this->integer(11)->comment('Дата создания записи'),
'updated_at' => $this->integer(11)->comment('Дата изменения записи'),
], $tableOptions);
down()
в миграциях обязателен к реализации, если миграция является обратимой. Нежелательно, чтобы метод down возвращал false
.php yii migrate/redo n
.batchInsert()
вместо конструкции, когда вызывается insert()
в цикле (то же касается и консольных алгоритмов).batch()
, each()
вместо all()
(то же касается и консольных алгоритмов).{{%table_name}}
. Это даст возможность использовать префиксы таблиц в БД. При использовании данного шаблона не забудьте применить следующий пункт в кодогенераторе Gii при генерации модели:Html::tag()
, Html::beginTag()
, Html::endTag()
. За счет этого html верстка становится нечитабельной и нет никакой подсветки html тегов.
$textAreaPlaceholder = "ДА\nДа\nда\ny\nYes\nYES\n+";
$valuePlaceholder = "1";
echo Html::beginTag('div', ['class' => 'hidden']);
echo $form->field($model, 'convert')->textarea(['rows' => 6]);
echo Html::endTag('div');
$model->convert = json_decode($model->convert, true);
echo Html::beginTag('table', ['class' => 'table list_table_for_validation_rules']);
echo Html::beginTag('thead');
echo Html::beginTag('tr');
echo Html::tag('th', 'Список возможных значений', ['width' => '48%']);
echo Html::tag('th', 'Заменить на', ['width' => '48%']);
echo Html::tag('th', '', ['width' => '4%']);
echo Html::endTag('tr');
echo Html::endTag('thead');
echo Html::beginTag('tbody');
$help = Html::tag('div', '', ['class' => 'help-block']);
if (is_array($model->convert))
foreach ($model->convert as $listJson) {
echo Html::beginTag('tr');
echo Html::tag('td', Html::textarea('list_replaced_list[]', implode("\n", $listJson['list']), ['rows' => 4, 'class' => 'form-control list_replaced_list', 'placeholder' => $textAreaPlaceholder]) . $help, ['class' => 'list_replaced_list_wrapper']);
echo Html::tag('td', Html::textarea('list_replaced_val[]', $listJson['value'], ['rows' => 4, 'class' => 'form-control list_replaced_val', 'placeholder' => $valuePlaceholder]) . $help, ['class' => 'list_replaced_val_wrapper']);
$button = Html::a(Html::tag('i', '', ['class' => 'fa fa-times']), 'javascript:;', ['class' => 'btn btn-danger remove_list_replaced_val']);
echo Html::tag('td', $button);
echo Html::endTag('tr');
}
echo Html::endTag('tbody');
echo Html::beginTag('tfoot');
echo Html::beginTag('tr');
echo Html::tag('td', Html::textarea('list_replaced_list[]', '', ['rows' => 4, 'class' => 'form-control list_replaced_list', 'placeholder' => $textAreaPlaceholder]) . $help, ['class' => 'list_replaced_list_wrapper']);
echo Html::tag('td', Html::textarea('list_replaced_val[]', '', ['rows' => 4, 'class' => 'form-control list_replaced_val', 'placeholder' => $valuePlaceholder]) . $help, ['class' => 'list_replaced_val_wrapper']);
$button = Html::a(Html::tag('i', '', ['class' => 'fa fa-save']), 'javascript:;', ['class' => 'btn btn-success add_list_replaced_val']);
echo Html::tag('td', $button);
echo Html::endTag('tr');
echo Html::endTag('tfoot');
echo Html::endTag('table');
Общие положения
if ($password) {
$this->password_hash = Yii::$app->security->generatePasswordHash($password);
}
Классы
Константы
Свойства
Методы
getСurrentUser()
.
$foo->bar(
$longArgument,
$longerArgument,
$muchLongerArgument
);
Переменные
Переменная должна наиболее полно описывать представляемую сущность, это значит, что она должна иметь понятное название, по которому можно судить о ее предназначении.
Комментирование - важный аспект разработки приложений на Yii 2. Игнорирование создания понятных комментариев отнимает значительно большего времени при поддержке и командной разработке проектов. Ниже мы привели основные нюансы простановки комментариев в коде, чтобы на выходе можно было сгенерировать удобную и понятную документацию по проекту.
Обратите внимание, что комментарий типа # не используется. Это связано с тем, что на основании оставленных комментариев генерируется документация к разрабатываемому программному продукту.
/**
* Форма редактирования пользователя
*
* @property string $email
* @property string $name
* @property string $surname
* @property string $position
* @property string $password
* @property string $repeatPassword
* @property boolean $sendEmailPassword
* @property boolean $sendEmailRegister
* @property integer $status
* @property UploadedFile $photo
* @property boolean $deletePhoto
* @property string $timezone
* @property string $role
*/
@mixin
для подключенных поведений к классу для того, чтобы PHPStorm знал о методах, реализованных в этих поведениях:Далее описываются константы, если есть, и записываются в верхнем регистре:
/**
* @mixin UploadImageBehavior
* @mixin AccessBehavior
* @mixin MultilingualBehavior
*/
При описании свойства необходимо задать тип данных через
/**
* Тип пользователя: юр. лицо
* @var integer
*/
const TYPE_CORP = 3;
@var
и дать описание:Описание статических свойств:
/**
* @var string Название базы данных
*/
public $database;
Методы могут содержать комментарий родительского метода класса. Это характерезуется
/**
* @var array Индикаторы цен за 6 месяцев
*/
public static $priceSixMonths = [4, 8];
@inheritdoc
параметром. Пример ниже говорит о том, что у метода уже есть комментарий. Читай комментарий родительского метода./** @var \common\modules\content\models\Post $model */
'value' => function($model) {
/** @var \common\modules\document\models\Document $model */
return $model->user->getUsernameWithEmail();
}
'value' => function(Document $model) {
return $model->user->getUsernameWithEmail();
}
Во время проектирования таблиц БД необходимо добавлять комментарии для полей таблиц:
$this->createTable('{{%document}}', [
'id' => $this->primaryKey(),
'author_id' => $this->integer(11)->notNull()->comment('Автор'),
'user_id' => $this->integer(11)->notNull()->comment('Пользователь'),
'name' => $this->string(150)->notNull()->comment('Наименование'),
'filename' => $this->string(50)->notNull()->comment('Файл'),
'size' => $this->string(50)->notNull()->comment('Размер файла'),
'extension' => $this->string(10)->notNull()->comment('Расширение файла'),
'hash' => $this->string(64)->notNull()->comment('Hash файла (SHA-256)'),
'is_active' => $this->smallInteger(1)->notNull()->defaultValue(0)->comment('Видимость'),
'order' => $this->smallInteger()->unsigned()->notNull()->defaultValue(0)->comment('Сортировка'),
'created_at' => $this->integer(11)->notNull()->comment('Дата создания записи'),
'updated_at' => $this->integer(11)->notNull()->comment('Дата обновления записи')
], $tableOptions);
Компонент gii во фреймворке Yii2 позволяет генерировать AR модели для таблиц БД. Установив галочку “Generate Labels from DB Comments”,
мы получим указанные комментарии в методе attributeLabels , который задает метки атрибутов.
public function attributeLabels()
{
return [
'id' => 'ID',
'author_id' => 'Автор',
'user_id' => 'Пользователь',
'name' => 'Наименование',
'filename' => 'Файл',
'size' => 'Размер файла',
'extension' => 'Расширение файла',
'hash' => 'Hash файла (SHA-256)',
'is_active' => 'Видимость',
'order' => 'Сортировка',
'created_at' => 'Дата создания записи',
'updated_at' => 'Дата обновления записи',
];
}
А также название полей появятся в веб-приложении для администрирования СУБД.
Для того, чтобы мы смогли Вам предоставить доступ расскажите немного о себе
Опишите в форме ниже задачу, которую требуется реализовать.