Laravel по-русски

Русское сообщество разработки на PHP-фреймворке Laravel.

Ты не вошёл. Вход тут.

#1 28.11.2012 07:36:21

apostol_11
Откуда: Челябинск
Сообщений: 13

Eloquent ORM проблема со связью many to many

Изучаю данный fw, и столкнулся с проблемой У меня есть модель пользователя и в ней есть метод

public function roles()
    {
        return $this->has_many_and_belongs_to('acl', 'cross_users_acls');
    }

Есть две таблицы users и acls в которых соответственно хранятся пользователи и права доступа, таблица cross_users_acls является таблицей пересечений прав доступа и пользователей.
Затем с помощью этого метода я хочу проверить есть ли права на создание пользователя

 public function get_new(){
        if(Auth::check()&&User::find(Auth::user()->id)->roles()->get()){
            return View::make('users.new')
                ->with('title', 'Добавление нового пользователя');
        }else{
            return Redirect::to('norights');
        }
    }

Сам вопрос, что возвращает User::find(Auth::user()->id)->roles()->get()?

Не в сети

#2 28.11.2012 09:43:51

Re: Eloquent ORM проблема со связью many to many

  1. PHPUser::find(Auth::user()->id)

А зачем ты сначала получаешь ID пользователя из модели, возвращённой Auth::user(), а затем ищешь эту самую модель в таблице по ID, который из неё же и получил? Почему не просто PHPAuth::user()->roles()->get()?

  1. Сам вопрос, что возвращает User::find(Auth::user()->id)->roles()->get()?

Методы отношений возвращают обычный запрос с привязанными условиями, то есть на них можно делать любые методы Query — first(), avg() и т.д. В твоём случае он должен вернуть массив моделей acl (после get()) — кстати, у тебя клсс называется маленькими буквами? В параметре ты передаёшь не имя таблицы, а имя класса модели, обычно это User, ACL и т.п…

И раз это массив код вызовет ошибку, так как тебе надо или first(), или цикл.

Есть перевод хорошей статьи про зависимости.

Не в сети

#3 29.11.2012 07:53:15

apostol_11
Откуда: Челябинск
Сообщений: 13

Re: Eloquent ORM проблема со связью many to many

Спасибо за помощь. Разобрался. А статьи читал, просто не мог понять что он должен именно массив моделей вернуть.

Не в сети

#4 29.11.2012 09:37:29

Re: Eloquent ORM проблема со связью many to many

  1. просто не мог понять что он должен именно массив моделей вернуть.

Это можно легко проверить с помощью var_dump.

Не в сети

#5 24.12.2012 12:27:58

Re: Eloquent ORM проблема со связью many to many

А еще в laravel есть очень хорошая функция PHPdd(). Она делает вывод также как и PHPvar_dump() только дополнительно обрамляет его тегами <pre></pre> что дает возможность удобно просматривать его в браузере + останавливает выполнение самого скрипта.

Не в сети

#6 24.12.2012 13:02:32

Re: Eloquent ORM проблема со связью many to many

Поскольку уже есть тема по отношениям типа Many-To-Many пожалуй стоит задать вопрос именно в ней.
У меня следующие модели:
— Модель сценария

PHP
class Scenario extends Eloquent
{
        public static 
$timestamps false;
        public static 
$table 'scenarios';

        public function 
configuration(){
            return 
$this->has_many_and_belongs_to('Configuration','scenario_to_configuration','scenario_id');
        }

}

— Модель конфигурации

PHP
class Configuration extends Eloquent
{
        public static 
$timestamps false;
        public static 
$table 'configurations';

        public function 
scenario(){
            return 
$this->has_many_and_belongs_to('Scenario','scenario_to_configuration','configuration_id');
        }

}

Один сценарий может входить в множество конфигураций, одна конфигурация может содержать множество сценариев. Для реализации данного типа отношения существует промежуточная таблица:

sqlCREATE TABLE `scenario_to_configuration` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `configuration_id` bigint(20) unsigned NOT NULL,
  `scenario_id` bigint(20) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

При запросе вида PHP$conf Scenario::find($id)->configuration()->get(); Получаю сообщение:

