Pull to refresh

Comments 46

CActiveRecord::attributeLabels()

выполняется при каждому обращению к названию атрибута, если у Вас представлении форма из 10 атрибутов, то этот метод выполнится соответствующее число раз.

Я к тому чтоб Вы осторожнее относились к рекомендациям по этому поводу.

Тем более что перевод это совсем не дело Model, а скорее View слоя.

ЗЫ: Не до конца прочитал, уже ночь, может еще завтра будут комментарии. Спокойной ночи.
/**
 * Благодаря этому методу можно не определять его явно в каждой модели-наследнике.
 * Спасибо PHP 5.3 с его get_called_class()
 */
public static function model ($className = __CLASS__) {

    return parent::model(get_called_class());

}


А в классах-наследниках останется только добавить строку в PHPDoc для автодополнение в IDE:
 * @method static {model_name} model() model(string $className = __CLASS__)
О, model() в PHPDoc получился лишний.
Да, вы правы, я сам использую такой метод. Но при подходе, который указал автор и который показан в примерах на оф сайте данный метод имеет смысл переопределять только в конечном классе.

Кстати, не объясните более подробно, какие именно надо прописать PHPDoc что бы класс, возвращаемый model(), определялся корректно. Я что то в ваш пример не понял.
вместо {model_name} надо прописать собственно сам класс.
понял, теперь разобрался. спасибою
Метод в таком виде недопустим, т.к. перестает работать код
$post = ActiveRecord::model('Post')->find();

более гибкий подход
public static function model ($className = null) {

    return parent::model($className ?: get_called_class());

}
Я использую такой подход:

$models = Post::model()->find();


На мой взгляд так читабельность выше.
Из своей практики, переопределяю метод getAttributeLabel() и уже там подставляю Yii::t()
Скажите, а зачем вы переопределяете метод model() в классе ActiveRecord? Его все равно необходимо переопределить в каждом наследнике. Можетэтот класс стоит вообще объявить как абстрактный?

И если вам не трудно, пишите чуть более сжато. Я понимаю, тема для новичков, но статья вышла немаленькая, а разобранно не так много. Лучше пусть поконкретнее, но о большем рассказать.

И раз уж статья для совсем новичков, хорошо бы приводить ссылки на документацию по мере повествования.

Спасибо за статью.
Когда только начинал работать с Yii тоже создавал наследника CActiveRecord и от него уже наследовал все другие модели. Да и вообще любил порасширять фреймворк везде где только можно через наследование. Потом понял что слишком увлекся, код приложения стал несколько отличается от типичного на Yii, причем не всегда в лучшую сторону. Обычно Behavior является более предпочтительным решением.
На самом деле очень полезно наследовать свои классы не от фреймворка, а от своих прослоек. Не все, конечно, но большинство.

У меня к примеру есть для таких классов отдельная директория. в том же ActiveRecord переопределены магические методы, которые позволяют обращаться к вот_таки_полям таблицы в горбатомСтиле.
В классе Controller объявлены методы для форматированной передачи данных на клиент при ajax запросах и методы для автоматического подключения assets файлов.

Так же обычно такие классы имеют абистрактные методы, чем задают основу архитектуры.
А зачем метод model() переопределять в каждом наследнике? Я так понимаю это наследние php 5.2, где не было late static binding?
Да, именно так. Для 5.3+ можно переопределить model в базовом классе и больше не париться.
К сожалению 5.2 еще стоит на серверах у клиентов (иногда там CentOS), а полномочий на обновление нам не дают, так что этот подход рекомендован разработчиками Yii и работает для обратной совместимости. Также у новичков с этим могут возникнуть проблемы при разворачивании.
Соболезную. Но все же большая часть цивилизованного мира уже на 5.4+
Использование сеттеров в моделях конечно хорошо, но, стоит не забывать что populateRecord про них ничего не знает
populateRecord и не должен знать ничего о них. populateRecord нужен для данных из таблицы, без дополнительных манипуляций над ними. геттеры и сеттеры, наоборот нужны для дополнительными манипуляциями над данными из таблицы или виртуальными атрибутами.
Некоторые вещи можно автоматизировать используя giix extension. Например сразу будет создаваться базовая модель и наследующая ее модель в которой можно дописывать свои методы.
Раз уж интересуетесь мнением общественности, выскажу пожелание. Напишите серию статей для новичков, типа «что такое Yii», «что такое MVC», как это все работает, как работать с базами данных и т.д. Обязательно все с примерами, но не как здесь. Не надо постить куски кода с которыми не понятно что делать. Пример должен быть цельным, т.е. вот код модели, вот контроллер и вьюха, копипастю это все себе в проект и вижу результат. Чем подробнее все разжуете (вплоть до того в какой папке и с каким названием файл создать) тем лучше.
Я только на этой неделе начал разбираться с yii обрадовался увидев эту статью, однако совершенно ничего здесь не понял…

