Предлагаю рассмотреть немногочисленные (пока) возможности по работе с БД, предоставленные «бетой» Kohana v3. Люди, «подсевшие» на комфортные ORM и Query Builder, приготовьте сердечные капли
Итак, для начала напомню, что все классы для работы с БД выделены в отдельный (и единственный на данный момент) модуль Database. Разработчикам показалось мало такого ущемления баз данных, они еще и исключили все драйверы, кроме MySQL (объяснив это тем, что они не используют другие СУБД, но будут рады драйверам со стороны). Однако и это еще не самое страшное. Абстрактный класс Database_Core, являющийся «сердцем» модуля, содержит в пять раз меньше методов, чем его аналог из 2.3.4.
По сути «дельными» являются только метод query($type, $sql), а также информационные list_tables() и list_columns($table). Как обычно, методы connect() и disconnect() в явном виде не требуются, т.к. в query() производится проверка на наличие линка с БД. Никаких намеков на будущее наличие методов а-ля Query Builder мы не видим, но отчаиваться не стоит — скорее всего все это будет выделено в отдельную библиотеку.
Вы заметили, что метод Database::query() принимает новый параметр $type? Возможные значения перечислены в виде констант с говорящими названиями, например Database::SELECT. Кажется, что не очень удобно, т.к. обычно из plain-запроса и так видно, какой тип. Однако давайте заглянем в библиотеку DB_Core из файла classes/db.php:
class DB_Core { public static function query($type, $sql) { return new Database_Query($type, $sql); } public static function select($sql) { return new Database_Query(Database::SELECT, $sql); } ... } |
Статические методы этой библиотеки позволят нам использовать их из любого места в приложении, например так: DB::select($sql). Теперь становится понятно, что сама по себе библиотека Database напрямую навряд ли будет использоваться, если есть такие удобные обертки.
В бете класс DB содержит 8 методов, но работать «из коробки» будут только первые два (select() и query()), остальные «ругнутся» на отсутствующие классы. По аналогии с select() можно привести в порядок методы insert(), update() и delete().
Эти методы возвращают экземпляр класса Database_Query, цель которого — сформировать и передать библиотеке Database SQL-запрос. Для заполнения запроса есть разнообразные методы, связанные с установкой внутреннего свойства $_values, оно будет использовано как хранилище плейсхолдеров. Сама подстановка значений, экранирование данных и собственно передача запроса выполняется в методе execute(). В результате, получить всех активных пользователей из таблицы users можно так:
$users = DB::select('select * from users where active=:active') ->values(array(':active'=>TRUE)) ->execute(); |
Что с этим делать дальше? Как вы наверное догадались, метод execute() возвращает результат работы метода Database::query(), т.е. объект класса Database_Result, а еще точнее — его потомка, например Database_Mysql_Result. В целом работа с ним не изменилась (можно обрабатывать как массив, есть методы as_array() и count(), и т.д.), но есть нюанс — если в 2.3.x есть возможность указать, в каком виде возвращать записи (объекты или массивы), то в нынешнем драйвере Mysql почему-то доступны только массивы, в коде явно прописано использование mysql_fetch_assoc(). Возможно это следствие явно прослеживаемой тенденции к уменьшению количества конфигурационных файлов, увидим. В общем, забудем о $result->id, используем $result["id"].
Как я говорил в начале статьи, ORM и Query Builder отсутствуют как класс (точнее как два класса ), но класс Model есть. Он ничем не отличается от моделей ветки 2.3, только вместо $this->db объект Database доступен через $this->_db. Таким образом, получить все тех же многострадальных активных пользователей с использованием моделей мы сможем так:
// classes/model/user.php class Model_User extends Model { public function get_active() { return DB::select('select * from users where active=:active') ->values(array(':active'=>TRUE)) ->execute($this->_db); } } // classes/controller/test.php class Controller_Test extends Controller { public function action_users() { $model = new Model_User(); $users = $model->get_active(); foreach($users as $user) $this->request->response .= "<p>".$user['username']."</p>"; } } |
Если вспомнить о кэшировании, то на данный момент никаких встроенных методов нет. Единственное реализованное решение — метод Kohana::cache(), например он используется в Kohana::auto_load() и route::_construct() для быстрого доступа к часто повторяющейся служебной информации (в данном случае имена классов и скомпилированные REGEX‘ы маршрутов).
В общем-то это все, чем на данный момент располагает KO3. С одной стороны, тоскливо и неудобно, но с другой — какой простор для развития. Работайте с базами данных, используйте Kohana!
Тяжело представить конечный вариант как оно будет, но что видно сейчас, убивает на корню все удобство и красоту, которая была изначально в кохане. И это уже не впервые, что касается орм и бд.
Ну почему же так пессимистично? Мне к примеру нравится идея с использованием статических методов типа DB::select(). Query Builder сейчас уже практически закончен, сейчас разглядываю его внутренности. ORM тоже уже начали портировать, но пока что все только в зародыше.
PS. Как по мне, весьма симпотично смотрится: QBuilder.
Здравствуйте. Спасибо вам за ваши статьи. Без них мне было бы вообще не разобраться что да как)
Знакомство с коханой началось совсем недавно и пока что на данный момент умею лишь манипулировать данными в контролере и в views. Что никак пока не могу освоить так это вставка и выбор из БД.
Понима, что в контроллере экземпляр класса из модели, вызываем его метод и в него подставляем данныем для insert. А в самой модели в этом классе реализована вставка в БД. Но я никак не могу понять синтаксис всего этого =((
Вот простой пример:
контроллер — метод в который поступают данный после валидации:
Модель:
classes/models/gb.php
понимаю что это очень примитивно, но пока мне сложно понять как обращаться с ORM или c какими-нибудь другими методами. Как понимаю Kohana 3 очень сильнов этом плане отличается от второй, а документации чтоб посмотреть примеры мало(
Не могли бы вы привести пример простой вставки и выборки из таблицы?
Пожалуй, второй раз за сегодня «отмажусь» чужой статьей — почитайте тут.
Только подобные вызовы лучше делать внутри модели, а в контроллере использовать public-методы модели, например
get_article($title)
илиadd_article(array $data)
опечатка — в модели вместе class Model_DB extends Model { надо class Model_Gb extends Model {
СПАСИБО ОГРОМНОЕ!!!!
все получилось) данные в базы записываются)
но вот с выборкой возникли проблемы
в модели:
public function get_active()
{
return DB::select(‘title_text’,'text’)
->from(‘blog’)
->order_by(‘id’,'desc’)
->limit(10)
//->as_object()
->execute($this->_db);
}
в контролере:
$model = new Model_Gb();
$posts = $model->get_active();
но когда я смотрю что находиться в $posts — print_r($posts) мне вместо данных из базы выдает следущее:
Database_MySQL_Result Object
(
[_internal_row:protected] => 0
[_query:protected] => SELECT `title_text`, `text` FROM `blog` ORDER BY `id` DESC LIMIT 10
[_result:protected] => Resource id #52
[_total_rows:protected] => 7
[_current_row:protected] => 0
[_as_object:protected] =>
)
я думал данные уже будут в виде массива. Оказывается нет. Подскажите пожалуйста, как можно их получить?
Работайте с ним как с массивом, не обращайте внимание. Циклы типа foreach, обращение к элементу по его смещению — все это работает
) чтобы я делал без вашей помощи — все равботает)
спасибо Вам!