Где взять видео-уроки по Symfony2 (Starting in Symfony2 Tutorial)

Время деньги

В виду постоянной нехватки времени, начать разбираться в новом фреймворке бывает не то чтобы сложно, а просто некогда. Поиски в сети не оставили меня равнодушным к урокам озвученным приятным женским голосом Лианны Пелхам из KnpLabs. Даже имея совсем начальный уровень владения PHP, уроки возымеют для вас вполне понятное изложение.
Первый урок, который я прослушал и посмотрел длился целый час, но пролетел он как несколько минут.
Абсолютно не скучно Лианна рассказала про основы Symfony и объяснила структуру.
Объясняется пользование доктриной, создание бандлов и прочие фишечки при работе с Symfony.
Одним словом, рекомендую. Не смотря на весь мой опыт и знакомство с Symfony до этого, я очень был рад, что есть такой туториал. Ознакомьтесь с PHP and Symfony Tutorials и оставь свой отзыв.

С чего бы MySQL server has gone away?

Пытался импортировать дамп базы данных на свой MySQL сервер, но никак не получалось, на многих записях сервер сообщал следующее: MySQL server has gone away. Сообщение забавное, но в чём же проблема, почему некоторые жирные insert-ы не проходили.

Не проходили пакеты. В my.cnf прописал:
max_allowed_packet = 200M

Всё заработало.

Чистка в Мазурино

Чисто там где не сорят.

В парке Мазурино проведена акция “чистый лес”, организованная группой “чистильщиков”.
Добровольцами был предоставлен транспорт для вывоза. С каждым разом, мы находим мусора всё больше и больше.

В очередной раз мы убрали мусор за какими-то засранцами:
Парк Мазурино

Включаем в PHPWord (Cyrillic) Кириллицу

Решение проблемы русских букв в .docx документах создаваемых библиотекой PHPWord

Завсегда пользовался этой прелестной библиотекой (PHPWord), но в основном для англоязычных проектов, и был сокрушён горем, когда попытался сохранить русский текст в .docx файле.

Пол дня потратил на анализ библиотеки, но не сразу понял, что они дважды делают utf8_encode(), благодаря чему текст нечитаем и было не ясно в какую кодировку конвертировать.

Поиски причины

Спасла команда: mb_detect_encoding($string);
Я вставил $string в проверку кодировки.
Затем сделал
$string = utf8_decode($string);
и ещё раз проверил,
echo mb_detect_encoding($string);
После раскодирования utf8, $string оставался всё равно в кодировке UTF-8.
Раскодировав второй раз, уже виднелась голая ASCII.

Решение

Находим файл PHPWord/Section.php и закомментируем все строчки, в которых есть utf8_encode(). Какой смысл что-то кодировать в UTF-8, если данные сразу приходят в UTF-8. Обращаем лишь внимание на строчку с переменной $givenText; Её комментировать не нужно. Можно прописать только $givenText = $text;

По итогу получается файлик:

