2014-07-12 14 views
6

Tôi đang xây dựng một CMS package for Laravel.Các vấn đề không rõ ràng và không gian tên Laravel

Tất cả models trong gói này được ràng buộc và được giải quyết từ bộ chứa IoC để chúng có thể dễ dàng được ghi đè trong bất kỳ triển khai cá nhân nào của gói.

Đối với các mối quan hệ không đa hình, điều này đã làm việc một sự quyến rũ.

Ví dụ, một Page đã nhiều PageModules, vì vậy mối quan hệ của nó thay đổi từ:

// \Angel\Core\Page 

public function modules() 
{ 
    return $this->hasMany('PageModule'); 
} 

tới:

// \Angel\Core\Page 

public function modules() 
{ 
    return $this->hasMany(App::make('PageModule')); 
} 

Nhưng tôi đã không thể tìm ra cách để làm điều tương tự với các mối quan hệ đa hình.

Ví dụ, Menu chứa MenuItems và mỗi MenuItem có thể được gắn với một mô hình khác, chẳng hạn như Trang hoặc BlogPost.

Để thực hiện việc này một cách Laravel, tôi đã thêm các mối quan hệ sau vào MenuItem:

// \Angel\Core\MenuItem 

public function linkable() 
{ 
    return $this->morphTo(); 
} 

Và mối quan hệ này để LinkableModel, mà tất cả các mô hình như Page và blogpost mở rộng:

// \Angel\Core\LinkableModel 

public function menuItem() 
{ 
    return $this->morphOne(App::make('MenuItem'), 'linkable'); 
} 

Và bảng menus_items (sử dụng MenuItems) có các hàng sau:

linkable_type  | linkable_id 
-------------------|-------------- 
\Angel\Core\Page | 11 
\Angel\Core\Page | 4 

Tác phẩm này rất tuyệt, nhưng tôi cần linkable_type để nói 'Trang' thay vì '\ Angel \ Core \ Page', và được giải quyết từ 'Trang' của IoC thay vì được mã hóa cứng thành một lớp tên cụ thể.

Những gì tôi đã thử:

Theo this question, nó phải là dễ dàng như việc xác định một tài sản $morphClass đến linkable() lớp học, như vậy:

// \Angel\Core\Page 
protected $morphClass = 'Page'; 

Nhưng khi tôi áp dụng điều này và thay đổi bảng menus_items để trông giống như sau:

linkable_type | linkable_id 
---------------|-------------- 
Page   | 11 
Page   | 4 

... Tôi chỉ gặp lỗi Class 'Page' not found. bất cứ khi nào có thể liên kết() được gọi trên MenuItem.

This is the exact line in Eloquent that throws the error.

Vì vậy, tôi đào vào hùng hồn và nghĩ rằng tôi có thể có thể nhận được ngay với một cái gì đó như thế này:

// \Angel\Core\MenuItem 

public function linkable() 
{ 
    return $this->morphTo(null, App::make($this->linkable_type)); 
} 

... này cảm thấy rất gần gũi, nhưng than ôi: hùng biện gọi linkable() trước khi nó được lấp đầy phần còn lại của các thuộc tính/cột của MenuItem, do đó $ this-> linkable_type là null và do đó sẽ không giải quyết bất cứ điều gì từ IoC.

Cảm ơn bạn rất nhiều trước vì bất kỳ hướng dẫn nào bạn có thể có!

Trả lời

4
public function linkable() 
{ 
    return $this->morphTo(null, App::make($this->linkable_type)); 
} 

này sẽ không làm việc trong mọi trường hợp, vì morphTo() trong Illuminate\Database\Eloquent\Model hy vọng

  1. Các tên của mối quan hệ đa hình ('linkable')
  2. Các loại của đối tượng bị biến dạng ('Trang', không phải là phiên bản của Page)
  3. Các id của đối tượng được morphed

