Обновить
12
Виктор Павлович Гришко@Yeah

Пользователь

16
Подписчики
Отправить сообщение
Тормозит дичайшим образом…
Так как include выполняется в контексте класса, то внутри шаблона будет доступен $this. Следовательно реализуйте __get и используйте $this->{имя переменной} в шаблонах. Использование просто переменных очень плохо, так как в случае неопределения какой-либо переменной, она будет взята из глобальной области видимости. Я даже не говорю про notice, если эта переменная вообще нигде неопределена
>> Тут немного не понял основной мысли. Имеется ввиду передача данных в шаблон и их последующая выгрузка в переменные?

Да. Есть __set — этот метод модифицирует внутреннее состояние класса, а метод show по логике не должен модифицировать внутреннее состояние класса, так как его назначение на основании предопределенного внутреннего состояния выдать какой-то результат. Вы же создали путаницу, добавив в метод show изменение внутреннего состояния класса. Это не смертельно, но это очень нелогично и вносит путаницу. Лучше создать метод assign, который будет заносить данные из массива.
На самом деле ужасно. Не забывайте, что та статья — 2007 года. Для 2007 года там высказываются вполне современные идеи. Но сейчас на дворе уже 2011 год и ТАК писать — право, стыдно. По пунктам:

>> Вместо PDO написал некий класс, названный мной как Active Records

Это напоминает мне «принципиально новую ОС с нескучными обоями». Мало того, что PDO написан и оттестирован десятками разработчиков, так он еще и в разы быстрее, так как это native расширение. Итог: сэкономили на спичках.

>> Переписан немного класс Template, добавлена возможность делать вложенные шаблоны

Убейте меня, не нашел там вложенных шаблонов.

>> extract($this->vars);

Это сразу премия Дарвина в ИТ. Попробуйте ради интереса выполнить что-то типа $this->template->show('main_template', array('_get' => 'OLOLO'));

Template::__set определена, __get — нет. Зачем передавать еще один массив в функцию show? Почему вместо этого не сделать метод assign? Зато вызывается __set при передаче массива — лишний код и лишние вызовы.

Существование переменных и индексов автора вообще не интересует. Пробуем: $this->template->show('main_template', null);

Полная чехарда с ошибками и исключениями. Не найден каталог? Это исключение. Не найден файл? А это уже просто ошибка. Где логика? А в Loader::library, если нет файла — просто false возвращаем…

Везде обычный include. Таким образом $router->delegate()->delegate(); гарантированно вызывает падение.

Передача параметров по ссылке в метод класса!!! И это в 5-м PHP!!!

>> $class = 'Controller_'. $controller;
$controller = new $class();

Отлично! А если файл есть, а класса в нем нет? Где проверки на существование класса?

Зачем в контроллере loader и template сделаны публичными?

function __set($varname, $value) {
$this->$varname = $value;
return true;
}


Что еще за бред?
Под семеркой, если не под админом сидишь, то для доступа к Program Files нужны права админа. Так что это не проблемы IDEA
Надо под админом запустить — тогда обновляет сама. Во всяком случае для PhpStorm — так.
Метод неплох, но есть несколько замечаний:
1. Инициализация кэша не должна выполняться внутри данного класса. У ZF для этого есть bootstrap и конфиг. Лучше сделать статические методы getCache и setCache, которые бы запускались из bootstrap.
2. Было бы неплохо указать, что этот класс работает только в PHP 5.3
Может кто-то не знает, как переводится «conspiracy»?
Сайт сделан отвратно. Ежесекундные запросы на update.php для получения статуса — это бред. Почему нельзя было для этого использовать Socket.io — непонятно.
Ну и безапелляционный flash — тоже не радует. Могли бы в духе стартапа сделать поддержку html5 audio.
Скорее всего из-за flashblock'а — /js/jquery.swfobject.1-1-1.min.js как бы намекает на это.
[conspiracymode=«On»]
Это гугл спровоцировал утечку, чтобы потом показать, что: «Пользователям Google Chrome ничего не угрожает так как он проверяет валидность сертификатов онлайн.»
Огнелису еще обновляться нужно, а пользователи Хрома уже вне опасности.
[conspiracymode=«Off»]
Если говорить о совсем нормальном варианте, то вот. Это, скажем так, мое видение DDD. Вдохновлялся у Мэтью:

