Русскоязычный форум, посвященный фреймворку Kohana

Все о фреймворке Kohana. Обсуждение уроков, документации.
Текущее время: 20 апр 2024, 00:26

Часовой пояс: UTC + 4 часа [ Летнее время ]




Начать новую тему Ответить на тему  [ Сообщений: 35 ]  На страницу Пред.  1, 2, 3, 4  След.
Автор Сообщение
 Заголовок сообщения: Re: ORM связи и значения
СообщениеДобавлено: 25 апр 2013, 19:08 
Не в сети
Бывалый
Аватара пользователя

Зарегистрирован: 02 апр 2013, 16:26
Сообщения: 474
Откуда: Сергиев Посад
ну да все нормально:
sql:
Код:
CREATE TABLE IF NOT EXISTS `cms_menu` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS `cms_menus_pages` (
  `menu_id` int(11) NOT NULL,
  `page_id` int(11) NOT NULL,
  `sort` int(11) DEFAULT '0'
);
CREATE TABLE IF NOT EXISTS `cms_page` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  PRIMARY KEY (`id`)
);

модель Menu.php
Код:
class Model_Menu extends ORM
{
    protected $_table_name = 'menu';
    protected $_has_many = array(
        'pages' => array(
            'model'   => 'Page',
            'through' => 'menus_pages',
        ),
    );
}

модель Page.php:
Код:
class Model_Page extends ORM
{
    protected $_table_name = 'page';
}

Контроллер Test.php:
Код:
class Controller_Test extends Controller_Layout_Default
{
    public function action_index()
    {
       // меню с id = 1, страницы  отсортированны по полю sort
        $pages = ORM::factory('Menu', 1)->pages->order_by('sort', 'DESC')->find_all();
        //print_r($pages);
        foreach ( $pages as $page ){
            print_r( $page->as_array() );
        }
    }
}

Данный код минимизирован чтобы упростить пример, не используйте его в таком виде!
Генерирует аж 4 запроса, минимизируем до 1:
1.добавим описание полей в модели:
Код:
    protected $_table_columns = array(
        'id' => array(
            'type'                     => 'int',
            'min'                      => '1',
            'max'                      => '10000',
            'column_name'              => 'id',
            'data_type'                => 'int',
            'is_nullable'              => false,
            'ordinal_position'         => 1,
            'display'                  => 11,
            'extra'                    => 'auto_increment',
            'key'                      => 'PRI',
            'privileges'               => 'select,insert,update,references',
        ),
        'name' => array(
            'type'                     => 'string',
            'column_name'              => 'name',
            'data_type'                => 'varchar',
            'is_nullable'              => false,
            'ordinal_position'         => 2,
            'character_maximum_length' => 255,
            'collation_name'           => 'utf8_general_ci',
            'privileges'               => 'select,insert,update,references',
        ),
    );

Описание полей генерируется с помощью ORM->list_columns http://kohanaframework.org/3.3/guide-ap ... st_columns
2. список страниц получаем так:
Код:
$pages = ORM::factory('Menu')->pages->where('id', '=', 1)->order_by('sort', 'DESC')->find_all();


Вот еще материал по данной теме(правда не знаю насколько он актуален):
Цитата:
Когда происходит связывание двух моделей с помощьюе третьей таблицы ORM почемуто не дает доступ к полям третьей таблицы, если попытаться сделать ->with('table_through') то будет ошибка, так как ORM попытается приджойнить таблицу второй раз. Код ниже как раз и позволяет без лишнего джойна включить поля table_through в результат

http://blog.alaruss.com/2010/10/through.html

_________________
Майкл Джордан играет в баскетбол. Чарльз Мэнсон убивает людей. Я пишу код. У каждого свой талант.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: ORM связи и значения
СообщениеДобавлено: 26 апр 2013, 09:40 
Не в сети
Бывалый
Аватара пользователя

Зарегистрирован: 23 июл 2012, 21:58
Сообщения: 100
WinterSilence позвольте все же потупить...
Цитата:
Данный код минимизирован чтобы упростить пример, не используйте его в таком виде!

Я полагаю это вы написали про Контроллер Test.php, так как код ниже и...
Цитата:
1.добавим описание полей в модели:

Для чего это? Для чего вообще описывать поля? И что было бы, если поле name не описать, к примеру.
Или при описании поля id, я не опишу параметр 'max' => '10000'?
Цитата:
2. список страниц получаем так:
$pages = ORM::factory('Menu')->pages->where('id', '=', 1)->order_by('sort', 'DESC')->find_all();

Разве where в данном случае не применяется уже к pages?
Заранее благодарен.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: ORM связи и значения
СообщениеДобавлено: 26 апр 2013, 12:29 
Не в сети
Бывалый
Аватара пользователя

