Библиотека 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

Другие вопросы по тегам