_sectionCount = $sectionCount;
        $this->_settings = new PHPWord_Section_Settings();

        if (!is_null($settings) && is_array($settings)) {
            foreach ($settings as $key => $value) {
                if (substr($key, 0, 1) != '_') {
                    $key = '_' . $key;
                }
                $this->_settings->setSettingValue($key, $value);
            }
        }
    }

    /**
     * Get Section Settings
     *
     * @return PHPWord_Section_Settings
     */
    public function getSettings()
    {
        return $this->_settings;
    }

    /**
     * Add a Text Element
     *
     * @param string $text
     * @param mixed $styleFont
     * @param mixed $styleParagraph
     * @return PHPWord_Section_Text
     */


    public function addText($text, $styleFont = null, $styleParagraph = null)
    {

        $givenText = $text;
        //$givenText = utf8_encode($text);
        $text = new PHPWord_Section_Text($givenText, $styleFont, $styleParagraph);
        $this->_elementCollection[] = $text;
        return $text;
    }

    /**
     * Add a Link Element
     *
     * @param string $linkSrc
     * @param string $linkName
     * @param mixed $styleFont
     * @param mixed $styleParagraph
     * @return PHPWord_Section_Link
     */
    public function addLink($linkSrc, $linkName = null, $styleFont = null, $styleParagraph = null)
    {
        //$linkSrc = utf8_encode($linkSrc);
        if (!is_null($linkName)) {
            //$linkName = utf8_encode($linkName);
        }

        $link = new PHPWord_Section_Link($linkSrc, $linkName, $styleFont, $styleParagraph);
        $rID = PHPWord_Media::addSectionLinkElement($linkSrc);
        $link->setRelationId($rID);

        $this->_elementCollection[] = $link;
        return $link;
    }

    /**
     * Add a TextBreak Element
     *
     * @param int $count
     */
    public function addTextBreak($count = 1)
    {
        for ($i = 1; $i <= $count; $i++) {
            $this->_elementCollection[] = new PHPWord_Section_TextBreak();
        }
    }

    /**
     * Add a PageBreak Element
     */
    public function addPageBreak()
    {
        $this->_elementCollection[] = new PHPWord_Section_PageBreak();
    }

    /**
     * Add a Table Element
     *
     * @param mixed $style
     * @return PHPWord_Section_Table
     */
    public function addTable($style = null)
    {
        $table = new PHPWord_Section_Table('section', $this->_sectionCount, $style);
        $this->_elementCollection[] = $table;
        return $table;
    }

    /**
     * Add a ListItem Element
     *
     * @param string $text
     * @param int $depth
     * @param mixed $styleFont
     * @param mixed $styleList
     * @param mixed $styleParagraph
     * @return PHPWord_Section_ListItem
     */
    public function addListItem($text, $depth = 0, $styleFont = null, $styleList = null, $styleParagraph = null)
    {
        //$text = utf8_encode($text);
        $listItem = new PHPWord_Section_ListItem($text, $depth, $styleFont, $styleList, $styleParagraph);
        $this->_elementCollection[] = $listItem;
        return $listItem;
    }

    /**
     * Add a OLE-Object Element
     *
     * @param string $src
     * @param mixed $style
     * @return PHPWord_Section_Object
     */
    public function addObject($src, $style = null)
    {
        $object = new PHPWord_Section_Object($src, $style);

        if (!is_null($object->getSource())) {
            $inf = pathinfo($src);
            $ext = $inf['extension'];
            if (strlen($ext) == 4 && strtolower(substr($ext, -1)) == 'x') {
                $ext = substr($ext, 0, -1);
            }

            $iconSrc = PHPWORD_BASE_PATH . 'PHPWord/_staticDocParts/';
            if (!file_exists($iconSrc . '_' . $ext . '.png')) {
                $iconSrc = $iconSrc . '_default.png';
            } else {
                $iconSrc .= '_' . $ext . '.png';
            }

            $rIDimg = PHPWord_Media::addSectionMediaElement($iconSrc, 'image');
            $data = PHPWord_Media::addSectionMediaElement($src, 'oleObject');
            $rID = $data[0];
            $objectId = $data[1];

            $object->setRelationId($rID);
            $object->setObjectId($objectId);
            $object->setImageRelationId($rIDimg);

            $this->_elementCollection[] = $object;
            return $object;
        } else {
            trigger_error('Source does not exist or unsupported object type.');
        }
    }

    /**
     * Add a Image Element
     *
     * @param string $src
     * @param mixed $style
     * @return PHPWord_Section_Image
     */
    public function addImage($src, $style = null)
    {
        $image = new PHPWord_Section_Image($src, $style);

        if (!is_null($image->getSource())) {
            $rID = PHPWord_Media::addSectionMediaElement($src, 'image');
            $image->setRelationId($rID);

            $this->_elementCollection[] = $image;
            return $image;
        } else {
            trigger_error('Source does not exist or unsupported image type.');
        }
    }

    /**
     * Add a by PHP created Image Element
     *
     * @param string $link
     * @param mixed $style
     * @return PHPWord_Section_MemoryImage
     */
    public function addMemoryImage($link, $style = null)
    {
        $memoryImage = new PHPWord_Section_MemoryImage($link, $style);
        if (!is_null($memoryImage->getSource())) {
            $rID = PHPWord_Media::addSectionMediaElement($link, 'image', $memoryImage);
            $memoryImage->setRelationId($rID);

            $this->_elementCollection[] = $memoryImage;
            return $memoryImage;
        } else {
            trigger_error('Unsupported image type.');
        }
    }

    /**
     * Add a Table-of-Contents Element
     *
     * @param mixed $styleFont
     * @param mixed $styleTOC
     * @return PHPWord_TOC
     */
    public function addTOC($styleFont = null, $styleTOC = null)
    {
        $toc = new PHPWord_TOC($styleFont, $styleTOC);
        $this->_elementCollection[] = $toc;
        return $toc;
    }

    /**
     * Add a Title Element
     *
     * @param string $text
     * @param int $depth
     * @return PHPWord_Section_Title
     */
    public function addTitle($text, $depth = 1)
    {
        //$text = utf8_encode($text);
        $styles = PHPWord_Style::getStyles();
        if (array_key_exists('Heading_' . $depth, $styles)) {
            $style = 'Heading' . $depth;
        } else {
            $style = null;
        }

        $title = new PHPWord_Section_Title($text, $depth, $style);

        $data = PHPWord_TOC::addTitle($text, $depth);
        $anchor = $data[0];
        $bookmarkId = $data[1];

        $title->setAnchor($anchor);
        $title->setBookmarkId($bookmarkId);

        $this->_elementCollection[] = $title;
        return $title;
    }

    /**
     * Create a new TextRun
     *
     * @return PHPWord_Section_TextRun
     */
    public function createTextRun($styleParagraph = null)
    {
        $textRun = new PHPWord_Section_TextRun($styleParagraph);
        $this->_elementCollection[] = $textRun;
        return $textRun;
    }

    /**
     * Get all Elements
     *
     * @return array
     */
    public function getElements()
    {
        return $this->_elementCollection;
    }

    /**
     * Create a new Header
     *
     * @return PHPWord_Section_Header
     */
    public function createHeader()
    {
        $header = new PHPWord_Section_Header($this->_sectionCount);
        $this->_header = $header;
        return $header;
    }

    /**
     * Get Header
     *
     * @return PHPWord_Section_Header
     */
    public function getHeader()
    {
        return $this->_header;
    }

    /**
     * Create a new Footer
     *
     * @return PHPWord_Section_Footer
     */
    public function createFooter()
    {
        $footer = new PHPWord_Section_Footer($this->_sectionCount);
        $this->_footer = $footer;
        return $footer;
    }

    /**
     * Get Footer
     *
     * @return PHPWord_Section_Footer
     */
    public function getFooter()
    {
        return $this->_footer;
    }
}