Зарегистрирован: 02 апр 2013, 16:26
Сообщения: 474
Откуда: Сергиев Посад
borodatych> Вначале идет минимальный пример, т.е. если вы его запустите все будет работать, но в реальных условиях он не применяется, он нужен чтобы просто продемонстрировать принцип. Далее я усложняю пример приводя его к более менее реалистичному.

Цитата:
Для чего это? Для чего вообще описывать поля?

Если не описывать поля явно, то при создании модели их структура будет формироваться автоматически: будет запрос к базе возвращающий список полей и на его основании сформулируется данный список. Но в условиях реального сайта это постоянная избыточная нагрузка, поэтому поля либо задаются явно, либо кешируются.
Где данные поля потом применяются я не смотрел, предлагаю сделать данное исповедование в качестве домашнего задания, потом расскажете нам ;)
Скорее всего они входят в фильтры\валидаторы и могут быть переопределены в соответствующих методах.

Цитата:
Разве where в данном случае не применяется уже к pages?

до
Цитата:
$pages = ORM::factory('Menu', 1)->pages->order_by('sort', 'DESC')->find_all();

после
Цитата:
$pages = ORM::factory('Menu')->pages->where('id', '=', 1)->order_by('sort', 'DESC')->find_all();

_________________
Майкл Джордан играет в баскетбол. Чарльз Мэнсон убивает людей. Я пишу код. У каждого свой талант.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: ORM связи и значения
СообщениеДобавлено: 26 апр 2013, 13:19 
Не в сети
Бывалый
Аватара пользователя

Зарегистрирован: 23 июл 2012, 21:58
Сообщения: 100
Благодарю за ответы, но как все таки в таблице cms_menus_pages записать данные в колонку sort?
Цитата:
$pages = ORM::factory('Menu', 1)->pages->order_by('sort', 'DESC')->find_all();

В данном случае мы выбираем menu с id=1 и потом уже page, так?
Цитата:
$pages = ORM::factory('Menu')->pages->where('id', '=', 1)->order_by('sort', 'DESC')->find_all();

Здесь мы выбираем все menu, для них page с id=1, не так интерпретировать что ли?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: ORM связи и значения
СообщениеДобавлено: 26 апр 2013, 14:56 
Не в сети
Бывалый
Аватара пользователя

Зарегистрирован: 02 апр 2013, 16:26
Сообщения: 474
Откуда: Сергиев Посад
перепутал =\ через orm получается только 2я запросами, лучше использовать database.
хотя попробую поиграться с моделями, может и получится сделать компактнее

Цитата:
как все таки в таблице cms_menus_pages записать данные в колонку sort?

создать модель для этой таблицы и через неё сохранить, можно orm переопределить как в статье по ссылке.

пользуйтесь Profiling для просмотра запросов http://kohanaframework.org/3.3/guide/kohana/profiling

_________________
Майкл Джордан играет в баскетбол. Чарльз Мэнсон убивает людей. Я пишу код. У каждого свой талант.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: ORM связи и значения
СообщениеДобавлено: 26 апр 2013, 15:23 
Не в сети
Бывалый
Аватара пользователя

Зарегистрирован: 02 апр 2013, 16:26
Сообщения: 474
Откуда: Сергиев Посад
Код:
$pages = ORM::factory('Menu')->pages->or_where('menu_id', '=', 1)->order_by('sort', 'DESC')->find_all();

генерирует всего один запрос
Код:
SELECT `cms_page`.`id` AS `id`, `cms_page`.`name` AS `name` 
FROM `cms_page` AS `cms_page`
JOIN `cms_menus_pages` ON (`cms_menus_pages`.`page_id` = `cms_page`.`id`)
WHERE `cms_menus_pages`.`menu_id` IS NULL OR `menu_id` = 1 ORDER BY `sort` DESC

не очень красиво, но разбираться где генерируется
Код:
`cms_menus_pages`.`menu_id` IS NULL
лень :oops:

_________________
Майкл Джордан играет в баскетбол. Чарльз Мэнсон убивает людей. Я пишу код. У каждого свой талант.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: ORM связи и значения
СообщениеДобавлено: 26 апр 2013, 17:10 
Не в сети
Бывалый
Аватара пользователя

Зарегистрирован: 23 июл 2012, 21:58
Сообщения: 100
Премного благодарен за проявленный интерес и все старания.
Жаль что нельзя сделать просто как обычно:
Код:
$products->save();
$products->add('categories',$data['cat_id']);


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: ORM связи и значения
СообщениеДобавлено: 26 апр 2013, 17:16 
Не в сети
Бывалый
Аватара пользователя

Зарегистрирован: 02 апр 2013, 16:26
Сообщения: 474
Откуда: Сергиев Посад
borodatych> почему нельзя? что мешает вам расширять модель? парадигма mvc как раз подразумевает обработку данных в моделях,а не в контроллерах