weierophinney.net/matthew/archives/202-Model-Infrastructure.html
weierophinney.net/matthew/archives/201-Applying-ACLs-to-Models.html
weierophinney.net/matthew/archives/200-Using-Zend_Form-in-Your-Models.html

Если же говорить о конкретно вашем случае, с использованием только Table Gateway, то я бы делал так:

Пусть нам изначально ставят задачу вывести список юзеров. Нет ничего проще.

class Users extends Zend_Db_Table_Abstract
{
    protected $_primary = 'id';
    
    public function getAll()
    {
        return $this->fetchAll();
    }
}

Казалось бы, ну что за идиотизм делать такую функцию, кому она нужна, если можно напрямую вызвать fetchAll???
Но тут начальство ставит нам задачу: выводить список юзеров + количество комментариев каждого юзера.
Все, что нам нужно, слегка модифицировать наш метод:
class User extends Zend_Db_Table_Row_Abstract
{
    protected $_commentsCount = 0;

    public function init()
    {
        parent::init();
        if (array_key_exists('commentsCount', $this->_data)) {
            $this->_commentsCount = (int)$this->_data['commentsCount'];
            unset($this->_data['commentsCount']);
        }
    }

    public function getCommentsCount()
    {
        return $this->_commentsCount;
    }
}

class Users extends Zend_Db_Table_Abstract
{
    protected $_primary = 'id';
    
    protected $_rowClass = 'User';

    public function getAll()
    {
        $select = $this->select()
            ->from(array('u' => 'Users'))
            ->joinLeft(array('c' => 'Comments'), 'c.user_id = u.id', array(
                                                   'commentsCount' => new Zend_Db_Expr('COUNT(c.*)')
                                               ))
            ->group('u.id');
        return $this->fetchAll($select);
    }
}

При таком решении никаких изменений в контроллере не потребуется.
Не нравятся join'ы??? Можно и без них, если правильно настроено кэширование:
class User extends Zend_Db_Table_Row_Abstract
{
    protected $_commentsCount;

    public function getCommentsCount()
    {
        if ($this->_commentsCount === null) {
            /**
             * @var Zend_Db_Table_Abstract $comments
             */
            $comments = $this->getTable()->getReference('Comments');
            $select = $comments->select()
                ->columns(array('commentsCount' => new Zend_Db_Expr('COUNT(*)')))
                ->where('user_id = ?', $this->id);
            $row = $comments->fetchRow($select);
            $this->_commentsCount = (int)$row->commentsCount;
        }
        return $this->_commentsCount;
    }
}

class Users extends Zend_Db_Table_Abstract
{
    protected $_primary = 'id';

    protected $_rowClass = 'User';

    public function getAll()
    {
        return $this->fetchAll();
    }
}
Как показывает опыт, новички сначала слизывают один в один, а потом уже в процессе работы начинают думать и понимать — в этом и заключается понятие «профессиональный рост». Да, в простейшем случае внутри getAllProducts будет только вызов fetchAll, но если позже потребуется добавить доп. функционал, то разработчик без опыта не станет рефакторить вызовы fetchAll в getAllProducts, а начнет добавлять копипастом новый функционал прямо в контроллер (или где у него будет этот fetchAll вызываться). Так вот если новичок все равно будет слизывать, так пусть он уже слизывает нормальный код и правильные подходы.

И я автора не отчитывал. Просто высказал свое мнение.
Ну и как? Дали им денег?
Два последних моих суждения, возможно, и не относятся к теме статьи, но я настаиваю на том, что применение fetchAll — это плохо. И совершенно ни к чему учить новичков сходу такой не очень хорошей практике. Впрочем, статья — ваша, а мнение — мое. Решать вам и вашим читателям.
Использовать встроенные методы Zend_Db_Table_Abstract — плохая практика с точки зрения моделирования. Лучше добавлять в свой класс методы getAllProducts и т.д.
А вообще, еще лучше не пользоваться напрямую Zend_Db, а отделять модель и маппер.

А кэш к таким моделям лучше делать декоратором — тогда вручную вызывать кэшер не нужно будет.
Еще node_dev: github.com/fgnass/node-dev

Перезапускает процесс node при каждом изменении исходников. Удобно применять на машине разработчика.
Отображается: «икт». Что имелось в виду: «кит» или «тик»?
Использую для просмотра запросов к БД и их профилирования. ZF и Doctrine отлично с ним работают.

Информация

В рейтинге
Не участвует
Откуда
Харьков, Харьковская обл., Украина
Дата рождения
Зарегистрирован
Активность