?>

Пользуйтесь наздоровье.

Теория разбитых окон

1980-х годах Нью-Йорк представлял собой адский ад. Там совершалось более 1 500 тяжких преступлений КАЖДЫЙ ДЕНЬ. 6-7 убийств в сутки. Ночью по улицам ходить было опасно, а в метро рисковано ездить даже днем. Грабители и попрошайки в подземке были обычным делом. Грязные и сырые платформы едва освещались. В вагонах было холодно, под ногами валялся мусор, стены и потолок сплошь покрыты граффити.

Вот что рассказывали о нью-йоркской подземке:

«Выстояв бесконечную очередь за жетоном, я попытался опустить его в турникет, но обнаружил, что монетоприемник испорчен. Рядом стоял какой-то бродяга: поломав турникет, теперь он требовал, чтобы пассажиры отдавали жетоны лично ему. Один из его дружков наклонился к монетоприемнику и вытаскивал зубами застрявшие жетоны, покрывая все слюнями. Пассажиры были слишком напуганы, чтобы пререкаться с этими ребятами: «На, бери этот чертов жетон, какая мне разница!» Большинство людей миновали турникеты бесплатно. Это была транспортная версия дантова ада».

Город был в тисках самой свирепой эпидемии преступности в своей истории.

Но потом случилось необъяснимое. Достигнув пика к 1990-му году, преступность резко пошла на спад. За ближайшие годы количество убийств снизилось на 2/3, а число тяжких преступлений – наполовину. К концу десятилетия в метро совершалось уже на 75 % меньше преступлений, чем в начале. По какой-то причине десятки тысяч психов и гопников перестали нарушать закон.

