Java, Groovy on Grails, PHP, Kohana

Блог о программировании на Java, Groovy on Grails, PHP, kohana

Currently Viewing Posts Tagged orm

Kohana 3.2 – особенности использования модуля ORM MPTT (на основе nested set) Часть 1.

Для проекта выбрал модуль https://github.com/evopix/orm-mptt
Описанный в readme функционал – работает без проблем, а вот с остальным пришлось помучиться.
Но обо всем – по порядку.
Многие проекты имеют сложную структуру категорий товаров либо информации.
Часто требуется не фиксированная глубина вложенности.
Для этих целей, как нельзя лучше, подойдет модель хранения данных Nested set и ее реализация посредством модуля для Kohana MPTT.
Более детально о nested set
Есть несколько различных реализаций, но я остановился на модуле от evopix.
Ниже приведу описание основных методов модуля.
Нам потребуется таблица БД, вот ее упрощенная структура:

  • id – уникальный идентификатор-счетчик
  • parent_id – родительский id (для рутов – значение = 0)
  • lvl – уровень (для рутовых категорий он равен 1)
  • lft
  • rgt
  • scope – № ветви
  • name – наименование категории
  • url – url категории

Модель наследуем от ORM_MPTT

 class Model_Category extends ORM_MPTT { }

Создание корневого узла:

$cat = ORM::factory('category');
$cat->name = 'Каталог';
$cat->insert_as_new_root();

Создание последнего дочернего узла:

$parent_cat = ORM::factory('category')->where('name', '=', 'Каталог')->find();
$cat->name = 'Мобильные телефоны';
$cat->insert_as_last_child($parent_cat);
$cat->name = 'Планшеты';
$cat->insert_as_last_child($parent_cat);
$cat->name = 'Аксессуары для планшетов';
$cat->insert_as_last_child($parent_cat);
$cat->name = 'Литература о планшетах';
$cat->insert_as_last_child($parent_cat);

По аналогии создается дочерний узел, но вставляется перед всеми существующими:

$parent_cat = ORM::factory('category')->where('name', '=', 'Каталог')->find();

$cat->name = 'Бытовая техника';

$cat->insert_as_first_child($parent_cat);

Создание братского узла (узла того же уровня вложенности) перед указанным узлом:

$sibling_cat = ORM::factory('category')->where('name', '=', 'Планшеты')->find();

$cat->name = 'Комплектующие';

$cat->insert_as_prev_sibling($sibling_cat);

Создание братского узла (узла того же уровня вложенности) после указанного узла:

$sibling_cat = ORM::factory('category')->where('name', '=', 'Планшеты')->find();
$cat->name = 'Ноутбуки';
$cat->insert_as_next_sibling($sibling_cat);

Перемещение произвольного узла с подузлами в выбранный узел (в нашем случае перемещаем категорию "Аксессуары для планшетов" в категорию "Планшеты" перед всеми имеющимися узлами):

$source_cat = ORM::factory('category')
->where('name', '=', 'Аксессуары для планшетов')->find();

$destination_cat = ORM::factory('category')
->where('name', '=', 'Планшеты')->find();

$cat->move_to_first_child($destination_cat); 
//Перемещаем на место первого дочернего узла

То же самое, но теперь вставляем категорию после всех имеющихся узлов:

$source_cat = ORM::factory('category')
->where('name', '=', 'Литература о планшетах')->find();

$destination_cat = ORM::factory('category')
->where('name', '=', 'Планшеты')->find();

$cat->move_to_last_child($destination_cat); 
//Вставляем последним дочерним узлом

По аналогии возможны перемещения братских узлов:

$sibling_cat = ORM::factory('category')
->where('name', '=', 'Мобильные телефоны')->find();

$cat = ORM::factory('category')
->where('name', '=', 'Планшеты')->find();

$cat->move_to_prev_sibling($sibling_cat); 
//Перемещаем на позицию перед братским узлом
$sibling_cat = ORM::factory('category')
->where('name', '=', 'Мобильные телефоны')->find();

$cat = ORM::factory('category')
->where('name', '=', 'Планшеты')->find();

$cat->move_to_next_sibling($sibling_cat);
//Перемещаем на позицию после братского узла

В этом месте лично меня ожидал неприятный сюрприз.
Никаким образом категории не желали перемещаться.
Для решения данной проблемы необходимо изменить код в модуле modules\orm-mptt\classes\kohana\orm\mptt.php в методе lock(), на следующий:

protected function lock()
{
    $q = 'LOCK TABLE '.$this->_db->quote_table($this->_table_name).' WRITE';

    if ($this->_object_name)
    {
        $q.= ', '.$this->_db->quote_table($this->_table_name);
        $q.= ' AS '.$this->_db->quote_column($this->_object_name).' WRITE';
    }

    $this->_db->query(NULL, $q, TRUE);
}

Перемещение узлов без ошибок возможно только в пределах одного корневого узла, перемещение узлов между деревьями необходимо реализовывать путем удаления узла из одного дерева и создания нового узла в другом дереве.

Использование ORM в kohana 3.2

Как и у большинства фреймворков, у kohana есть модуль для работы с базой данных на основе объектов – ORM. Полезность и удобство этого модуля сейчас никто не ставит под сомнение. Многие задачи программирования решаются с помощью ORM. ORM это не только удобство, но и универсальность кода, другими словами: любому программисту использующему ORM будет достаточно просто понять код другого разработчика.

Основные методы и приемы использования ORM.

  • Получение данных из таблицы
    //получаем все записи из таблицы "users".
    $users = ORM::factory('user')
    ->find_all(); 
    
    //получаем все записи из таблицы "users"
    //с условием-фильтром по слову "victor" в поле "name".
    $users = ORM::factory('user')
    ->where('name', 'LIKE', "%victor%")->find_all();
    
    //получаем одну запись со значением поля "name"="victor".
    $user = ORM::factory('user')
    ->where('name', '=', "victor")->find();
    еще вариант:
    $user = ORM::factory('user', $user_id); 
    что соответствует такому варианту синтаксиса
    $user = ORM::factory('user')->where('id', '=', $user_id)->find();

    Continue reading “Использование ORM в kohana 3.2”

Использование функций SQL в Query Builder и ORM фреймворка Kohana

Иногда возникает необходимость воспользоваться функцией SQL в Query Builder или в ORM, это можно сделать при помощи:
$users = ORM::factory('user')->where(DB::expr('LOWER(`name`)), 'like', "%$searchdata%")->find_all();
Т.е. в данном примере мы средствами SQL переводим данные из поля name таблицы users в нижний регистр и производим по ним поиск.

Оптимизация запросов к базе данных Kohana 3.2 (ORM & JOIN)

В kohana есть замечательный модуль ORM, он значительно облегчает жизнь разработчикам.
Хотя как известно “бесплатный сыр бывает только в мышеловке”.

Используя ORM мы получаем простой и удобный доступ к базе данных, как к обычному объекту, но при этом в конечном итоге kohana все же создает обычные SQL запросы.

Таблица пользователей ‘users’
id role_id name
1 2 Вася
2 3 Петя
3 1 Степа
Таблица ролей пользователей ‘roles’
id role_name
1 root
2 admin
3 manager

Допустим мы создали 2 модели к вышеописанным таблицам:

  • user.php
  • role.php

Continue reading “Оптимизация запросов к базе данных Kohana 3.2 (ORM & JOIN)”

  • Recent Posts