SQLSTATE[42S22]: Column not found: 1054 Unknown column ’scenario_to_configuration.created_at’ in ’field list’

SQL: SELECT `configurations`.*, `scenario_to_configuration`.`id` AS `pivot_id`, `scenario_to_configuration`.`created_at` AS `pivot_created_at`, `scenario_to_configuration`.`updated_at` AS `pivot_updated_at`, `scenario_to_configuration`.`scenario_id` AS `pivot_scenario_id`, `scenario_to_configuration`.`configuration_id` AS `pivot_configuration_id` FROM `configurations` INNER JOIN `scenario_to_configuration` ON `configurations`.`id` = `scenario_to_configuration`.`configuration_id` WHERE `scenario_to_configuration`.`scenario_id` = ?

Bindings: array (
0 ⇒ 2,
)

Если в промежуточную таблицу добавить следующие поля:

sql`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,

То все хорошо ☺.

Но хотелось бы разобраться почему так? Ведь в обоих моделях переопределено свойство PHPpublic static $timestamps false И таблицы не содержат полей created_at, updated_at. Подскажите как правильно сделать? Нужна ли модель описывающая промежуточную таблицу?

Не в сети

#7 24.12.2012 13:30:04

Re: Eloquent ORM проблема со связью many to many

  1. Но хотелось бы разобраться почему так?

Это беда Eloquent начиная с первой версии. Возможно в Laravel 4 это исправят. В текущей версии всё происходит через класс-модель Laravel\Database\Eloquent\Pivot — по умолчанию она имеет PHP$timestamps true. Изменив эту перменную, например, в start.php, ты можешь отменить временны́е поля для всех промежуточных таблиц в своём проекте.

Отменить их для одних, оставив для других, простым образом нельзя, но можно наследовать новый класс отношения has_many_and_belongs_to и в нём перекрыть метод pivot(), который создаёт модель промежуточной таблицы конкретно для этого отношения.

PHP
// application/start.php
Laravel\Database\Eloquent\Pivot::$timestamps false;

См. laravel\database\eloquent\pivot.php и laravel\database\eloquent\relationships\has_many_and_belongs_to.php.

Не в сети

#8 24.12.2012 13:34:05

Re: Eloquent ORM проблема со связью many to many

Если в промежуточную таблицу добавить следующие поля:

sql`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,

То все хорошо ☺.

Но хотелось бы разобраться почему так? Ведь в обоих моделях переопределено свойство PHPpublic static $timestamps false И таблицы не содержат полей created_at, updated_at. Подскажите как правильно сделать? Нужна ли модель описывающая промежуточную таблицу?

Вот кусок кода из ядра Eloquent:

PHP
public function __construct($model$associated$table$foreign$other)
    {
        
$this->other $other;

        
$this->joining $table ?: $this->joining($model$associated);

        
// If the Pivot table is timestamped, we'll set the timestamp columns to be
        // fetched when the pivot table models are fetched by the developer else
        // the ID will be the only "extra" column fetched in by default.
        
if (Pivot::$timestamps)
        {
            
$this->with[] = 'created_at';

            
$this->with[] = 'updated_at';
        }

        
parent::__construct($model$associated$foreign);
    }

А в модели Pivot по умолчанию стоит

PHP
 public static $timestamps true;

Я думаю можно смело поменять на false, даже не заморачиваясь.

Изменено OrlandoST (24.12.2012 13:35:39)

Не в сети

#9 24.12.2012 13:47:15

Re: Eloquent ORM проблема со связью many to many

Отменить их для одних, оставив для других, простым образом нельзя, но можно наследовать новый класс отношения has_many_and_belongs_to и в нём перекрыть метод pivot(), который создаёт модель промежуточной таблицы конкретно для этого отношения.

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

PHP
return has_many_and_belongs_to->with(array('created_at''updated_at'))

А при вставке указывать вторым атрибутом наши поля

PHP
$model->many_relation->insert(<массив полей для вставки в модель>, <массив для вставки в Pivot>)

Изменено OrlandoST (24.12.2012 13:47:59)

Не в сети

#10 24.12.2012 19:06:17

