Успях най-нкарая да отключа четвъртото ядро на моя Phenom II X3 710 процесор. Бройката, с която разполагам не е от най-читавите и не носи много на clock. Все пак успях да го стабилизирам с отключено четвърто ядро на 3.4 GHz.
How to calculate the difference between two dates, in full calendar months using Zend_Date
- Zend_Date::setOptions(array('format_type' => 'php'));
- $start = new Zend_Date('2013-01-31');
- $end = new Zend_Date('2013-06-30');
- $result = $end->toString('Y') * 12 + $end->toString('n') – $start->toString('Y') * 12 – $start->toString('n');
- if ($start->addMonth($result)->compare($end) == 1) {
- $result = $result – 1;
- }
- var_dump($result);
Как работят декораторите в Zend_Form
На практика декораторите в Zend Form са един доста удобен, мощен и полезен инструмент. С тях можем да направим всяка една форма, да изглежда точно така, както е зададена от дизайнерите на сайта. Причината да си блъскаме главата с декораторите е основно една – веднъж постигнали желаната визия на формата, забравяме за HTML-а. Zend_Form ще се грижи вместо нас за създаването на HTML-а, обработването и показването на грешките. Това е особено полезно, когато имаме сайт с например 10 или повече форми с еднаква структура. Тук наблягам на думата структура – формите могат да съдържат различни елементи, но HTML структурата им да е еднаква. Това означава, че се използват едни и същи тагове за показване на грешките или за визуализиране на заглавието на елемента например. Zend_Form прилага различни декоратори за различните елементите. Като цяло, за по-голямата част от елементите се прилгат следните декоратори:
ViewHelper
Errors
HtmlTag (<dd>)
Label (with wrapping <dt> tag)
Ето и как изглежда HTMl-а за един от елементите, генериран посредством декораторите по подразбиране:
- <dt id="name-label"><label for="name" class="required">Your name</label></dt>
- <dd id="name-element">
- <input type="text" name="name" id="name" value="" />
- <ul class="errors"><li>Value is required and can't be empty</li></ul></dd>
Това, което се случва е много просто е повече от елементарно. Трябва да се отбележи, че генерирането на HTML-а става от вътре на вън. С други думи първо се създавата input елементът. Грижата за това има ViewHelper декораторът. Резултат след изпълнението на ViewHelper декоратора, може да се види по-долу.
След това се добавят грешките, ако има такива разбира се. За това се грижи Errors декораторът. Ето и как ще изглежда генерираният HTML след прилагането на Errors декоратора.
- <input type="text" name="name" id="name" value="" />
- <ul class="errors"><li>Value is required and can't be empty</li></ul>
Всичко това се обвива в dd таг посредсвтом HtmlTag декоратора:
- <dd id="name-element">
- <input type="text" name="name" id="name" value="" />
- <ul class="errors"><li>Value is required and can't be empty</li></ul></dd>
Накрая се добавя label-а, обвит в dt таг. Грижа за това има Label декораторът. Това е резултатът (отново), който се получава след прилагането на всички декоратори.
- <dt id="name-label"><label for="name" class="required">Your name</label></dt>
- <dd id="name-element">
- <input type="text" name="name" id="name" value="" />
- <ul class="errors"><li>Value is required and can't be empty</li></ul></dd>
Освен декоратори за елементите, има и декоратори, които се прилагат към формата, след генерирането на всички елементи. Ето ги и тях (по подразбиране).
FormElements
HtmlTag (<dl>)
Form
Първият – FormElements, се грижи за рендирането на елементите. Резултатът се обвива в <dl> таг посредством втория декоратор – HtmlTag. Накрая се прилага Form декораторът, който обвива всичко във <form> таг. Ето как би изглеждала една форма с три полета (name, email, phone) и един submit бутон, генерирана посредством Zend_Form, с декораторите по подразбиране.
- <form enctype="application/x-www-form-urlencoded" action="" method="post"><dl class="zend_form">
- <dt id="name-label"><label for="name" class="required">Your name</label></dt>
- <dd id="name-element">
- <input type="text" name="name" id="name" value="" />
- <ul class="errors"><li>Value is required and can't be empty</li></ul></dd>
- <dt id="email-label"><label for="email" class="required">Your email</label></dt>
- <dd id="email-element">
- <input type="text" name="email" id="email" value="test@test.com" /></dd>
- <dt id="phone-label"><label for="phone" class="required">Your phone number</label></dt>
- <dd id="phone-element">
- <input type="text" name="phone" id="phone" value="1111" /></dd>
- <dt id="submit-label"> </dt><dd id="submit-element">
- <input type="submit" name="submit" id="submit" value="Save changes" /></dd></dl></form>
Zend View – output на XML файл
Какво е XML едва ли е нужно да се обяснява. На всеки що годе запознат с компютри му се е налагало да го използва, на мен също. Най-често се случва да описвам някакви конфигурационни променливи необходими за стартирането на някакъв third party софтуер. Пресен пример е едно slideshow писано на flash, което се настройваше посредством XML файл. Налагаше се да опиша пълния път до всички картинки, използвани в slideshow-то. Тук изникна следният проблем – свързан с това, че сайтът върху който работех първо се стартираше на демо адрес от рода на demo.domain.com и ако всичко беше наред с него се прехвърляше на domain.com. Проблемът се изразява в това, че пътят до картинките трябва да се промени (съответно и xml файлът) при прехвърлянето от demo.domain.com към domain.com. Изключително досадна и ненужна задача, предвид това, че вече сме дефинирали като константа URL-а върху който работи сайтът. За де избегна преправянето на този XML файл направих направих нов action, който да се грижи единствено и само за XML-а, съответно го прекарах и през Zend View, за да мога да сложа константата с URL-а.
- class IndexController extends Zend_Controller_Action
- {
- public function slideshowAction()
- {
- $this->_helper->layout()->disableLayout();
- $this->_helper->viewRenderer->setNoRender(true);
- $view = new Zend_View();
- $view->setScriptPath(APPLICATION_PATH . '/views/scripts/index/');
- $content = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>";
- $content .= $view->render('slideshow.phtml');
- header('Content-Type: text/xml');
- echo $content;
- }
- }
Прекалено бавен Zend_Db_Table!
Днес изгубих известно време в чудене, защо заявките към базата, които минават през Zend_Db_Table са толкова бавни. Оказа се, че за да работи Zend_Db_Table му е необходима структурата на базата. За целта се изпълняват много на брой DESCRIBE заявки. Всичко това е добре описано в документацията, но аз стигнах до него по трудния начин. Проблемът се решава с кеширане. Само за сравнение, броят на заявките които се изпълняваха на една от страниците върху които работя преди кеширането бяха около 1800, а след това паднаха до 800. Както сами виждате има смисъл да се кешира и дори е задължително, когато заявките са много на брой.
Две думи ще кажа и за Zend_Db_Profiler, защото именно него използвах, за да хвана проблема. Доста полезна библиотека, особено когато трябва да се направи някакъв анализ на изпълняваните заявки. Удачно решение е след приключването на всички заявки (зареждането на страницата, така да се каже) да се използва Zend_Db_Profiler и посредством него да разберем колко и какви заявки са изпълнявани. Аз си направих един controller plugin за целта.
- class myLibs_Controller_Plugin_DbProfiler extends Zend_Controller_Plugin_Abstract {
- public function dispatchLoopShutdown()
- {
- $registry = Zend_Registry::getInstance();
- $dbh = $registry->get('dbAdapter');
- $profiler = $dbh->getProfiler();
- var_dump($profiler->getTotalElapsedSecs());
- var_dump($profiler->getTotalNumQueries());
- $longestTime = 0;
- $longestQuery = null;
- foreach ($profiler->getQueryProfiles() as $query) {
- if ($query->getElapsedSecs() > $longestTime) {
- $longestTime = $query->getElapsedSecs();
- $longestQuery = $query->getQuery();
- }
- }
- var_dump($longestTime);
- var_dump($longestQuery);
- }
- }
След това модифицирах леко Bootstrap-a, така че да стартирам db profiler-а и да регистрирам plugin-а.
