Замечу, что мы — команда разработки десктопных приложений для Windows, поэтому сборка и выкладка docker-образов пока что не про нас (вот ASP.NET Core команда — это другое дело, может скоро и их затащим).
В общем:
Кое-где закидываем через SSH (job-а запускается под linux и scp-шкой закидывает нужные файлы).
Кое-где кидаем через WebDAV (job-а запускается также под Linux и у нас кто-то, примонтировав через davfs2 закидывает rsync-ом, а кто-то типа меня через кастомный скрипт на powershell core).
А непосредственно доставкой до клиента после выкладки на публичный сервер занимается самописный обновлятор (сделанный примерно во времена .NET 4). Так исторически сложилось + пока функционала более, чем хватает.
Обновлятор при запуске ПО и/или раз в некоторый интервал времени лезет на сервер, смотрит нет ли новой версии и, если есть, скачивает её инсталлер и даёт пользователю выбор: запустить сразу или запустить после закрытия программы (эта же идея, к примеру, в Paint.NET реализована).
Если же говорить о конкретно вашем случае, с использованием только 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();
}
}
для блокировки достаточно атомарной операции добавления ключа (которая фейлится, если такой ключ уже существует):
while (true) {
if ($mc->add('lock', getmypid())) {
try {
// ... work work work
} catch (Exception $e) { // no 'finally' in PHP =(
$mc->delete('lock');
throw $e;
}
$mc->delete('lock');
break;
}
usleep(rand(10, 1000));
}
А себе я взял BMW 535d GT, которая на самом деле — 7-ка фактически (и даже больше места сзади для пассажиров) и по начинке идентична 7-ке — вот только BMW специально поставила ее классом ниже дабы не перебивать продажи 7-ки (и убрали «сверхважную» опцию — массаж на задних сидениях, при том что спереди массаж оставили — тобишь те кто ездят сзади реально все же пойдут и купят 7-ку ;)) )
Короче — «дурят» везде и разводят на деньги за шильдик. Но пока что те кто реально думают и изучают (при этом не испытывают необходимости в показухе) — могут потратить сильно меньше денег но получить то-же самое (а то и больше).
Под понятие художественного приема попадает не только легкий отход от прямого перевода, но также локализация, подгон под реалии времени унд прочие вещи. Чем руководствовались в данном случае авторы перевода, лично я НЕ знаю — спросите у них. Но вполне возможно, что это было оправдано.
Вы — потребитель, вам элементарно неизвестны и не понятны мотивы людей, занимающихся переводами профессионально. Ну а раз так, то потребляйте молча, без публичной демонстрации дилетантства и нелепых примеров, природа которых вам не ясна.
Кешировани смарти, к сожалению, весьма глючная штука, приводящая, иногда, к непредвиденным результатам. Ждем финала Смарти3, хотя более подходящее решение уже найдено:
В нашем частном случае, мы статику кешируем через memcache и nginx отдает ее оттуда напрямую. Если не попал в кеш — проваливаемся в бекенд, который генерирует контент и сохраняет его в memcache
При этом имеем:
— возможность отдавать всю «статику» практически моментально
— при потере кеша он быстро восстанавливается
— динамические блоки собираются nginx через SSI (с предварительной проверкой на такую же закешированность в мемкеше). при этом собираются они параллельно и в случае отсутствия закешированного значения запросы «проваливаются» на разные бекенды одновременно (снижение нагрузки на каждый отдельно-взятый бекенд)
С осликом другая ситуация. Если вы опытный технолог, то проблем с осликом мало (все явные баги ослика давно изучены и описаны + есть куча вариантов их профиксить (conditional comments, expressions, behavior, filters, hasLayout, хаки наконец).
С Оперой совсем другая песня. Когда встречаешь какой-нибудь баг в Опере то практически всегда, во-первых, не понимаешь из-за чего так, во-вторых, сложно найти триггер бага, в-третьих, тупо не знаешь как фиксить да и вариантов особых нет, хаков для Оперы рабочих практически не существует. В JS еще можно сделать что-то типа if (window.opera)… а в CSS остается только переверстывать. А если еще учесть, что опера довольно часто обновляется, и что с каждой новой версией багов, как правило, становится больше, то это просто кошмар.
Плюс, у меня сложилось стойкое ощущение, что у них регрессивные и старые баги (типа глюков display:inline-block у элементов с position отличным от static, не всегда происходящим repaint/reflow, глюков с регулярными выражениями, глюков с overflow:hidden) имеют низший приоритет. Я точно знаю, что баги эти все по 10 раз зарепортены. Невозможно так долго на это забивать.
Бюрократия есть. А знаете, кто ее развел? Именно такой планктон, который не желает шевелиться и делает все, что бы было меньше работы и меньше нагрузок.
Где как на самом деле.
Замечу, что мы — команда разработки десктопных приложений для Windows, поэтому сборка и выкладка docker-образов пока что не про нас (вот ASP.NET Core команда — это другое дело, может скоро и их затащим).
В общем:
А непосредственно доставкой до клиента после выкладки на публичный сервер занимается самописный обновлятор (сделанный примерно во времена .NET 4). Так исторически сложилось + пока функционала более, чем хватает.
Обновлятор при запуске ПО и/или раз в некоторый интервал времени лезет на сервер, смотрит нет ли новой версии и, если есть, скачивает её инсталлер и даёт пользователю выбор: запустить сразу или запустить после закрытия программы (эта же идея, к примеру, в Paint.NET реализована).
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, то я бы делал так:
Пусть нам изначально ставят задачу вывести список юзеров. Нет ничего проще.
Казалось бы, ну что за идиотизм делать такую функцию, кому она нужна, если можно напрямую вызвать fetchAll???
Но тут начальство ставит нам задачу: выводить список юзеров + количество комментариев каждого юзера.
Все, что нам нужно, слегка модифицировать наш метод:
При таком решении никаких изменений в контроллере не потребуется.
Не нравятся join'ы??? Можно и без них, если правильно настроено кэширование:
Ненамного, но все же проще.
Унификация.
А себе я взял BMW 535d GT, которая на самом деле — 7-ка фактически (и даже больше места сзади для пассажиров) и по начинке идентична 7-ке — вот только BMW специально поставила ее классом ниже дабы не перебивать продажи 7-ки (и убрали «сверхважную» опцию — массаж на задних сидениях, при том что спереди массаж оставили — тобишь те кто ездят сзади реально все же пойдут и купят 7-ку ;)) )
Короче — «дурят» везде и разводят на деньги за шильдик. Но пока что те кто реально думают и изучают (при этом не испытывают необходимости в показухе) — могут потратить сильно меньше денег но получить то-же самое (а то и больше).
Бентли — это фольксваген фаэтон. Только за шильдик и другую «внешность» прибавка к цене в два раза.
Фольсксваген и ауди (и порш) очень много платформ — идентичны.
Как пример — фольксваген туарег, audi Q7 и порш кайен — это одно и то же практически, только опять же по цене отличается ;)
Засим — верить в то что бентли лучше ауди — это чаще всего самовнушение на уровне «я ж такие бабки заплатил!»
Вы — потребитель, вам элементарно неизвестны и не понятны мотивы людей, занимающихся переводами профессионально. Ну а раз так, то потребляйте молча, без публичной демонстрации дилетантства и нелепых примеров, природа которых вам не ясна.
В нашем частном случае, мы статику кешируем через memcache и nginx отдает ее оттуда напрямую. Если не попал в кеш — проваливаемся в бекенд, который генерирует контент и сохраняет его в memcache
При этом имеем:
— возможность отдавать всю «статику» практически моментально
— при потере кеша он быстро восстанавливается
— динамические блоки собираются nginx через SSI (с предварительной проверкой на такую же закешированность в мемкеше). при этом собираются они параллельно и в случае отсутствия закешированного значения запросы «проваливаются» на разные бекенды одновременно (снижение нагрузки на каждый отдельно-взятый бекенд)
С Оперой совсем другая песня. Когда встречаешь какой-нибудь баг в Опере то практически всегда, во-первых, не понимаешь из-за чего так, во-вторых, сложно найти триггер бага, в-третьих, тупо не знаешь как фиксить да и вариантов особых нет, хаков для Оперы рабочих практически не существует. В JS еще можно сделать что-то типа if (window.opera)… а в CSS остается только переверстывать. А если еще учесть, что опера довольно часто обновляется, и что с каждой новой версией багов, как правило, становится больше, то это просто кошмар.
Плюс, у меня сложилось стойкое ощущение, что у них регрессивные и старые баги (типа глюков display:inline-block у элементов с position отличным от static, не всегда происходящим repaint/reflow, глюков с регулярными выражениями, глюков с overflow:hidden) имеют низший приоритет. Я точно знаю, что баги эти все по 10 раз зарепортены. Невозможно так долго на это забивать.
Инструменты » Настройки » Содержимое
затем во Шрифты и цвета выбрать размер больше чем стандартные 16