Мы все любим Composer. Он значительно изменил способ как мы создаем PHP приложения, основываясь на маленьких и повторно используемых компонентах, но это создает новые проблемы, особенно когда мы имеем единую точку отказа (SPO).
Метка: kohana
Доработка модулей для Kohana – Doctrine и Doctrine Migrations
В виду того, что проект Kohana вообще закрылся и версию 3.4 c namespace мы наверное никогда не увидим следует вывод – не стоит начинать на ней новые проекты. Но что делать, если приходится поддерживать старые. Не пользоваться же ORM Kohana, ее знание и знание ее особенностей уже ни кому не нужны. Значит надо подключить Doctrine.
Фикс Bootstrap 3 Navigation dropdown submenu и реализация в Zend Framework 2 и Smarty
В новом (относительно) Bootstrap 3 отсутствует возможность по умолчанию для выпадающего меню в навигациии задавать уровень вложенности более чем 2. Т.е. невозможно построить навигацию с бесконечным выпадающим меню используя возможности Bootstrap 3 по умолчанию. Для добавления такой нужной возможности существует следующее решение.
Zend Framework 2 Paginator без Zend MVC
Представим проект, который либо не использует фреймворки, либо к нему подключена ORM DOCTRINE, но у используемого фреймворка/проекта нет адаптера для пагинации с Doctrine.
Kohana и Роут с бесконечным уровнем вложенности каталогов.
В данном посте я хочу сохранить обсуждение и решение проблемы с офф форума Kohana. Проблему обозначаю в первой цитате, решение с подсказки сообщества (использовать коллбеки) во второй, т.е. сам код. Работает для kohana 3.2, для 3.3 надо править, чего я не сделал в виду не надобности. У меня проект на 3.2. :)
Модуль Minion с Kohana 3.3 на Kohana 3.2
В данный момент разрабатываю проект на Kohana. В этом проекте не малую роль играют задания выполняемые через cron. Еще не имея опыта работы с cron и Kohana я думал, что скрипты можно вызывать напрямую, а в контроллере делать проверку Kohana::$is_cli для определения вызова cli. Но как выяснилось существует модуль с версии 3.0, который эволюционировал и в 3.3 стал частью поставки Kohana по умолчанию.
Проблема в том, что Kohana 3.3 внесла некоторые изменения в свой autoload, которые несомненно более удобны. Теперь не обязательно писать классы с заглавной только первой буквой и не обязательно именовать файлы и папки в нижнем регистре. Теперь можно писать так Kohana_CLI, Class_InvalidTask и еще так InvalidTask.php.
Для прикрутки module Minion сначала я хотел было воспользоваться версией для 3.2, которая была загружена Zeelot3k в теги модуля на git. Но там оказалась поделка из более ранней 3.1. В ней используется bash скрипт для вызова index.php с параметрами, когда как в 3.3 minion просто обертка для модуля. Выложенное решение для 3.2 по моему не рабочее, по крайне мере я так и не смог запустить свой task.
1 2 3 4 |
sudo ./minion --task=welcome Task "welcome" does not exist |
После я копировал модуль с 3.3 версии.
Для запуска модуля необходимо переименовать все файлы в директории minion в нижний регистр, включая папки. так же исправить имена файлов и классов по правилам именования Kohana 3.2, т.е. Kohana_CLI на Kohana_Cli и InvalidTask в Invalidtask.
Далее подключить модуль как обычно в Kohana::modules() и исправить index.php в конце на следующий код
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
if (PHP_SAPI == 'cli') // Try and load minion { class_exists('Minion_Task') OR die('Please enable the Minion module for CLI support.'); set_exception_handler(array('Minion_Exception', 'handler')); Minion_Task::factory(Minion_CLI::options())->execute(); } else { echo Request::factory() ->execute() ->send_headers(TRUE) ->body(); } |
И все, должно работать. Создаем в папке /classes/task файл welcome.php с кодом
1 2 3 4 5 6 7 8 |
class Task_Welcome extends Minion_Task { protected function _execute(array $params) { Minion_CLI::write('hello world!'); } } |
Далее вызываем.
1 2 3 4 |
sudo ./minion --task=welcome hello world! |
Темы с вопросами о minion с официального форума:
1
2
3
Так же в решении вопроса мне помог блог участника сообщества biakaveron.
У него можно почитать про модуль подробнее.
GIT REPO: https://github.com/seyfer/minion
UPD: 2014-11-28
Сейчас я пользуюсь стандартным minion для версии 3.2, т.к. у меня возникли некоторые проблемы с совместимостью с другими модулями.
Поэтому я описал пакет вот так
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
{ "type": "package", "package": { "name": "kohana/modules/minion32", "version": "3.2", "source": { "type": "git", "url": "https://github.com/kohana/minion.git", "reference": "k3.2-v1.0" } } }, |
И подключил его в require, а мой портированный с 3.3 удалил. Проект на 3.2. и отлично все работает.
Отлов ошибок, error handler в php
Просто заметка, для сохранения кода и ссылок.
Пользовался в движке не на фреймворке вот этим:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
ob_start('fatal_error_handler'); function fatal_error_handler($buffer){ $error=error_get_last(); if($error['type'] == 1){ // type, message, file, line $newBuffer='<html><header><title>Fatal Error </title></header> <style> .error_content{ background: ghostwhite; vertical-align: middle; margin:0 auto; padding:10px; width:50%; } .error_content label{color: red;font-family: Georgia;font-size: 16pt;font-style: italic;} .error_content ul li{ background: none repeat scroll 0 0 FloralWhite; border: 1px solid AliceBlue; display: block; font-family: monospace; padding: 2%; text-align: left; } </style> <body style="text-align: center;"> <div class="error_content"> <label >Fatal Error </label> <ul> <li><b>Line</b> '.$error['line'].'</li> <li><b>Message</b> '.$error['message'].'</li> <li><b>File</b> '.$error['file'].'</li> </ul> <a href="javascript:history.back()"> Back </a> </div> </body></html>'; return $newBuffer; } return $buffer; } |
Взято отсюда: http://stackoverflow.com/questions/277224/how-do-i-catch-a-php-fatal-error
Вставил код и автоматически хочу нажать ctrl+f – это форматирование кода в нетбианс. Далее был бы ctrl+s …
Для более продвинутого отлова ошибок можно заценить на примере Kohana в этой теме на kohanaframework.org.
Создавалась мной, хотя ответ был дан в другой теме намного ранее. Не все было понятно.
В двух словах всевозможные ошибки перенаправляются на обработку в свой класс
1 2 3 4 5 6 7 8 |
//Исключения ловим через класс EHandler set_exception_handler(array('EHandler', 'exception_handler')); //Ошибки ловим через стандартный метод Kohana set_error_handler(array('Kohana', 'error_handler')); //Падение ловим через класс EHandler register_shutdown_function(array('EHandler', 'shutdown_handler')); |
Ну а далее на контроллер.
Проблемы с проектированием базы данных на основе ORM (Kohana)
Сначала перечисляю сущности.
sуstems – некие системы.
preferences – некоторые настройки, сокращенно pref
pref имеет разные типы, например настройки кеша (cache) и тамаута (timeout). Таким образом pref можно записывать в одну таблицу с полями id, value, type или в две разные таблицы – prefcache и preftimeout с той же структурой. Идем дальше.
Поля таблицы system – id, name. Осуществляется связь многие ко многим через таблицу prefs_systems с полями: id_system, id_pref, type (можно вынести сюда в случае отдельных таблиц prefcache и preftimeout.
И вот зачем две таблицы pref, я хочу на каждую делать свой ORM, т.е. есть базовый ORM_Pref extends ORM и от него наследуются ORM_Prefcache и ORM_Preftimeot. Каждый работает со своей таблицей, а общие настройки в базовом классе.
В этом случае в каждой ORM прописываются связи $_has_many. В случае ORM pref все очевидно, по одной записи связей $_has_many к ORM_System. В случае с описанием ORM_System получается такая конструкция (додумался пока писал).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
protected $_has_many = array( 'prefcache' => array( 'model' => 'orm_prefcache', 'foreign_key' => 'id_system', 'through' => 'prefs_systems', 'far_key' => 'id_pref', ), 'preftimeot' => array( 'model' => 'orm_preftimeout', 'foreign_key' => 'id_system', 'through' => 'prefs_systems', 'far_key' => 'id_pref', ), ); |
Вопросы:
- Нормально ли я придумал структуру?
- Могу ли я базовый класс ORM_Pref объявить абстрактным (т.к. у него нет привязанной таблицы и его не надо создавать) ?
- Можно ли как-то улучшить мою структуру? Если все выше правильно, то при добавления нового типа настроек я должен буду прописать связь в ORM_System, это не удобно.
UPD. 02.04.2014
Спустя полтора года мой пост выше кажется мне уже простым вопросом новичка. Решил добавить сюда еще решение по ORM
Получение свойства ORM сразу с UNCOMPRESS.
Проблема: Можно ли как-то через ORM извлекать данные, которые были записаны через COMPRESS () в mysql в BLOB?
В кохановском ОРМ такого нет. Приходится писать функции в ORM типа
1 2 3 4 5 6 7 8 9 10 11 |
public function find_uncompress() { $result = DB::select("*", array(DB::expr("UNCOMPRESS(response)"), "response")) ->from($this->_table_name) ->where("id", "=", $this->pk()) ->execute()->as_array(); return $result; } |
Задачу решает, но было бы приятнее просто указать в каких-то правилах как извлекать столбец, как фильтры после извлечения, только эти во время.
Решение нашел коллега. В нужной ORM модели надо переопределить
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
protected function _build($type) { if($type==Database::SELECT) { $this->select(array( DB::expr("UNCOMPRESS(request)"),'requestUncompress')); $this->select(array( DB::expr("UNCOMPRESS(result)"),'resultUncompress')); } parent::_build($type); } |
В данном случае поля request и result сжаты, извлекаются под псевдонимами с распаковкой и будут доступны $model->requestUncompress, например.