_________________
Майкл Джордан играет в баскетбол. Чарльз Мэнсон убивает людей. Я пишу код. У каждого свой талант.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: ORM связи и значения
СообщениеДобавлено: 28 апр 2013, 00:39 
Не в сети
Бывалый
Аватара пользователя

Зарегистрирован: 23 июл 2012, 21:58
Сообщения: 100
Цитата:
что мешает вам расширять модель?

Действительно, что то я совсем))
Позвольте спросить совета. Как лучше организовать.
Так как меню несколько, то есть как чекбоксы, когда страницу нужно включить меню, так и значения.
Но не во все меню нужно включать страницу.
Соответственно в контроллер из вида попадет совсем не красивый массив с меню.
Checkbox либо он есть, либо его нет, а вот input может передать пустое имя.
Предполагаю поняли про что я?
Сейчас я попробовал и оно работает.
Добавил метод:
Код:
class ORM extends Kohana_ORM {
    public function addMenu($alias,$far_key,$position){
        if(is_array($far_key)){throw new Kohana_Exception('$far_key is array');}
        if(is_array($position)){throw new Kohana_Exception('$position is array');}
      $far_key = ($far_key instanceof ORM)?$far_key->pk():$far_key;
      $columns = array(
            $this->_has_many[$alias]['foreign_key'],
            $this->_has_many[$alias]['far_key'],
            $this->_has_many[$alias]['sort']
                );
      $foreign_key = $this->pk();
      $query = DB::insert($this->_has_many[$alias]['through'],$columns);
      $query->values(array($foreign_key,$far_key,$position));
      $query->execute($this->_db);
      return $this;
   }
}

В модели добавил одно значение:
Код:
class Model_Page extends ORM_MPTT{
    protected $_has_many = array(
            'menu' => array(
            'model' => 'Menu',
            'through' => 'menus_pages',
            'sort' => 'sort',
        ),
    );
}

И в контроллере в переборе массива, при условии если есть checkbox и input не ноль и не пусто:
Код:
$page->addMenu('menu',$menu_id,$position);

Дак вот вопрос, мне перебор массива оставить в контроллере или все же добавить в эту функцию?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: ORM связи и значения
СообщениеДобавлено: 28 апр 2013, 01:58 
Не в сети
Бывалый
Аватара пользователя

Зарегистрирован: 02 апр 2013, 16:26
Сообщения: 474
Откуда: Сергиев Посад
1. вот так делать не стоит:
Цитата:
class ORM extends Kohana_ORM

нужно данные методы определить в конкретной модели, чтобы не таскать их по всем моделям

2. function addMenu как-то странно на мой взгляд реализована, DB быть не должно добавьте лучше явно атрибут $pages в модель и через него сохраняйте,а еще лучше расширьте ORM так, чтобы он использовал get\set\save еще и для связующей таблицы.

3. в Model_Page не должно быть sort, т.к. в таблице этой модели поле sort отсутствует, хотя могу ошибаться

4.
Цитата:
$page->addMenu('menu',$menu_id,$position);
не 'menu', а 'Menu' т.к. модель называется Model_Menu
Цитата:
И в контроллере в переборе массива, при условии если есть checkbox и input не ноль и не пусто

Я бы делал так:
В виде задаем id меню
Код:
<input type="hidden" name="menu_id" value="1">

и страницы:
Код:
..
<td><input type="checkbox" name="pages[{$page[id]}][id]" value="{$page[id]}"></td>
<td>{$page[name]}</td>
<td><input type="text" size="4" name="pages[{$page[id]}][sort]" value="{$page[sort]}"></td>
...

В контроллере создаем модель меню(которая в свою очередь через $pages связана с таблицей menus_pages), удаляем все страницы для данного меню, передаем POST данные в модель и сохраняем.

5. всю работу с данными осуществляют в моделях, контроллер служит только для передачи данных в\из модели\вида. Контроллер он как телефонистка: ей говорят мне бы поговорить с Петровым, она и соединяет, за него она на вопросы звонящего не отвечает. Модель не должна соответственно содержать никаких html тегов, они все в виде, ну а вид не должен как-то изменять данные (или только какие-то мелкие действия вроде экранирования спецсимволов и т.п.). Если нужно 3 в 1, то это реализуется через хэлпер

_________________
Майкл Джордан играет в баскетбол. Чарльз Мэнсон убивает людей. Я пишу код. У каждого свой талант.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 35 ]  На страницу Пред.  1, 2, 3, 4  След.

Часовой пояс: UTC + 4 часа [ Летнее время ]


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 20


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Все о фреймворке Kohana  | 
Powered by phpBB® Forum Software © phpBB Group