Библиотека Laravel MongoDB 'jenssegers/laravel-mongodb' имеет много отношений не работает
Я использую библиотеку MongoDB https://github.com/jenssegers/laravel-mongodb version 3.1.0-alpha
в Laravel 5.3.28
У меня есть две коллекции в MongoDB, и я хочу связать их с hasMany. Значит каждый сотрудник выполняет много задач. Я использовал ссылку и добавил employee_ids в коллекцию задач.
Ниже мой код:
MongoDB:
1-я коллекция: сотрудник
{
"_id" : ObjectId("586ca8c71a72cb07a681566d"),
"employee_name" : "John",
"employee_description" : "test description",
"employee_email" : "john@email.com",
"updated_at" : "2017-01-04 11:45:20",
"created_at" : "2017-01-04 11:45:20"
},
{
"_id" : ObjectId("586ca8d31a72cb07a6815671"),
"employee_name" : "Carlos",
"employee_description" : "test description",
"employee_email" : "carlos@email.com",
"updated_at" : "2017-01-04 11:45:20",
"created_at" : "2017-01-04 11:45:20"
}
2-я коллекция: задание
{
"_id" : ObjectId("586ccbcf1a72cb07a6815b04"),
"task_name" : "New Task",
"task_description" : "test description",
"task_status" : 1,
"task_start" : "2017-04-01 12:00:00",
"task_end" : "2017-04-01 02:00:00",
"task_created_at" : "2017-04-01 02:17:00",
"task_updated_at" : "2017-04-01 02:17:00",
"employee_id" : [
ObjectId("586ca8c71a72cb07a681566d"),
ObjectId("586ca8d31a72cb07a6815671")
]
},
{
"_id" : ObjectId("586cd3261a72cb07a6815c69"),
"task_name" : "2nd Task",
"task_description" : "test description",
"task_status" : 1,
"task_start" : "2017-04-01 12:00:00",
"task_end" : "2017-04-01 02:00:00",
"task_created_at" : "2017-04-01 02:17:00",
"task_updated_at" : "2017-04-01 02:17:00",
"employee_id" : ObjectId("586ca8c71a72cb07a681566d")
}
Laravel: модель: сотрудник:
<?php
namespace App\Models;
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class Employee extends Eloquent {
protected $collection = 'employee';
protected $primaryKey = '_id';
public function tasks()
{
return $this->hasMany('App\Models\Task');
}
}
Laravel: Модель: Задача:
<?php
namespace App\Models;
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class Task extends Eloquent {
protected $collection = 'task';
protected $primaryKey = '_id';
public function employees()
{
return $this->belongsTo('App\Models\Employee');
}
}
Я хочу получить задания, назначенные конкретному сотруднику.
контроллер:
public function EmployeeData($data)
{
$employees = Employee::with('tasks')->where('_id', new \MongoDB\BSON\ObjectID('586ca8d31a72cb07a6815671'))->get();
echo "<pre>";
print_r($employees);exit;
}
Выход:
Illuminate\Database\Eloquent\Collection Object
(
[items:protected] => Array
(
[0] => App\Models\Employee Object
(
[connection:protected] => mongodb
[collection:protected] => lt_employees
[primaryKey:protected] => _id
[employee_id:App\Models\Employee:private] =>
[employee_name:App\Models\Employee:private] =>
[employee_description:App\Models\Employee:private] =>
[employee_email:App\Models\Employee:private] =>
[employee_created_at:App\Models\Employee:private] =>
[employee_updated_at:App\Models\Employee:private] =>
[parentRelation:protected] =>
[table:protected] =>
[keyType:protected] => int
[perPage:protected] => 15
[incrementing] => 1
[timestamps] => 1
[attributes:protected] => Array
(
[_id] => MongoDB\BSON\ObjectID Object
(
[oid] => 586ca8d31a72cb07a6815671
)
[employee_name] => Carlos
[employee_description] => test description
[employee_email] => carlos@email.com
[updated_at] => 2017-01-04 11:45:20
[created_at] => 2017-01-04 11:45:20
)
[original:protected] => Array
(
[_id] => MongoDB\BSON\ObjectID Object
(
[oid] => 586ca8d31a72cb07a6815671
)
[employee_name] => Carlos
[employee_description] => test description
[employee_email] => carlos@email.com
[updated_at] => 2017-01-04 11:45:20
[created_at] => 2017-01-04 11:45:20
)
[relations:protected] => Array
(
[tasks] => Illuminate\Database\Eloquent\Collection Object
(
[items:protected] => Array
(
)
)
)
[hidden:protected] => Array
(
)
[visible:protected] => Array
(
)
[appends:protected] => Array
(
)
[fillable:protected] => Array
(
)
[guarded:protected] => Array
(
[0] => *
)
[dates:protected] => Array
(
)
[dateFormat:protected] =>
[casts:protected] => Array
(
)
[touches:protected] => Array
(
)
[observables:protected] => Array
(
)
[with:protected] => Array
(
)
[exists] => 1
[wasRecentlyCreated] =>
)
)
)
В выходных данных элементы реляционных задач пусты.
Кто-нибудь может подсказать, что отношение ч / б коллекций правильное?
Обновить
Я использовал принадлежащий ToMany в отношении. Теперь мои модели:
В модели сотрудника:
public function tasks()
{
return $this->belongsToMany('App\Models\Task');
}
В модели задач:
public function employees()
{
return $this->belongsToMany('App\Models\Employee');
}
Это документы:
Коллекция сотрудников
{
"_id" : ObjectId("586ca8c71a72cb07a681566d"),
"employee_name" : "Carlos",
"employee_description" : "test description",
"employee_email" : "carlos@email.com",
"updated_at" : "2017-01-04 11:45:20",
"created_at" : "2017-01-04 11:45:20",
"task_ids" : [
ObjectId("586ccbcf1a72cb07a6815b04"),
ObjectId("586cd3261a72cb07a6815c69")
]
},
{
"_id" : ObjectId("586ca8d31a72cb07a6815671"),
"employee_name" : "John",
"employee_description" : "test description",
"employee_email" : "john@email.com",
"updated_at" : "2017-01-04 11:45:20",
"created_at" : "2017-01-04 11:45:20"
}
Сборник задач
{
"_id" : ObjectId("586ccbcf1a72cb07a6815b04"),
"task_name" : "New Task",
"task_description" : "test description",
"task_status" : 1,
"task_start" : "2017-04-01 12:00:00",
"task_end" : "2017-04-01 02:00:00",
"task_created_at" : "2017-04-01 02:17:00",
"task_updated_at" : "2017-04-01 02:17:00",
"employee_ids" : [
ObjectId("586ca8c71a72cb07a681566d"),
ObjectId("586ca8d31a72cb07a6815671")
]
},
{
"_id" : ObjectId("586cd3261a72cb07a6815c69"),
"task_name" : "2nd Task",
"task_description" : "test description",
"task_status" : 1,
"task_start" : "2017-04-01 12:00:00",
"task_end" : "2017-04-01 02:00:00",
"task_created_at" : "2017-04-01 02:17:00",
"task_updated_at" : "2017-04-01 02:17:00",
"employee_ids" : ObjectId("586ca8c71a72cb07a681566d")
}
Я получаю первого сотрудника с этими документами:
$employee = Employee::with('tasks')->first();
dd($employee);
И я получил вывод с пустым отношением:
Employee {#176
#connection: "mongodb"
#collection: "employee"
#primaryKey: "_id"
-employee_id: null
-employee_name: null
-employee_description: null
-employee_email: null
-employee_created_at: null
-employee_updated_at: null
#parentRelation: null
#table: null
#keyType: "int"
#perPage: 15
+incrementing: true
+timestamps: true
#attributes: array:10 [
"_id" => ObjectID {#170}
"employee_name" => "Carlos"
"employee_description" => "test description"
"employee_email" => "carlos@email.com"
"updated_at" => "2017-01-04 11:45:20"
"created_at" => "2017-01-04 11:45:20"
"task_ids" => array:2 [
0 => ObjectID {#174}
1 => ObjectID {#175}
]
]
#original: array:10 [
"_id" => ObjectID {#170}
"employee_name" => "Carlos"
"employee_description" => "test description"
"employee_email" => "carlos@email.com"
"updated_at" => "2017-01-04 11:45:20"
"created_at" => "2017-01-04 11:45:20"
"task_ids" => array:2 [
0 => ObjectID {#174}
1 => ObjectID {#175}
]
]
#relations: array:1 [
"tasks" => Collection {#173
#items: []
}
]
#hidden: []
#visible: []
#appends: []
#fillable: []
#guarded: array:1 [
0 => "*"
]
#dates: []
#dateFormat: null
#casts: []
#touches: []
#observables: []
#with: []
+exists: true
+wasRecentlyCreated: false
}
1 ответ
По вашему другому вопросу я понял, что задание может принадлежать многим сотрудникам, верно? Так что вы должны использовать belongsToMany
отношения в вашем Task
модель. Также ваш пример коллекции "задача" показывает, что в одном документе employee_id
это массив, а в другом документе это ObjectId, когда оба должны быть массивами.
Во всяком случае, мне было трудно понять это, но я видел, что вы не можете использовать hasMany
как обратное belongsToMany
, так как belongsToMany
создает массив идентификаторов, и hasMany
плохо работает с массивами. Я бы сказал, что нам нужно что-то вроде hasManyInArray
, но когда я ассоциирую belongsToMany
В связи с "родительским" документом создается массив идентификаторов, что заставляет меня думать, что родитель должен также использовать belongsToMany
даже если он не "принадлежит", но на самом деле "имеет". Поэтому, когда вы хотите связать сотрудника с такой задачей:
$task->employees()->save($employee);
В результате документ "employee" будет иметь атрибут "task_ids" с единственным идентификатором задачи, который у него должен быть. Таким образом, кажется, что путь с Jenssegers: использовать belongsToMany
в обеих моделях:
Laravel: модель: сотрудник:
<?php
namespace App\Models;
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class Employee extends Eloquent
{
protected $collection = 'employee';
public function tasks()
{
return $this->belongsToMany(Task::class);
}
}
Laravel: Модель: Задача:
<?php
namespace App\Models;
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class Task extends Eloquent
{
protected $collection = 'task';
public function employees()
{
return $this->belongsToMany(Employee::class);
}
}
И вы бы использовали это как:
// Give a task a new employee
$task->employees()->save($employee);
// Or give an employee a new task
$employee->tasks()->save($task);
Единственное, что с этим связано, это то, что когда вы посмотрите на базу данных, вы увидите, что ваши документы о сотрудниках имеют массив с именем "task_ids", а внутри - идентификатор единственной задачи, которую имеет каждый сотрудник. Я надеюсь, что это помогло.
Просто некоторые примечания, вы знаете, что вам не нужно определять имя первичного ключа для каждой модели, верно? Вам не нужно это:
protected $primaryKey = '_id';
Также вам не нужно определять название коллекции (т.е. protected $collection = 'employee';
), если вы действительно не хотите, чтобы они были в единственном числе (по умолчанию они во множественном числе).
Я встал посреди ночи (сейчас 3:52 утра) и кое-что проверил на компьютере, а затем проверил ТАК и увидел твой вопрос. Надеюсь, на этот раз я ответил достаточно скоро для тебя, похоже, мы находимся в разных часовых поясах.
Обновить
Это документы, которые я создал для тестирования:
коллекция сотрудников
{
"_id" : ObjectId("5870ba1973b55b03d913ba54"),
"name" : "Jon",
"updated_at" : ISODate("2017-01-07T09:51:21.316Z"),
"created_at" : ISODate("2017-01-07T09:51:21.316Z"),
"task_ids" : [
"5870ba1973b55b03d913ba56"
]
},
{
"_id" : ObjectId("5870ba1973b55b03d913ba55"),
"name" : "Doe",
"updated_at" : ISODate("2017-01-07T09:51:21.317Z"),
"created_at" : ISODate("2017-01-07T09:51:21.317Z"),
"task_ids" : [
"5870ba1973b55b03d913ba56"
]
}
сборник задач
{
"_id" : ObjectId("5870ba1973b55b03d913ba56"),
"name" : "New Task",
"updated_at" : ISODate("2017-01-07T09:51:21.317Z"),
"created_at" : ISODate("2017-01-07T09:51:21.317Z"),
"employee_ids" : [
"5870ba1973b55b03d913ba54",
"5870ba1973b55b03d913ba55"
]
}
С этими документами я получаю первого сотрудника как это:
$employee = Employee::with('tasks')->first();
dd($employee);
И в выводе мы можем видеть, что атрибут отношений представляет собой массив:
Employee {#186 ▼
#collection: "employee"
#primaryKey: "_id"
// Etc.....
#relations: array:1 [▼
"tasks" => Collection {#199 ▼
#items: array:1 [▼
0 => Task {#198 ▼
#collection: "task"
#primaryKey: "_id"
// Etc....
#attributes: array:5 [▼
"_id" => ObjectID {#193}
"name" => "New Task"
"updated_at" => UTCDateTime {#195}
"created_at" => UTCDateTime {#197}
"employee_ids" => array:2 [▶]
]
}
]
}
]
}
Обновление 2
belongsToMany
метод не в файле, который вы упоминаете, потому что этот класс (т.е. Jenssegers\Mongodb\Eloquent\Model
) расширяет класс Eloquent Model от Laravel, и вот где belongsToMany
метод есть.
Итак, это должно быть то, почему это не работает для вас, потому что массивы должны быть строками, а не ObjectIds. Почему это? Так как библиотека Jenssegers работает, она сохраняет идентификаторы в виде строк. Я также нашел это поведение странным, но так оно и работает. Помните, что вы должны связывать объекты, используя библиотеку Jenssegers, а не создавая данные вручную в базе данных. Как вы можете индексировать идентификаторы? Просто создайте нормальный индекс в MongoDB, как tasks.createIndex({task_ids: 1})
, Вот документация о том, как создавать индексы: https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/. Вы также можете создавать индексы по миграции, вот документы по миграции, обязательно прочитайте заметки Jenssegers по миграции.
Вы можете получить доступ к tasks
Реальность такова: $employee->tasks;
, Вы получаете доступ к отношениям, получая свойство с тем же именем метода, с которым вы объявили свое отношение, так что если у вас есть:
class Post
{
public function owner()
{
return $this->belongsTo(User::class);
}
}
Вы получаете отношение как $post->owner;
, Вот документация по отношениям: https://laravel.com/docs/5.3/eloquent-relationships