Nếu họ không được cung cấp, Laravel là đủ thông minh để đoán họ và sau đó cho phù trả về một đối tượng Illuminate\Database\Eloquent\MorphTo.

Ngoài ra, $this->linkable_type$this->linkable_id thực sự không được là null trong ngữ cảnh đó.

Hãy có một cái nhìn lướt qua phần liên quan của morphTo() chức năng:

$instance = new $class; 

return new MorphTo(
    $instance->newQuery(), $this, $id, $instance->getKeyName(), $type, $name 
); 

Note: Đây là mã từ phiên bản 4.2.6, mã liên kết ở trên có vẻ là từ một phiên bản sau và hơi khác một chút và hàm trả về một BelongsTo thay vì đối tượng MorphTo.

Vấn đề cụ thể là $instance = new $class; - lớp học chỉ đơn giản là được instanciated và không được giải quyết. Nhưng bạn chỉ có thể lấy một phần của sự kỳ diệu và xử lý nó tự hỏi:

public function linkable() 
{ 
    $instance = App::make($this->linkable_type); 

    $id = 'linkable_id'; 
    $type = 'linkable_type'; 
    $name = 'linkable'; 

    return new MorphTo(
     $instance->newQuery(), $this, $id, $instance->getKeyName(), $type, $name 
    ); 
} 

Điều này thực sự nên làm việc (chưa được thử nghiệm nó), nhưng tôi không chắc chắn về bất kỳ tác dụng phụ nó có thể gây ra ở một số cạnh các trường hợp.

Hoặc có thể bạn cũng có thể chỉ ghi đè lên toàn bộ chức năng trong MenuItem -Người mẫu của bạn và chỉ cần điều chỉnh một phần có liên quan:

public function morphTo($name = null, $type = null, $id = null) 
{ 
    if (is_null($name)) 
    { 
     list(, $caller) = debug_backtrace(false); 

     $name = snake_case($caller['function']); 
    } 

    list($type, $id) = $this->getMorphs($name, $type, $id); 

    //eager loading 
    if (is_null($class = $this->$type)) 
    { 
     return new MorphTo(
      $this->newQuery(), $this, $id, null, $type, $name 
     ); 
    } 

    // normal lazy loading 
    else 
    { 
     // this is the changed part 
     $instance = \App::make($class); // new $class; 

     return new MorphTo(
      $instance->newQuery(), $this, $id, $instance->getKeyName(), $type, $name 
     ); 
    } 
} 

Note: Đây hoạt động tốt cho nạp lười biếng, nhưng không làm việc để háo hức. An issue has been raised seeking a solution for eager-loading here.

Mối quan hệ sau đó sẽ như bình thường:

public function linkable() 
{ 
    return $this->morphTo(); 
} 
+0

Bạn là một thiên tài. Cảm ơn rất nhiều vì sự giúp đỡ của bạn. Bạn nói rằng chúng ta không thể bỏ qua null cho tên bởi vì nó sẽ không thể suy ra nó, nhưng [điều này làm tôi nghĩ rằng chúng ta có thể!] (Http://laravel.com/api/source-class- Illuminate.Database.Eloquent.Model.html # 523) – Leng

+0

Mặc dù tôi đang sử dụng Laravel 4.1 có [this morphTo] (https://github.com/laravel/framework/blob/2f1c6cd51dfd51d573977f07e34ba609cc0bf3ac/src/Illuminate/Database/Eloquent/ Model.php # L724). – Leng

+0

Chuột!Quasdunk, khi tôi háo hức tải mối quan hệ này, nó không còn hoạt động bởi vì $ this-> linkable_type là, thực sự, null trong tình huống đó. Tôi cho rằng khi tải mong muốn, Eloquent gọi các phương thức quan hệ trước khi điền vào các thuộc tính/cột. :(Tôi sẽ tiếp tục tìm kiếm giải pháp làm việc – Leng

Các vấn đề liên quan