Что произошло? Кто нажал волшебный стоп-кран и что это за кран?[]

Его название – «Теория разбитых окон». Канадский социолог Малкольм Гладуэлл в книге «Переломный момент» рассказывает:«Разбитые окна» — это детище криминалистов Уилсона и Келлинга. Они утверждали, что преступность — это неизбежный результат отсутствия порядка. Если окно разбито и не застеклено, то проходящие мимо решают, что всем наплевать и никто ни за что не отвечает. Вскоре будут разбиты и другие окна, и чувство безнаказанности распространится на всю улицу, посылая сигнал всей округе. Сигнал, призывающий к более серьезным преступлениям».

Гладуэлл занимается социальными эпидемиями. Он считает, что человек нарушает закон не только (и даже не столько) из-за плохой наследственности или неправильного воспитания. Огромное значение на него оказывает то, что он видит вокруг. Контекст.

Нидерландские социологи подтверждают эту мысль (источник). Они провели серию любопытных экспериментов. Например, такой. С велосипедной стоянки возле магазина убрали урны и на рули велосипедов повесили рекламные листовки. Стали наблюдать – сколько народа бросит флаеры на асфальт, а сколько постесняется. Стена магазина, возле которого припаркованы велосипеды,
была идеально чистой.

Листовки бросили на землю 33% велосипедистов.

Затем эксперимент повторили, предварительно размалевав стену бессодержательными рисунками.

Намусорили уже 69 % велосипедистов.

Но вернемся в Нью-Йорк в эпоху дикой преступности. В середине 1980-х в нью-йоркском метрополитене поменялось руководство. Новый директор Дэвид Ганн начал работу с… борьбы против граффити. Нельзя сказать, что вся городская общественность обрадовалась идее. «Парень, займись серьезными вопросами – техническими проблемами, пожарной безопасностью, преступностью… Не трать наши деньги на ерунду!» Но Ганн был настойчив:

«Граффити — это символ краха системы. Если начинать процесс перестройки организации, то первой должна стать победа над граффити. Не выиграв этой битвы, никакие реформы не состоятся. Мы готовы внедрить новые поезда стоимостью в 10 млн. долларов каждый, но если мы не защитим их от вандализма – известно, что получится. Они продержатся один день, а потом их изуродуют».

И Ганн дал команду ощищать вагоны. Маршрут за маршрутом. Состав за составом. Каждый чертов вагон, каждый божий день. «Для нас это было как религиозное действо», — рассказывал он позже.

В конце маршрутов установили моечные пункты. Если вагон приходил с граффити на стенах, рисунки смывались во время разворота, в противном случае вагон вообще выводили из эксплуатации. Грязные вагоны, с которых еще не смыли граффити, ни в коем случае не смешивались с чистыми. Ганн доносил до вандалов четкое послание.

«У нас было депо в Гарлеме, где вагоны стояли ночью, – рассказывал он. – В первую же ночь явились тинейджеры и заляпали стены вагонов белой краской. На следующую ночь, когда краска высохла, они пришли и обвели контуры, а через сутки все это раскрашивали. То есть они трудились 3 ночи. Мы ждали, когда они закончат свою «работу». Потом мы взяли валики и все закрасили. Парни расстроились до слез, но все было закрашено снизу доверху. Это был наш мэссидж для них: «Хотите потратить 3 ночи на то, чтобы обезобразить поезд? Давайте. Но этого никто не увидит»…

В 1990-м году на должность начальника транспортной полиции был нанят Уильям Браттон. Вместо того, чтобы заняться серьезным делом – тяжкими преступлениями, он вплотную взялся за… безбилетников. Почему?

Новый начальник полиции верил – как и проблема граффити, огромное число «зайцев» могло быть сигналом, показателем отсутствия порядка. И это поощряло совершение более тяжких преступлений. В то время 170 тысяч пассажиров пробирались в метро бесплатно. Подростки просто перепрыгивали через турникеты или прорывались силой. И если 2 или 3 человека обманывали систему, окружающие (которые в иных обстоятельствах не стали бы нарушать закон) присоединялись к ним. Они решали, что если кто-то не платит, они тоже не будут. Проблема росла как снежный ком.