P.S. Я в курсе, что эта статья для бывалых, я просто высказал пожелание :)
серию статей для новичков

Извиняюсь, забыл выделить
Предположим, что мы поддались соблазну и в одной миграции создали таблицу и индексы в ней. Тогда при опечатке в функции создания индекса миграция будет прервана выброшенным прерыванием, и повторно запустить миграцию не получится так как таблица уже создана. Тут если есть возможность следует либо использовать механизм транзакций, либо делать множество мелких миграций.

safeUp/safeDown же. Обрамляет миграцию в транзакцию.
транзакции работают только для CRUD операций, при изменении схемы базы данных вам safeUp/safeDown не помогут.
Иногда над моделью производятся мелкие операции над небольшим количеством атрибутов, такие методы можно начинать с префикса make и такие методы могут выполнять сохранение модели внутри себя

Не уверен, что хорошая идея мешать в одном методе изменение состояния и его сохранение.
public function setStatus(int $status)

Разве скалярные типы можно использовать для контроля типов аргументов?
увы нет. насколько я помню почти все предложения в rfc изьяты/отклонены.
В этом случае Yii выбросит Recoverable error
Вы может веткой ошиблись? Yii ничего не может поделать с отсутствием тайп-хинтинга для скалярных типов.
нет не ошибся
Вот такой код:
function geta(int $a){
    return $a;
};

echo geta("test");


при вызове без YII выводит такое сообщение
PHP Catchable fatal error: Argument 1 passed to geta() must be an instance of int, string given, called in /home/my/in.php on line 7 and defined in /home/my/in.php on line 3

Если этот код будет внутри приложения YII то он будет показано сообщение Recoverable error

PHP 5.3.10-1ubuntu3.9 with Suhosin-Patch (cli) (built: Dec 12 2013 04:27:25) Copyright (c) 1997-2012 The PHP Group Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies
фраза instance of int означает что у вас должен быть класс int, экземпляр которого и должен передаваться.
class int{

}

function foo(int $a) {
}

foo('test');// выбросит исключение
foo(42); // выбросит исключение
foo(new int()); // отработает
вы правы, я исправлю в записи.
Я бы добавил то, что надо в названии модели добавлять слово Model, как делается это с контроллерами, на пример UserModel.php
Так не будем путать модели с другими всякими классами. Получается очень удобно.
С какими другими? Для других добавляем суффикс, обозначающий их роль в приложении, а классі модели моделируют предметную область, и к приложению как бі не относятся.
Компоненты, классы расширений и т.д… что может быть мало классов в приложении, что за дурацкий вопрос…
жаль не могу минусовать, а то как-то не справедливо получается…
Ну так тем, которые выполняют служебную роль и присваиваем суффикс, отражающий эту роль. А модель предметной области — это основное в приложении, незачем его ставить наравне со всем остальным.
P.S. Про справедливость не понял. Я вас не минусовал, если вы на это намекаете.
Не пойму о чем вы… то пишите, что к приложению не относятся, то пишите, что модель это основное в приложении… определитесь, пожалуйста…
У нас есть классы приложения команд, контроллеров, у них мы пишем Command, Controller, речь о том, что модели тоже нужно обозначать Model, так гораздо удобней
PS, да, подумал что минусовали вы, извиняюсь
Модель относится к уровню бизнес-логики, а не к уровню логики приложения или отображения. Бизнес-логика основное в приложение, без нёё оно точно никому не нужно. В общем на вкус и цвет, но мне удобнее что основными сущностями приложения оперируешь без суффиксов, показывающих что они основные.
Такое писать в базовом классе не правильно:
    public function getId()
    {
        return $this->id;
    }

Далеко не все таблицы имеет поле id и могут иметь составной PK.

Так же мне кажется довольно сомнительным использовать для всего геттеры и сеттеры в описанном в статье виде, ибо setAttributes эти геттеры и сеттеры использовать не будет. Что бы этот подход работал нужно использовать название поле например, начинающиеся с символа '_' — а это тот ещё изврат.

Так же лишние вызовы методов — это увеличение времени работы приложения, и поэтому такие вызовы должны быть оправданы.
Оправдание простое — абстрагирование от деталей реализации, инкапсуляция, контроль доступа. Даже если в начале ничего не нужно, то потом может понадобится. Имхо, это для использования паблик-свойств нужно обоснование типа «поднимет производительность всего приложения на 10%», а не наоборот.

Ещё раз, это геттеры и сеттеры не будут работать во всяких setAttributes и прочих местах, например при использовании хелпера CHtml::activeTextFiled() и т.д. И получается не понятно, какой прок от них.
лишние вызовы методов

использование магических методов __get/__set намного дороже обходится, и все равно это капля в море. Сомнительно что это может быть узким местом производительности.
Именно поэтому я написал это в конце начиная со слов «Так же», т.е. это не имеет конечно сильное значение.
Sign up to leave a comment.

Articles