Re: Eloquent ORM проблема со связью many to many

  1. Вот кусок кода из ядра Eloquent:

Ого, похоже у нас появился участник, который не брезгует заглядывать в исходники Laravel. Так держать ☺

Не в сети

#11 25.12.2012 14:49:16

Re: Eloquent ORM проблема со связью many to many

Proger_XP пишет:

Ого, похоже у нас появился участник, который не брезгует заглядывать в исходники Laravel. Так держать smile

Я в Laravel новичек, поэтому приходится заглядывать. Кстати код прекрасно структурирова и документирован.
Программирую на Kohana, уже привычка выработалась к некоторым решениям. А здесь еще не совсем понял логику разработчиков. Хотя то, что вижу, мне пока нравится.

Вот не совсем понял чем было вызвано решение использовать HTTPFoundation.

Не в сети

#12 25.12.2012 16:06:12

Re: Eloquent ORM проблема со связью many to many

  1. Вот не совсем понял чем было вызвано решение использовать HTTPFoundation.

Мне тоже совершенно не понятно, зачем всю эту муть её тянуть — стиль написания совершенно другой, кода в объёме намного больше и его сложнее понять из-за тучи методов getXXX, prepareXXX и т.п. Не спорю, что она может быть более универсальной, в ней меньше ошибок и т.п., но в моих глазах этот аргумент не перевешивает минус за её громоздкость.

Но это остаётся на совести авторов Laravel.

Не в сети

#13 25.12.2012 18:07:14

Re: Eloquent ORM проблема со связью many to many

Спасибо всем за грамотные советы. Теперь для меня кое-что прояснилось. Надеюсь у меня тоже в скором времени будет получатся разбираться в исходниках ядра Laravel.

Не в сети

#14 25.12.2012 21:26:57

Re: Eloquent ORM проблема со связью many to many

Спасибо всем за грамотные советы. Теперь для меня кое-что прояснилось. Надеюсь у меня тоже в скором времени будет получатся разбираться в исходниках ядра Laravel.

Да не за что! Надеюсь помогли хоть советы то??
И вообще надо русское сообщество развивать, так что не стесняйтесь задавать вопросы!
Искать решение чужих проблем это тоже способ изучения фреймворка ;)

Не в сети

#15 25.12.2012 21:31:33

Re: Eloquent ORM проблема со связью many to many

Мне тоже совершенно не понятно, зачем всю эту муть её тянуть — стиль написания совершенно другой, кода в объёме намного больше и его сложнее понять из-за тучи методов getXXX, prepareXXX и т.п. Не спорю, что она может быть более универсальной, в ней меньше ошибок и т.п., но в моих глазах этот аргумент не перевешивает минус за её громоздкость.

Но это остаётся на совести авторов Laravel.

Возможно откажутся в поздних версиях. По мне код явно чужероден для Laravel. Надо поднять вопрос на англоязычном форуме.

Не в сети

#16 03.01.2013 21:42:19

Re: Eloquent ORM проблема со связью many to many

  1. Да не за что! Надеюсь помогли хоть советы то??

В start.php добавил строку:
PHPLaravel\Database\Eloquent\Pivot::$timestamps false теперь все хорошо ☺.
Можно конечно и в 1-M\laravel\database\eloquent\pivot.php переопределить PHPpublic static $timestamps, тоже работает)
Для моих целей поля `created_at` и `updated_at`не нужны вовсе.

Изменено Dmitriy (03.01.2013 21:45:06)

Не в сети

#17 05.01.2013 10:23:28

Re: Eloquent ORM проблема со связью many to many

В start.php добавил строку:
PHPLaravel\Database\Eloquent\Pivot::$timestamps false теперь все хорошо.
Можно конечно и в 1-M\laravel\database\eloquent\pivot.php переопределить PHPpublic static $timestamps, тоже работает)
Для моих целей поля `created_at` и `updated_at`не нужны вовсе.

Менять код ядра это не совсем ООП подход. Потом забудешь что поменял, и при обновлении версии ядра получишь пляски с бубнами ☺
Первый вариант имхо лучше

Не в сети

Подвал раздела