2017-01-07 8 views
0

Я использую библиотеку MongoDB https://github.com/jenssegers/laravel-mongodbversion 3.1.0-alpha в Laravel 5.3.28 У меня есть две коллекции в MongoDB, и я хочу сделать hasMany соотношение б/ш них. Означает, что каждый сотрудник выполняет множество задач. Я использовал ссылку и добавил employee_ids в коллекцию задач.Laravel MongoDB библиотека «jenssegers/Laravel-MongoDB» отношения hasMany не работает

Ниже мой код:

MongoDB:

первая коллекция: Сотрудник

{ 
    "_id" : ObjectId("586ca8c71a72cb07a681566d"), 
    "employee_name" : "John", 
    "employee_description" : "test description", 
    "employee_email" : "[email protected]", 
    "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" : "[email protected]", 
    "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_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] => [email protected] 
          [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] => [email protected] 
          [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] => 
       ) 

     ) 

) 

В выходных данных, отношение задачи элементы пусты.

Может ли кто-нибудь предложить мне, чтобы отношения ч/б коллекций были правильными?

Update

Я использовал belongsToManyin отношение.Теперь мои модели:

В модели Сотрудника:

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" : "[email protected]", 
    "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" : "[email protected]", 
    "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); 

И я gotthe выход с пустым отношением:

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" => "[email protected]" 
    "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" => "[email protected]" 
    "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 
} 

ответ

2

я понял другим вопрос, что задача может принадлежать многим сотрудникам, не так ли? Поэтому вы должны использовать отношения belongsToMany в своей модели Task. Также ваш пример коллекции «задача» показывает, что в одном документе employee_id есть массив, а в другом документе это ObjectId, когда оба должны быть массивами.

Во всяком случае, у меня было трудное время, пытаясь понять это, но я видел, что вы не можете использовать hasMany как обратная belongsToMany, поскольку belongsToMany создает массив идентификаторов и hasMany не хорошо работать с массивами. Я бы сказал, что нам нужно что-то вроде hasManyInArray, но когда я связываю связь belongsToMany, «родительский» документ создает массив идентификаторов, что заставляет меня думать, что родитель должен также использовать belongsToMany, даже если он не " принадлежат «но на самом деле» имеет ». Поэтому, когда вы связать работник к задаче, как это:

$task->employees()->save($employee); 

«работник» документ будет в конечном итоге, «task_ids» атрибут с единственным идентификатором задачи он должен иметь. Так что, как представляется, путь, чтобы пойти с Jenssegers: использовать belongsToMany в обеих моделях:

Laravel: Модель: Employee:

<?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 утра здесь) и проверил что-то на компьютере, а затем проверил так что видел ваш вопрос, я надеюсь, что на этот раз я ответил достаточно быстро для вас, мы похоже, находятся в разных часовых поясах.

Update

Это документы, которые я создал для тестирования:

коллекция сотрудник

{ 
    "_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 [▶] 
      ] 
     } 
     ] 
    } 
    ] 
} 

Update 2

belongsToMany метода нет в файле, который вы упоминаете, использовать этот класс (т. Jenssegers\Mongodb\Eloquent\Model) расширяет класс Laravel's Eloquent Model, и именно здесь используется метод belongsToMany.

Хорошо, поэтому должно быть поэтому, что оно не работает для вас, потому что массивы должны быть строками вместо ObjectIds. Почему это? Так как библиотека Jenssegers работает, она сохраняет идентификаторы как строки. Я также нашел это поведение странным, но так оно и работает. Помните, что вы принимаете для связывания объектов с использованием библиотеки Jenssegers, а не путем создания данных вручную в базе данных. Как вы можете индексировать идентификаторы? Просто создайте нормальный индекс в MongoDB, например tasks.createIndex({task_ids: 1}). Вот документация о том, как создавать индексы: https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/. Вы также можете создавать индексы при миграции, here are the docs on migrations, обязательно прочитайте Jenssegers notes on migrations.

Вы можете получить доступ к tasks realtion следующим образом: $employee->tasks;. Вы получаете доступ к отношениям, получая свойство с тем же именем методы вы объявленной родственницей с, так что если у вас есть:

class Post 
{ 
    public function owner() 
    { 
     return $this->belongsTo(User::class); 
    } 
} 

Вы получаете соотношение как $post->owner;.Вот документация по отношениям: https://laravel.com/docs/5.3/eloquent-relationships

+0

Спасибо за ответ. Теперь я использовал 'attribToMany' в обеих моделях и в документах task_ids в коллекции сотрудников, как вы писали в приведенном выше ответе, но это не сработало. Он посылает мне тот же результат – okconfused

+0

Не могли бы вы обновить свой вопрос новыми документами? Я обновляю свой ответ с документами, которые я создал для тестирования, которые работают. – Parziphal

+0

Я обновил вопрос. Скажите мне, что мы используем отношение 'ownToMany', используя файл' Jenssegers \ Mongodb \ Eloquent \ Model 'в 'Model', но в этом файле отношения' ownToMany' не существует. – okconfused