Что сделал Браттон? Он выставил возле турникетов по 10 переодетых полицейских. Они выхватывали «зайцев» по одному, надевали на них наручники и выстраивали в цепочку на платформе. Там безбилетники стояли, пока не завершалась «большая ловля». После этого их провожали в полицейский автобус, где обыскивали, снимали отпечатки пальцев и пробивали по базе данных. У многих при себе оказывалось оружие. У других обнаружились проблемы с законом.

«Для копов это стало настоящим Эльдорадо, – рассказывал Браттон. – Каждое задержание было похоже на пакет с поп-корном, в котором лежит сюрприз. Что за игрушка мне сейчас попадется? Пистолет? Нож? Есть разрешение? Ого, да за тобой убийство!.. Довольно быстро плохие парни поумнели, стали оставлять оружие дома и оплачивать проезд».

В 1994 году мэром Нью-Йорка избран Рудольф Джулиани. Он забрал Браттона из транспортного управления и назначил шефом полиции города. Кстати, в Википедии написано, что именно Джулиани впервые применил Теорию разбитых окон. Теперь мы знаем, что это не так. Тем не менее, заслуга мэра несомненна – он дал команду развить стратегию в масштабах всего Нью-Йорка.

Полиция заняла принципиально жесткую позицию по отношению к мелким правонарушителям. Арестовывала каждого, кто пьянствовал и буянил в общественных местах. Кто кидал пустые бутылки. Разрисовывал стены. Прыгал через турникеты, клянчил деньги у водителей за протирку стекол. Если кто-то мочился на улице, он отправлялся прямиком в тюрьму.

Уровень городской преступности стал резко падать – так же быстро, как в подземке. Начальник полиции Браттон и мэр Джулиани объясняют: «Мелкие и незначительные, на первый взгляд, проступки служили сигналом для осуществления тяжких преступлений».

Цепная реакция была остановлена. Насквозь криминальный Нью-Йорк к концу 1990-х годов стал самым безопасным мегаполисом Америки.

Волшебный стоп-кран сработал.
Источник: http://wowfacts.net/teoriya-razbityx-okon/

Перерасход трафика урезал скорость сервера до 10 Мбит/c

Немного недотянул до конца июня (2011) месяца вспомогательный сервер doblox.ru и упала скорость до 10 мегабит в секунду, всвязи с перерасходом трафика.
Количество одновременных просмотров упало с 70-ти до 10-ти и стало очень некомфортным для зрителя.
Будем исправлять положение покупкой дополнительного трафика или путём установки дополнительного зеркала.
Словом, к платному запуску doblox.ru мы пока ещё не готовы. Нужно запустить ещё как минимум три зеркала в разных географических зонах.

Zend Framework: как я прикручивал Zend_Paginator (постраничный вывод)

Начиная изучать Zend Framework самопроизвольно собрался макет для управления таблицой и её содержимыми в базе данных. Сейчас расскажу как именно.
Первые шаги с Zend я делал по примерам Роба Аллена.
В частности по этому учебному материалу.

Предлагалось собрать табличку альбомов. Добавлять, редактировать и удалять в ней записи. И в общем-то всё.
Обычный вывод на страницу списка альбомов.
Захотелось, изучить как работает Zend_Paginator и сделать постраничный вывод.
Правда, я чтобы не обезьянничать на 100%, решил назвать в своём примере не Albums, а Pages. (ну типа пишу свою CMS и у меня уже страницы правятся из базы, админка на ZF)

И как только я начал искать как же прикрутить пейджинг или пейджинэйтор, всё время нарывался на статьи и примеры далёкие от абстрактной модели работы с базами данных.
Предлагаю использовать Zend_Db_Table_Abstract вместо привычно встречающихся в примерах Zend_Db_Table и Zend_Db_Select.

К файлам темплейтов не придираться, мне тоже не нравится мешанина php-кода + HTML, но такое вот понятие MVC у Zend.

У меня получилось вот что.

Controller (application/controllers/IndexController.php) выглядит так:

_getParam('page');

        $select = $pages->select();
        $result = $this->view->table = $pages->fetchAll($select)->toArray();
        $paginator = new Zend_Paginator(new Zend_Paginator_Adapter_Array($result));
        $paginator->setItemCountPerPage($num);
        $paginator->setCurrentPageNumber($page);
        $paginator->setView($this->view);
        $this->view->paginator = $paginator;

    }






    public function addAction()
    {
        // action body
		$this->view->pageTitle = "Add";
		$this->view->pageKeywords = "keywords";
		$this->view->pageDescription = "description";
		
		
		$form = new Application_Form_Page();
		$form->submit->setLabel('Add');
		$this->view->form = $form;
		
		
		if ($this->getRequest()->isPost()) {
		$formData = $this->getRequest()->getPost();
		if ($form->isValid($formData)) {
		$artist = $form->getValue('artist');
		$title = $form->getValue('title');
		$creation_date = $form->getValue('creation_date');
		$pages = new Application_Model_DbTable_Pages();
		$pages->addPage($artist, $title,$creation_date);
		$this->_helper->redirector('index');
		} else {
		$form->populate($formData);
		}
		}
		
		
    }

    public function editAction()
    {
        // action body
		
			$this->view->pageTitle = "Edit";
						
			$form = new Application_Form_Page();
			$form->submit->setLabel('Save');
			$this->view->form = $form;
			
			if ($this->getRequest()->isPost()) {
				$formData = $this->getRequest()->getPost();
			if ($form->isValid($formData)) {
				
				$id = (int)$form->getValue('id');
				$artist = $form->getValue('artist');
				$title = $form->getValue('title');
		        $creation_date = $form->getValue('creation_date');
				
				$pages = new Application_Model_DbTable_Pages();
				$pages->updatePage($id, $artist, $title,$creation_date);
				$this->_helper->redirector('index');
			} else {
			$form->populate($formData);
			}
			} else {
			$id = $this->_getParam('id', 0);
			if ($id > 0) {
			$pages = new Application_Model_DbTable_Pages();
			$form->populate($pages->getPage($id));
			}
			}
			
			
			
    }

	
	
    public function deleteAction()
    {
        
		$this->view->pageTitle = "Delete";
		
		
		if ($this->getRequest()->isPost()) {
			$del = $this->getRequest()->getPost('del');
		if ($del == 'Yes') {
			$id = $this->getRequest()->getPost('id');
			$pages = new Application_Model_DbTable_Pages();
			$pages->deletePage($id);
		}
			$this->_helper->redirector('index');
		} else {
			$id = $this->_getParam('id', 0);
			$pages = new Application_Model_DbTable_Pages();
			$this->view->page = $pages->getPage($id);
		}
    }
}

Шаблон (application/views/scripts/pagination.phtml) пагинатора:

pageCount) { ?>
previous)) { ?> < | < | pagesInRange as $page) { if ($page != $this->current) { ?> | | next)) { ?> > >

 

DB модель (application/models/DbTable/Pages.php)

fetchRow('id = ' . $id);
                if (!$row) {
                throw new Exception("Could not find row $id");
                }

    			return $row->toArray();
			}
			
			public function addPage($artist, $title, $creation_date)
			{
                $data = array(
                'artist' => $artist,
                'title' => $title,
                'creation_date' => $creation_date,
                );
    			$this->insert($data);
			}
			
			public function updatePage($id, $artist, $title,$creation_date)
			{
                $data = array(
                'artist' => $artist,
                'title' => $title,
                'creation_date' => $creation_date,
			);
			    $this->update($data, 'id = '. (int)$id);
			}
			
			public function deletePage($id)
			{
			    $this->delete('id =' . (int)$id);
			}
	



}

Здесь к пейджингу относится только название таблицы в базе данных.

 

И сам (application/views/scripts/index/index.phtml):

title = "My pages";
$this->headTitle($this->title);
?>

Add new page

paginator)) { ?> paginator as $item) {?>
Title Artist Date  
Edit Delete
paginationControl($this->paginator); ?>

Вот эти знания мне пригодились в реализации постраничного вывода на Zend Framework.

P.S.:
Если, у кого-то не получилось, пишите в комменты вопросы.