Итак, разработчики ветки 3.1.x решили, с одной стороны, не отказываться от своих обещаний выдать релиз к Новому Году, а с другой — не публиковать сыроватый дистрибутив. В результате получаем объявление о выпуске Release Candidate под номером 1. Документации конечно еще нет, поэтому предлагаю рассмотреть новые возможности самостоятельно.
Разделение объектов Request, Request_Client и Response
Как мы помним, самым главным изменением, ознаменовавшим создание ветки 3.0 Shadowhand‘ом, было выделение класса Request
, собравшего в себе все, что связано с собственно выполнением основного запроса приложения. Ранее все это было аккуратно размазано между ядром (класс Kohana
) и объектом Router
с использованием событий. Новый класс взял на себя сбор параметров текущего запроса (информация о клиенте-инициаторе, выбранный роут и т.д.), обработку собственно запроса, и хранение результатов работы (заголовки и тело ответа). Данные изменения позволили легко реализовать множественные вызовы для HMVC, но сам класс все-таки получился избыточным. Поэтому появление новых классов в ветке 3.1 выглядит логичным.
Общий алгоритм работы приложения выглядит так:
1. Создается объект Request
(через factory($uri)
)
2. В зависимости от содержимого переменной $uri
(если не передано, то используется текущий URI, т.е. создается основной запрос) создается объект Request_Client
, либо внешний (Request_Client_External
), либо внутренний (Request_Client_Internal
).
3. В методе execute()
объекта Request
происходит передача управления объекту Request_Client
, вызывается метод execute()
. В качестве параметра передается текущий объект Request
, он используется в основном для получения информации о параметрах для запуска (например, данные роутинга для внутренних запросов и URL для внешних). Далее пути расходятся в зависимости от типа запроса:
3.1. Request_Client_Internal
выполняет знакомые нам функции — определяется контроллер, в нем сперва вызывается метод before()
, затем искомый метод-экшен, а затем уже after()
.
3.2. Request_Client_External
пытается загрузить указанный при создании запроса URL всеми тремя известными ему способами: через PECL_HTTP, CURL или stream_* + fopen()
. Способы указаны в порядке убывания приоритета, но ведь не всегда установлен CURL, не говоря уж о PECL_HTTP… Вместе с запросом отправляются куки (если указаны именно для этого экземпляра Request
) и заголовки.
4. Результат работы запроса попадает в объект Response
, хранящийся в текущем Request
‘е. Собственно $request->execute()
возвращает именно объект Response
.
Класс Request
Что нового:
- Результат работы запроса хранится в
$_response
в виде объектаResponse
. Чтобы его получить, используется вызов методаrender()
, либо просто преобразование к строке (напримерecho $request
). - Класс
Request
сам никаких запросов не отправляет. Для этого есть объект классаRequest_Client
, хранящийся в свойстве$_client
. Получить его можно через методget_client()
— странно, что не простоclient()
, как-то выбивается из общего стиля. Уже в него вынесен методexecute()
, который ранее был в самомRequest
(а точнее говоря, вRequest
он остался, но там он занимается просто перенаправлением действия клиенту). - Запросы можно кэшировать. Если при создании запроса передан второй параметр — объект
Cache
, то данный запрос будет пробовать найти себя в этом кэше, а если не найдет, то запишет туда свойResponse
. - Каждый экземпляр
Request
«знает» как об основном запросе (Request::$initial
), так и об активном, т.е. выполняемом в данный момент времени (Request::$current
). Несмотря на то, что доступ к свойствам$initial
и$current
открыт (public), имеются и методыinitial()
иcurrent()
. Скорее всего позже свойства вынесут в protected. Также для проверки, основной это запрос или нет, существует методis_initial()
. - Основные параметры маршрута (directory, controller, action) теперь перенесены в protected-свойства, для них созданы setter/getter-методы
directory()
,controller()
иaction()
соответственно. Все остальное черезparam()
, как и прежде. - Каждый запрос имеет собственные GET- и POST-данные, которые хранятся в свойствах
$_get
и$_post
. Доступ на чтение/запись организован через методыquery()
иpost()
соответственно.
Класс Request_Client
Точнее даже не один класс, а несколько. Request_Client
является базовым для Request_Client_External
и Request_Client_Internal
. По названию понятно, что первый используется для внешних запросов, а второй для внутренних. Определяется это просто — если в Request::factory()
передан абсолютный адрес, то создается внешний запрос.
Как я уже говорил ранее, Request_Client_External
знает три способа выполнить запрос, поэтому там имеются методы _http_execute()
, _curl_execute()
и _native_execute()
. Request_Client_Internal
ничего особенного не производит — просто старая часть кода из Request::execute()
пренесена в Request_Client_Internal::execute()
.
Обратите внимание, что в ветке 3.1 передача параметров в экшены помечена как deprecated, т.е. устаревшая/нежелательная. Зачем себя ограничивать порядком аргументов, если гибкий роутинг позволяет просто получать именованные параметры через
$this->request->param()
? Начания с релиза 3.2 передачи параметров уже не будет.
Сам по себе объект типа Request_Client
в явном виде в приложении не появляется, поэтому он может пригодиться разве что для получения времени его отработки (метод request_execution_time()
).
Класс Response
- Если ранее результат работы хранился в свойстве
$response
объектаRequest
, то теперь это свойство$_body
классаResponse
. По наличию подчеркивания в имени свойства можно догадаться, что это защищенное свойство, так что для доступа к нему создан специальный методbody($content)
. Если параметр$content
не указан, то вернется текущее значение$_body
. На данный момент все сделано не очень удобно, т.к.$content
явным образом преобразовывается в строку, соответственно работа с объектами (те же Views) должна проводиться ДО установки в$_body
. - Каждый конкретный объект
Response
может манипулировать набором кук (свойство$_cookies
и методыcookie()
/delete_cookie()
/delete_cookies()
) и заголовков ($_header
иheaders()
). Причем свойство$_header
является экзепляром специального классаHTTP_Header
(о нем ниже).
Теперь даже редирект (метод
redirect()
классаRequest
) происходит посредством создания экземпляра классаResponse
, а не отправки заголовка «Location» напрямую. - Есть методы с говорящими названиями
serialize()
/unserialize()
, помимо собственно тела ответа они обрабатывают еще статус ответа, заголовки и куки. Если в методserialize()
передать существующий массив, то данные изResponse
добавятся в него с ключами ‘_status’, ‘_header‘, ‘_cookies‘ и ‘_body‘.
Работа с запросами на практике
Основной запрос внешне практически не изменился. Добавился вызов body()
для доступа к телу ответа, да и сам вызов переместили из bootstrap.php в index.php:
echo Request::factory() ->execute() ->send_headers() ->body(); |
Напоминаю, что хотя это выглядит стандартной цепочкой вызовов
Kohana
, после методаexecute()
вместоRequest
мы работаем уже сResponse
!
Если где-то в теле приложения мы хотим вызвать дополнительные запросы, это будет выглядеть примерно так:
$internal = Request::factory('welcome/test')->execute(); $external = Request::factory('http://ya.ru')->execute(); $this->response->body($internal.$external); |
Мы можем смело «складывать» объекты класса
Response
, так как они при приведении к типу «строка» просто возвращают свое свойство$_body
, что нам и нужно.
Как видите, для формирования результата запроса в контроллере имеется свойство $this->response
. В случае использования Controller_Template
в методе after()
базовый шаблон записывается в $this->response
автоматически.
Роутинг
- Для счастливых пользователей php v5.3 можно использовать лямбда-функции в роутах! Выглядеть это должно было примерно так (взято отсюда):
Route::set('testing', function($uri) { if ($uri == '</language regex/>(.+)') { Cookie::set('language', $match[1]); return array( 'controller' => 'welcome', 'action' => 'foobar' ); } } );
Но, естественно, получилось по-другому. Каждая такая лямбда-функция должна принимать на входе один параметр — разбираемый URI. Возвращает массив параметров для роутинга. Если возвращает не массив — будет проигнорировано при анализе роутов. В итоге у меня более-менее динамическим получился следующий роут:Route::set('lambda', function($uri) { $compiled = Route::compile('(<lang>/)(<controller>(/<action>))', array('lang' => '[a-z]{2}')); if ( ! preg_match($compiled, $uri, $matches)) { return FALSE; } if ($lang = arr::get($matches,'lang')) { cookie::set('lang', $lang); } return $matches; }, '(<lang>/)(<controller>(/<action>))' )->defaults(array( 'controller' => 'welcome', 'action' => 'index' ));
Синтаксис следующий: в методset()
вторым параметром передается сама лямбда-функция, а третьим (где раньше была регулярка для параметров) — шаблон для URI в том виде, каким обычно мы его подставляем в качестве второго параметра. Это нужно для генерации URI данным роутом (т.н. «reverse routing» — обратный роутинг). Вdefaults()
, как и прежде, добавляем значения по умолчанию.Так как мы не можем тупо сравнивать
$uri
с шаблоном, то надо прикрутить имеющийся методcompile()
классаRoute
. Передаем туда шаблон и регулярки для параметров (я сделал для lang) и потом просто ищем совпадения с помощьюpreg_match()
. По идее еще надо чистить все лишнее из результата (пустые элементы или нестроковые ключи), но для примера сойдет. Тем не менее, как-то все пока получается негибко и корявенько, возможно я что-то не понимаю, а может механизм еще допилят. Например, передавать в лямбда-функцию еще и ссылку на текущий роут — как вариант. - Добавился еще один параметр в роуты — это имя хоста (host). По умолчанию он FALSE, т.е. не используется. Хранится в свойстве
$_host
. В принципе он нужен для определения типа создаваемого запроса (внутренний/внешний), а также для генерации URI/URL. Для внешнего запроса методы$route->uri()
и$route->url()
будут возвращать одно и то же — абсолютный адрес.
Напомню, что в 3.0.x метод
url()
отличался отuri()
тем, что добавлялurl::base()
перед относительным адресом. Теперь же появились нюансы, связанные с обработкой внешних запросов.Определить, внешний это роут или внутренний, можно с помощью метода
is_external()
. Проверка простая — хост считается внутренним, если он не указан (это логично), либо перечислен в специальном свойствеRoute::$localhosts
. По умолчанию это свойство содержит следующие значения:FALSE
,''
(пустая строка), ‘local
‘, ‘localhost
‘. Не уверен, что данное нововведение будет пользоваться бешенной популярностью, но сама возможность весьма интересная. - В случае, когда роуты загружаются из кэша (
if (Route::cache()) {...}
), то новое свойствоRoute::$cache
устанавливается вTRUE
. Опять же, непонятны мотивы именования свойства — обычно слово ‘cache‘ ассоциируется с объектомCache
, а булевские флаги обычно что-то вроде ‘cached‘ или ‘is_cached‘.
Работа с HTTP
- Созданы специальные классы
HTTP_Header
(как коллекция имеющихся заголовков) иHTTP_Header_Value
(как обертка для конкретного заголовка). Впрочем, классы сугубо служебные и вряд ли вам когда-нибудь понадобится знание их внутренностей. - Реализовано целое семейство исключений. Родитель —
HTTP_Exception
, расширенный в 24-х (!) исключениях, отличающихся между собой только кодом HTTP-ответа (хранится в свойстве$_code
). Например,HTTP_Exception_404
для Not Found. Естественно, коды в диапазоне 4xx (ошибки клиента) и 5xx (ошибки сервера).
Валидация
- Класс
Validate
разделен на два (относительно) новых классаValid
иValidation
. Первый содержит набор статических правил (alpha()
,min_length()
и т.д.). Второй нужен непосредственно для хранения проверяемых данных и применяемых правил, а также выполнения проверки (методcheck()
). Т.е. по сути вернулись к состоянию версии 2.3.4 (хэлперValid
и библиотекаValidation
).
Соответственно и исключение поменяло имя на
Validation_Exception
! - Как таковые исчезли фильтры и callback‘и — теперь есть только один термин — правило. Для добавления правил есть знакомые методы
rule($field, $rule, array $params = NULL)
иrules($field, array $rules)
. С параметром$field
, думаю, все понятно — это имя проверяемого поля.$rule
— вызываемый метод, который может принимать различные формы:- Строковое значение. Если в нем есть двойное двоеточие (например, ‘Valid::not_empty‘), то вызовется статический метод
not_empty()
классаValid
. Если нет, то сперва проверяется наличие метода с таким именем во все том же классеValid
, в противном случае выполняется функция с таким именем (если существует конечно, иначе ждитеReflectionException
). - Массив. Первый элемент массива должен быть именем класса или объектом соответствующего класса, а второй — название метода этого объекта. Например
array('Valid', 'not_empty')
илиarray($obj, 'method_name')
. - Лямбда-функция. Естественно, только для php v5.3+. Можно «на лету» создать функцию для проверки и указать, какие параметры в нее передавать. Например:
$validation ->rule('username', function($value) { return ! in_array(strtolower($value), array('admin', 'root', 'administrator', 'админ', 'администратор')); });
Таким образом мы не разрешаем пользователям иметь логины, похожие на админские. Я не указывал, какие параметры передавать в правило (третий параметр методаrule()
), поэтому в него передается значение проверяемого поля. Правило должно возвращать FALSE, если значение не прошло проверку.На данный момент работа с лямбда-правилами не очень отработана, например нет алгоритма формирования текста для сообщения (у правила нет имени). В результате при вызове метода
errors()
сгенерируется ошибка «Object of class Closure could not be converted to string«.
- Строковое значение. Если в нем есть двойное двоеточие (например, ‘Valid::not_empty‘), то вызовется статический метод
- Появились контексты. Точнее, в библиотеке это называется связыванием (bind), но принцип полностью аналогичен тому, что я недавно описывал в статье Развитие Jelly. Метод
bind($key, $value)
позволяет связать между собой некие текстовые ключи и переменные (эти связки хранятся в свойстве$_bound
объектаValidation
), а потом использовать при валидации. По умолчанию можно рассчитывать на ключи ‘:validation‘ (собственно сам текущий объект валидации), ‘:value‘ (значение поля), ‘:field‘ (имя поля). Можно добавлять и свои, например экземпляр модели, из которой вызывается валидация.Далее эти ключи можно использовать в параметрах правила:
$validation ->rule('username', function($value) { return ! in_array(strtolower($value), array('admin', 'root', 'administrator', 'админ', 'администратор')); }, array(':value'));
Я слегка изменил предыдущий пример. Делает он то же, но явно указан параметр для передачи в функцию — значение функции.
Заставить работать фильтры по синтаксису правил я смог только через одно место. Проблема в том, что каждое правило получает свою копию первоначального значения поля, т.е. не может влиять на последующие правила. На помощь пришли связывания:
$validation->rule( 'field2', function($value, $validation) { $validation->bind(':value', trim($value)); return TRUE;}, array(':value', ':validation') );
Данный «фильтр» должен идти перед остальными правилами, в таком случае они будут работать с обработанным значением. Тем не менее, если после прохождения проверки обратиться к данному полю, оно по-прежнему будет содержать пробелы, т.е. фильтр работает только на этапе проверки. Вообще, теперь основная идея, вызвавшая отказ от фильтров — «валидация не должна менять данные». Т.е. фильтрация должна производиться на стадии присвоения значения
Прочие изменения
- Произошли небольшие изменения в файлах запуска Kohana. Теперь создание и выполнение запроса (
Request::factory()->execute()
и т.д.) располагается в файле index.php, а не в bootstrap.php, как ранее. Таким образом, теперь файл bootstrap.php занимается только конфигурированием системы под нужды проекта. - Кроме того, исчез файл base.php, который обычно располагался в SYSPATH. В нем ранее объявлялась функция
__()
для перевода слов и предложений. Теперь функция находится в файле SYSPATH/classes/kohana/i18n.php, т.е. в файле классаKohana_I18n
. Чтобы преопределить ее, достаточно расположить объявление до первого вызова методов классаi18n
. Напомню, обычно это установка локали в bootstrap.php. Как вариант (чтобы не располагать объявления в этом файле, а также не инклюдить ничего) — опустить вызовi18n::lang()
ниже, чемKohana::modules()
, а собственный вариант функции__()
объявить в каком-нибудь из файлов init.php. - Константы
Kohana::PRODUCTION
/STAGING
/TESTING
иDEVELOPMENT
теперь имеют не строковые, а численные значения от 1 до 4. Соответственно можно сравниватьKohana::$environment
с этими константами, отсекая какие-то стадии разработки. - Появился флаг
Kohana::$expose
, если его установить в TRUE, то в заголовках ответов проекта появится дополнительно ‘X-POWERED-BY‘ с текущей версией Kohana. - В 3.1 добавились новые классы логов —
Log_Stderr
иLog_Stdout
, отправляющие сообщения в соответствующие стандартные потоки STDERR и STDOUT. Работают аналогично прочим типам логов — добавляем черезKohana::$log->attach()
, пишем черезKohana::$log->add()
. - Класс
Cookie
использует параметр$salt
для подписывания (signing) значений. Раньше он имел значение по умолчанию, теперь его надо ОБЯЗАТЕЛЬНО указывать, например в файле bootstrap.php:Cookie::$salt = 'my_secret_salt'
. Иначе при первой же попытке записать/считать куку получите исключение. - В модуль Database добавили поддержку транзакций. Это методы
begin()
,commit()
иrollback()
. Выглядеть это будет примерно так:
$db->begin(); try { $db->query(...); $db->commit(); } catch (Database_Exception $e) { $db->rollback(); }
В дальнейшем планируется добавить поддержку вложенных транзакций, подробнее можно почитать в данном тикете.
- Модели теперь по умолчанию не содержат объекта Database, т.е. не связаны с БД. Напомню, ранее у них было свойство $_db, содержащее автоматически создающийся объект Database.
- Метод
date::months()
, ранее возвращавший тупо массив порядковых номеров месяцев года (’01′=>’01′, ’02′=>’02′ и т.д.), теперь поддерживает возможность отдавать названия. Возможные параметры —date::MONTHS_LONG
иdate::MONTHS_SHORT
. В первом случае в качестве значений будут полные имена месяцев (January для английской локали, Январь для русской и т.д.), а во втором — сокращенные (Jan или Янв). - К методу
arr::path()
, возвращаемому элемент массива по пути типа ‘foo.bar.baz‘, добавился методarr::set_path()
, который позволяет добавить элемент по подобному пути. Например,arr::set_path($arr, 'one.two.three', $value)
установит значение$arr['one']['two']['three']
равное$value
.
Заключение
Надеюсь, что ничего важного не забыл. Понятное дело, что полноценно использовать данный RC нельзя. Много шероховатостей, некоторые методы требуют доработки, отдельные вообще не работают. Ну, на то это и RC, чтобы собрать замечания и в результате выдать очередной великолепный продукт из серии «фреймворк Kohana».
В основном я привел изменения касательно модуля Core, т.е. ядра фреймворка. Остальные модули (в первую очередь ORM) буду рассматривать в отдельной статье или статьях — как получится.
А Database из 3.1 получится использовать в 3.0.8?
Вообще, обновление расстроило немного. В частности — validation.
Пока не увидел серьезных изменений, поэтому, полагаю, что можно попробовать
А что в Validation расстроило? Да, серьезные изменения в API, но по идее контексты — очень вкусная штучка.
Чет не понятно, как жить без callback-ов в валидации?
А кто сказал, что их теперь нет? Просто все делается через правила + контексты.
спасибо за описание =)
Отличные изменения, ждем финального релиза. Хочется поддержки неймспейсов из php 5.3.
Спасибо за статью.
@Smarty
Полный переход на php5.3 планируется только в ветке 3.2.x. Сейчас есть только возможность кое-где использовать отдельные «фишки» типа лямбда-функций, но при этом фреймворк полностью совместим с младшими версиями php.
Спасибо за обзор, те, кто по уши в работе и не высовывают голову выше стабильной ветки вам очень благодарны. Выглядит вкусно, хотя непривычно.
@Xobb
Мне аж стыдно стало ))
Отсутствие фильтров и callback-ов расстроило. У меня почти всегда валидация через них идет, причем примерно так: в classes есть папка validation, в ней папки callbacks и filters, в которых уже файлы с нужными методами. Я понимаю, что сейчас можно тоже самое реализовывать через rules, но все-равно не привычно — filters и callback все-же не правила валидации, как таковые.
Ну и самое большое огорчение — не получится теперь обновить кохану на работающих проектах до новой версии =(.
@aktuba
Callback’и все равно есть, просто объявлять их немного по-другому придется. Насчет отказа от фильтров в валидации — достаточно холиварная тема, но в принципе можно понять разработчиков. Просто придется перестраивать работу моделей и прочих проверяемых объектов. С другой стороны, тот же Jelly уже при установке значений свойствам модели приводит их к нужному виду.
И кто обещал, что можно будет обновить без забот? Это major-релиз, тут изменения API изначально запланированы
Спасибо за обзор!
Удивил перенос цепочки запроса в index.php из бутстрапа. Как сейчас обернуть его в try/catch, если нужно ловить исключение? Или такой подход чем-то неправилен?
А какой-нибудь migration guide c ветки 3.0.х планируется?
Вот это и отпугивает разработчиков от коханы =(.
Поясни, plz. Я не вижу объективных причин отказа от фильтров.
Понравились комиты, их бы я в 3.0.x добавил поскорее. Ну а arr::set_path(), я ещё очень давно с коханы 2.3.4 вставил ^^
В роутах так ничего и не придумали для работы с сабдаменами, жаль.
А зачем? И так не сложно вроде работать с поддоменами:
define(‘SUBDOMAIN’, count($subdomain = explode(‘.’, $_SERVER['HTTP_HOST'])) == 3 ? $subdomain[0] : FALSE);
if (SUBDOMAIN)
Route::set(‘default’, », array(‘params’ => ‘.*’))
->defaults(array(
‘controller’ => u,
‘action’ => ‘index’,
));
Примерно так…
@Alexander Kupreev
Насколько я знаю, вся документация будет ближе к окончательному релизу. Ну, еще есть вот это обсуждение на форуме.
@aktuba
1. А что отпугивает? Никто ветку 3.0 не забрасывает, и на 3.1 переходить не заставляет.
2. Основная мысль такова: валидатор только проверяет, не исправляет ничего. Т.е. все данные должны фильтроваться на входе.
@Мимошёл
Не смотрел, но наверняка часть коммитов уже отправлена в ветку 3.0/develop
Шутка? Все-же понимают, что раз нет обратной совместимости, рано или поздно 3.0.х просто забросят. Да и плюшки в новых версиях приманивают… Вот я сейчас делаю свою мини-cms и не знаю как поступить теперь: то ли продолжить на 3.0.8, то ли сразу 3.1 взять.
Эмм… Даже не знаю что и сказать тогда. Если идут такие рассуждения — начинаю сомневаться в правильности выбора коханы =(. Тогда уж и очистку данных из database надо убрать, т.к. «все данные должны фильтроваться на входе». Бред какой-то =(.
P.S.: пошел изучать FuelPHP и Yii =(((((((
1. Дык рано или поздно и 3.1 забросят На каждый мажорный релиз положен один год жизни, как я сегодня написал. Просто пока была только 3.0 ветка, никого наличие параллельной ветки не волновало. Многие проекты до сих пор на 2.3.4 сидят — и ничего ))
2. А в чем проблема фильтровать данные в модели? Имеется в виду не фильтрация на входе системы (в контроллере или еще где), а на входе модели, т.е. в методе set() или __set(). В конце концов, возможность расширить класс Validate через КФС имеется.
Так проблема не в этом, а в том, что нет обратной совместимости… Ну меняют api — пусть делают постепенно, чтобы сохранять текущую функциональность. С той же валидацией — какой смысл был резать фильтры а коллбеки на корню? Ввели бы новый функционал, а старый оставили.
Мы с тобой это на форуме обсуждали, вот только ссылку найти не могу. Я сторонник тонких моделей, т.е. считаю, что в модель параметры попадают уже чистые. Очищать же их в модели — лишние действия и лишний код в модели.
1. Ну, разработчики не предусмотрели ветки с «медленным изменением API» и с «быстрым»
2. Повторюсь — добавить фильтры вручную никто не мешает.
Такое ощущение, что они вообще ничего не предусмотрели. Посуди сам: каждый год кардинально будет меняться часть api и это при отсутствии нормальной документации к существующему api. К чему это приведет? К тому, что пользователи просто не будут поспевать за изменениями, ведь придется каждое новое изменение изучать через исходники. В итоге, полноценно использовать фреймворк смогут только разработчики фреймворка и бездельники, которые могут постоянно изучать изменения в коде.
Самому делать мост между старой и новой версией? Или менять текущий функционал? И то, и другое грозит кучей багов и огромным количеством потраченного времени.
Доброго времени суток!
Извините я не по теме…
Где взять переводы на русский язык всего что связано с Kohana, о которых тут не так давно говорилось?
Переходил по предоставленным в комментариях ссылкам, но в том, на что они ссылаются, нет русского перевода.
Например: http://kohanaframework.org/guide/, справа сверху две ссылки User Guide и API Browser ни одна из них не даёт результата в виде русского перевода.
@aktuba
***пошел изучать FuelPHP***
Только не изучать…
Полагаю, что для практического использования Fuel на сегодняшний день — наиболее приемлемое решение, особенно для тех, кто хорошо знаком с KO3.
Посудите сами: разработчикам удалось в этой оболочке интегрировать все лучшее, что было в CI c передовыми решениями KO3, придав всему этому форму реального мощного инструмента.
DB -> практически один к одному.
KO3-подобная структура файловой системы позволяет использовать имеющиеся наработки от Kohana. Мне, к примеру, буквально за несколько дней после выхода beta1 удалось адаптировать основную часть модулей тройки…
@aktuba
Еще раз повторюсь, кто заставляет прыгать с версии на версию? Если текущая ветка стабильная, то зачем с нее уходить, да еще и с необходимостью прилагать усилия по этому переходу… Документация появляется обычно после релиза, так что можно спокойно читать доки по новой версии, не торопясь обдумывать перевод проектов.
Сейчас получается, что хочется обновлять версии из-за новых возможностей и вкусных плюшек. Но ругаться при этом на отсутствие обратной совместимости, ИМХО, уже несерьезно.
Я вот насчет FuelPHP не понимаю — вот сделают они стабильный релиз, потом займутся расширением функционала (не удивлюсь, если опять выдернут много чего с Ko3). Захочется вкусностей — повторится ситуация с Ko 3.0/3.1. И что дальше — искать новый фреймворк?
@Zares
Если не ошибаюсь, DB там вообще стырен из Ko3, даже остались «родные» комменты в шапке.
@Igor
Да, в новой версии (пока что) нет возможности переключить язык.
А где можно взять любую инфу по Kohana на русском может предыдущих версий?
А что вообще было на русском — документация или ещё и коментарии к коду (извините, я полный ламер но хочется разобраться).
@biakaveron:
Есть гарантии, что разработчики модулей будут поддерживать все релизы коханы? Например, если в модуле используется стандартная валидация — он уже не будет полноценно работать в 3.1, верно? В последствии, это скажется и на других модулях… Между тем, от обновления модулей зависит надежность готовой системы. «Хотелки» тут не при чем.
Надеюсь, не повторится… Но и другого выхода не вижу: либо забыть про обновления (включая модули), либо искать другой фреймворк, который более лояльно относится к пользователям, не ставя их перед такими выборами. Или есть еще какие-то варианты?
1 год на каждый мажорный релиз. Мало? По крайней мере большинство багов и дырок должны исправить.
Почему такое непринятие параллельных веток? Ведь 3.0.x продолжается, по моим прикидкам еще полгода будет развиваться (точнее багфикситься), так что жизнь продолжается Да, новых фич скорее всего не будет, но и совместимость останется.
Мало. Полгода-год — это срок обкатки фреймворка/модулей, но никак не срок гарантии надежности.
В принципе, ты уже сам ответил — ветке 3.0.х жить осталось полгода-год. А дальше? Я, например, с CI переходил на кохану по такой-же причину (точнее, это была одна из причин) — нет развития фреймворка. CI тоже живет, поддерживает совместимость с 1.5 и т.д. Даже баги какие-то правят.
При переходе на ko3 я планировал постепенно перевести большинство своих проектов на нее. Это позволило бы в будущем не распыляться, изучая 2-3 разных фреймворка, следить за их обновлениями и пр. А что получается сейчас? Либо постоянно обновлять сами проекты (т.к. версии одного фреймворка между собой не совместимы), либо снова-таки постоянно следить за обновлениями разных версий ko3. И где тот профит, на который был упор при смене фреймворка?
А какой срок — гарантия? Сил и времени у разработчиков не так уж и много, а есть ведь и пожелания по развитию фреймворка…
Противоречие получается. С одной стороны, надо развиваться, а с другой — сохранять обратную совместимость со старыми проектами. Это возможно?
Как можно добавлять вкусности, и при этом сохранять старый API? Точнее, этого можно достичь, но получится что-то вроде того же CI, держащегося за PHP4 долгое время.
А кто заставляет обновлять проекты? Переходить с ветки на ветку имеет смысл, если текущий релиз не предоставляет тех возможностей, что новый. А значит, стоит потратить время на изучение документации, исходников и т.д.
Да нет противоречий. Посмотри на ZF, Yii и пр. — они и развиваются, и поддерживают совместимость. Не вижу причин, когда надо ломать старое апи, чтобы добавить новые возможности. Хотя бы через конфиги (хоть глобальные) можно регулировать что и как использовать.
Совесть, деньги, интерес и т.д. У каждого свои причины на развитие проектов. У меня, в данный момент, пара проектов на постоянной поддержке и развитии. Но самая большая проблема — что делать с новыми проектами? Реализовывать на умирающей 3.0 или использовать 3.1? Как потом не запутаться, где и какие фичи можно использовать, а где нет? С той же валидацией, например, или с новым апи для базы. Брать 3.0 — значит отказываться от новых модулей, от поддержки старых модулей и пр. Ну не будут создатели модулей поддерживать несколько веток — это не имеет практического смысла. Значит они будут поддерживать только ту версию, которую используют сами.
В общем, грустно все это. Реально, я уже не горю желанием использовать ko. Возможно, все-же доделаю для себя cms на 3.0, но потом все-равно буду искать другой фреймворк, либо набросаю свой, на основе ko.
На самом деле главная проблема, связанная с 3.1.x — это именно изменения в валидации. Я пока вижу два варианта для изменения сложившейся ситуации:
1. Вынос валидации в отдельный модуль. Решает проблему выбора версии фреймворка и дальнейшего обновления. Однако некоторые модули (например ORM) ориентированы на конкретное API валидации, это придется постоянно держать в уме
2. Можно попробовать использовать тот факт, что имена классов валидации в 3.0.x и 3.1.x не пересекаются. То есть можно добавить класс Validation, а в нем все имеющиеся методы сделать просто врапперами для соответствующих методов классов Valid и Validate. Тут проблемы могут быть с добавлением колбэков и фильтров, т.к. их нет в новой ветке.
В 3.1 — да. А что будет в 3.2, 3.3 и т.д.? Ну и request тоже вроде сильно изменился в 3.1.
На самом деле, раз уж решили изменять api — это единственно правильный способ. Модуль валидации должен был стать мостиком, между коханой и сторонними модулями, такими как orm.
Как говорил Казьма прутков, нельзя обнять необъятное…
Равно, как и затея запихнуть весь сыр в один вареник — утопия
Посему, всегда рассматривал Kohana, как интегрирующую оболочку.
Прекрасная организация входных потоков, мощный вывод, и отличные
возможности для того, чтобы легко можно было все это кастомизировать…
Если честно — ни один из моих проектов на KO3 не использует ни ORM с его прибамбасами сомнительной ценности, ни дренной Auth, ни даже Kohana_Session…, поэтому, легко и с превеликим удовольствием оставляю все это в прошлом и перехожу на долгожданную KO3.1.
Zares, а чем Auth не угодил?
Кстати у YII, тоже при следущей версии (2.0), будет смена апи (1 год мажорный релиз как раз получается). Разве они обещали совместимость, с учетом того что там уже для свежей версии пхп будет все ? У Zend 2.0 помоему, аналогично все.
По поводу YII и совместимости версий:
Ни о какой совместимости версий в YII не может быть и речи.
Это миф!
Я, конечно, не берусь судить по состоянию за последних 3-4 месяца