This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
khosb/includes/kohana/modules/userguide/guide/ru-ru/about.upgrading.md
2011-05-03 09:49:01 +10:00

293 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Переход с 2.3.x
Многое в Kohana v3 работает совсем по другому, нежели в Kohana 2.3, вот список самых популярных советов для обновляющихся.
## Правила именования
Ветка 2.x выделяет различные 'типы' классов (т.е. контроллер, модель и т.д.), используя для этого суффиксы. Директории внутри папок model / controller не влияют на имя класса.
В 3.0 от данного подхода отказались в пользу файловых соглашений Zend framework , в котором имя класса является путем к файлу, разделенному знаками подчеркивания вместо слэщей (т.е. `/some/class/file.php` становится `Some_Class_File`)
Смотри [описание соглашений](start.conventions) для получения подробной информации.
## Библиотека Input
Библиотека Input была исключена из 3.0, просто используйте `$_GET` и `$_POST`.
### Защита от XSS
Если Вам нужно обезопасить от XSS введенные пользователем данные, можете использовать [Security::xss_clean] :
$_POST['description'] = security::xss_clean($_POST['description']);
Также можно вызывать [Security::xss_clean] в качестве фильтра для объекта [Validate]:
$validation = new Validate($_POST);
$validate->filter('description', 'Security::xss_clean');
### POST & GET
Одной из важнейших возможностей библиотеки Input было то, что если Вы попытаетесь обратиться к значению одного из суперглобальных массивов и оно не задано, библиотека Input возвратит значение по умолчанию, которое Вы зададите, например:
$_GET = array();
// $id установлено в 1
$id = Input::instance()->get('id', 1);
$_GET['id'] = 25;
// $id установлено в 25
$id = Input::instance()->get('id', 1);
В 3.0 Вы можете сделать то же самое с помощью [Arr::get]:
$_GET = array();
// $id установлено в 1
$id = Arr::get($_GET, 'id', 1);
$_GET['id'] = 42;
// $id установлено в 42
$id = Arr::get($_GET, 'id', 1);
## Библиотека ORM
Произошло немало серьезных изменений в ORM после версии 2.3, вот список наиболее известных проблем после обновления.
### Свойства
Все свойства модели теперь начинаются со знака подчеркивания (_) и больше не доступны через метод `__get()`. Вместо этого Вы должны вызвать метод с именем свойства, но без подчеркивания.
Например, свойство, бывшее в 2.3 `loaded`, теперь называется `_loaded` и извне класса доступно через `$model->loaded()`.
### Связи
В 2.3, если Вы хотели пройтись по связанным с моделью объектам, надо было использовать:
foreach($model->{relation_name} as $relation)
Однако в новой системе это не будет работать. В версии 2.3 любой запрос с использованием библиотеки Database, был сгенерирован глобально, т.е. у Вас не получится создать одновременно два запроса. Вот пример:
# TODO: Нужен достойный пример!!!!
Этот запрос приведет к ошибке, т.к. второй запрос будет 'наследовать' условия первого, тем самым вызывая чертовщину.
В v3.0 это было исправлено выделением каждого запроса в свою собственную 'песочницу', это приводит к тому, что некоторые вещи работают не так, как ожидается. Пример:
foreach(ORM::factory('user', 3)->where('post_date', '>', time() - (3600 * 24))->posts as $post)
{
echo $post->title;
}
[!!] (Смотри описание нового синтаксиса запросов в [руководстве по Database](tutorials.databases))
В 2.3 данный запрос вернет объект-итератор всех записей пользователя с id=3, где поле `post_date` лежит в диапазоне последних 24 часов. Однако новая версия применит условия where к пользовательской модели и вернет объединенную через join модель `Model_Post`.
Для достижения нужного эффекта необходимо перераспределить порядок вызовов:
foreach(ORM::factory('user', 3)->posts->where('post_date', '>', time() - (36000 * 24))->find_all() as $post)
{
echo $post->title;
}
Аналогично со связями `has_one`:
// Неправильно
$user = ORM::factory('post', 42)->author;
// Правильно
$user = ORM::factory('post', 42)->author->find();
### Связи много-ко-многим
В 2.3 Вы можете указать `has_and_belongs_to_many` тип связи. В 3.0 эта функциональность была переработана в связь *сквозное* `has_many`.
В моделях определяется связь `has_many` с другой моделью, но добавляется атрибут `'through' => 'table'` , где `'table'` - имя промежуточной таблицы. Например (в контексте области записи<>категории):
$_has_many = array
(
'categories' => array
(
'model' => 'category', // внешняя модель
'through' => 'post_categories' // промежуточная модель
),
);
Если Вы настроили kohana с использованием табличных префиксов, то не стоит беспокоиться о явном указании префиксов в модели.
### Внешние ключи
Если Вы хотели переопределить внешний ключ в ORM ветки 2.x, надо было указать в принадлежащей (слабой) модели свойство `$foreign_keys` со значением имени внешнего ключа.
В 3.0 Вы определяется ключ `foreign_key` в самом объявлении связи, вот так:
Class Model_Post extends ORM
{
$_belongs_to = array
(
'author' => array
(
'model' => 'user',
'foreign_key' => 'user_id',
),
);
}
В данном примере мы настроили поле `user_id` для таблицы записей.
В связях has_many атрибут `far_key` (дальний ключ) является полем в промежуточной таблице, которое связано с внешней (для текущей) таблицей, а внешний ключ является полем в промежуточной таблице, которое связано с "этой" таблицей.
Следуя вышесказанному, "posts" связаны много-ко-многим с "categories" через `posts_sections`.
| categories | posts_sections | posts |
|------------|------------------|---------|
| id | section_id | id |
| name | post_id | title |
| | | content |
Class Model_Post extends ORM
{
protected $_has_many = array(
'sections' => array(
'model' => 'category',
'through' => 'posts_sections',
'far_key' => 'section_id',
),
);
}
Class Model_Category extends ORM
{
protected $_has_many = array (
'posts' => array(
'model' => 'post',
'through' => 'posts_sections',
'foreign_key' => 'section_id',
),
);
}
Очевидно, что настройки псевдонимов выглядят несколько неадекватными, но это хороший пример того, как работает схема внешний/дальний ключ.
### ORM Iterator
Стоит также отметить, что от класса `ORM_Iterator` отказались в пользу `Database_Result`.
Если надо получить массив объектов ORM с ключами из первичных ключей, надо вызвать [Database_Result::as_array], вот так:
$objects = ORM::factory('user')->find_all()->as_array('id');
Здесь `id` является первичным ключом таблицы.
## Библиотека Router
В версии 2 была библиотека Router, которая обрабатывала основной запрос приложения. Она позволяла определить базовые маршруты в файле `config/routes.php` и использовать собственные регулярные выражения для них, однако этого было недостаточно для описания чего-нибудь нестандартного.
## Маршруты
Система маршрутизации (теперь логичнее называть ее системой запросов) в версии 3.0 стала намного более гибкой. Маршруты объявляются в загрузочном файле (`application/bootstrap.php`) и скриптах init.php модулей (`modules/module/init.php`). (Стоит также отметить, что маршруты рассматриваются в том же порядке, в каком были определены).
Вместо объявления массива маршрутов теперь необходимо создавать новый объект [Route] на каждый маршрут. В отличие от ветки 2.x нет необходимости отделять один URI от другого. Вместо этого Вы определяете шаблон с использованием переменных для обозначения секций (таких как контроллер, метод, id).
К примеру, в предыдущей системе данное выражение:
$config['([a-z]+)/?(\d+)/?([a-z]*)'] = '$1/$3/$1';
подменит URI `controller/id/method` на `controller/method/id`. В 3.0 следует использовать:
Route::set('reversed','(<controller>(/<id>(/<action>)))')
->defaults(array('controller' => 'posts', 'action' => 'index'));
[!!] Каждому маршруту назначается уникальное имя (в данном случае он называется `reversed`), причины описаны в [учебнике по URL](tutorials.urls).
Угловые скобки являются признаком динамических секций, которые будут сохранены в виде переменных. Круглые скобки обозначают необязательные участки. Если Вы хотите обрабатывать только адреса, начинающиеся с `admin`, используйте:
Rouse::set('admin', 'admin(/<controller>(/<id>(/<action>)))');
А если надо заставить пользователя указать контроллер:
Route::set('admin', 'admin/<controller>(/<id>(/<action>))');
Также Kohana не устанавливает сама значений по умолчанию. Если Вы хотите, чтобы Kohana установила метод 'index' как дефолтный, необходимо указать это в явном виде! Сделайте это с помощью [Route::defaults]. Когда надо указать регулярное выражение для отдельных сегментов uri, добавьте параметр - массив вида `segment => regex`. Например:
Route::set('reversed', '(<controller>(/<id>(/<action>)))', array('id' => '[a-z_]+'))
->defaults(array('controller' => 'posts', 'action' => 'index'))
Значение сегмента `id` теперь должно состоять только из маленьких латинских букв и знака подчеркивания.
### Экшены
Еще один момент, который необходимо отметить - методы контроллера, которые должны быть доступны через url теперь называются "экшены" ("actions"), и начинаются с префикса 'action_'. В вышеуказанном примере, если пользователь введет `admin/posts/1/edit`, то экшен будет называться `edit`, но вызываемый метод контроллера получится `action_edit`. Подробности в [учебнике url](tutorials.urls).
## Сессии
Больше нет методов Session::set_flash(), Session::keep_flash() и Session::expire_flash(), вместо них используйте [Session::get_once].
## Хэлпер URL
Изменилось немногое - `url::redirect()` перемещен в `$this->request->redirect()` (при вызове из контроллера) / `Request::instance()->redirect()`
`url::current` заменен на `$this->request->uri()`
## Valid / Validation
Эти два класса были объединены в единый класс `Validate`.
Немного изменился синтаксис для валидации массивов:
$validate = new Validate($_POST);
// Применяем фильтр на все элементы массива
$validate->filter(TRUE, 'trim');
// Для указания специфических правил используйте rule()
$validate
->rule('field', 'not_empty')
->rule('field', 'matches', array('another_field'));
// Устанавливайте множество правил для одного поля через rules(), передавая массив вида rules => params в качестве второго параметра
$validate->rules('field', array(
'not_empty' => NULL,
'matches' => array('another_field')
));
Стандартное правило 'required' было переименовано в 'not_empty' для ясности.
## Библиотека View
Сделано несколько незначительных изменений, которые стоит отметить.
В 2.3 представления формировались в зоне видимости контроллера, что позволяло в представлении использовать `$this` как ссылку на контроллер, и в 3.0 теперь по-другому. Представления теперь генерируются в пустом окружении. Если необходимо использовать `$this` в шаблоне, создайте ссылку с помощью [View::bind]: `$view->bind('this', $this)`.
Тем не менее, стоит отметить, что это *очень* плохая привычка, т.к. повышает сцепление представления с контроллером и усложняет повторное использование. Рекомендуется подключать необходимые переменные таким образом:
$view = View::factory('my/view');
$view->variable = $this->property;
// ИЛИ если нравится запись по цепочке
$view
->set('variable', $this->property)
->set('another_variable', 42);
// НЕ рекомендуется
$view->bind('this', $this);
Так как представление формируется в пустом окружении, `Controller::_kohana_load_view` теперь избыточно. Если надо изменить представление до его генерации (например, добавить меню сайта), используйте [Controller::after].
<?php
Class Controller_Hello extends Controller_Template
{
function after()
{
$this->template->menu = '...';
return parent::after();
}
}