2015-03-08 19 views
7

Tôi có bảng tổng hợp kết nối người dùng với không gian làm việc. Trên bảng tổng hợp, tôi cũng có một cột cho vai trò, xác định vai trò người dùng cho không gian làm việc đó. Tôi có thể cung cấp các phương thức Mutator (Setter) của Accessor (Getter) & đối với vai trò bên trong bảng tổng hợp không? Tôi đã cố gắng để xem xét tất cả, nhưng chi tiết về các bảng trụ trong hùng hồn là khá thưa thớt.Trình truy cập (Getter) & Bộ đột biến (Setter) Trên Bảng tổng hợp trong Laravel

Tôi không chắc liệu mình có phải thiết lập mô hình trục tùy chỉnh không? Nếu tôi làm như vậy, một ví dụ sẽ tuyệt vời vì tài liệu về mô hình trục là rất cơ bản.

Cảm ơn.

+0

tôi đang cố gắng để làm điều đó bằng tay. Dưới đây là những gì tôi có: http://laravel.io/bin/RE2ze – ATLChris

Trả lời

7

Nếu tất cả các bạn cần làm là truy cập bổ sung lĩnh vực trên pivot table, bạn chỉ cần sử dụng phương pháp withPivot() vào định nghĩa mối quan hệ:

class User extends Model { 
    public function workspaces() { 
     return $this->belongsToMany('App\Models\Workspace')->withPivot('role'); 
    } 
} 

class Workspace extends Model { 
    public function users() { 
     return $this->belongsToMany('App\Models\User')->withPivot('role'); 
    } 
} 

Bây giờ lĩnh vực vai trò của bạn sẽ có mặt trên các bảng pivot :

$user = User::first(); 

// get data 
foreach($user->workspaces as $workspace) { 
    var_dump($workspace->pivot->role); 
} 

// set data 
$workspaceId = $user->workspaces->first()->id; 
$user->workspaces()->updateExistingPivot($workspaceId, ['role' => 'new role value']); 

Nếu bạn thực sự cần phải tạo accessors/mutators cho bảng pivot của bạn, bạn sẽ cần phải tạo một lớp tùy chỉnh bảng tổng hợp. Tôi đã không làm điều này trước đây, vì vậy tôi không biết nếu điều này thực sự sẽ làm việc, nhưng có vẻ như bạn sẽ làm điều này:

Tạo một lớp trục mới chứa trình truy cập/bộ biến đổi của bạn. Lớp này sẽ mở rộng lớp Pivot mặc định. Lớp mới này là lớp sẽ được khởi tạo khi User hoặc Workspace tạo một cá thể mô hình Pivot.

namespace App\Models; 
use Illuminate\Database\Eloquent\Relations\Pivot; 
class UserWorkspacePivot extends Pivot { 
    getRoleAttribute() { 
     ... 
    } 
    setRoleAttribute() { 
     ... 
    } 
} 

Bây giờ, hãy cập nhật mô hình Người dùng và không gian làm việc của bạn để tạo lớp bảng tổng hợp mới này thay vì lớp bảng mặc định. Điều này được thực hiện bằng cách ghi đè phương thức newPivot() do lớp Mô hình cung cấp. Bạn muốn ghi đè phương thức này để tạo một cá thể của lớp UserWorkspacePivot mới của bạn, thay vì lớp Pivot mặc định.

class User extends Model { 
    // normal many-to-many relationship to workspaces 
    public function workspaces() { 
     // don't forget to add in additional fields using withPivot() 
     return $this->belongsToMany('App\Models\Workspace')->withPivot('role'); 
    } 

    // method override to instantiate custom pivot class 
    public function newPivot(Model $parent, array $attributes, $table, $exists) { 
     return new UserWorkspacePivot($parent, $attributes, $table, $exists); 
    } 
} 

class Workspace extends Model { 
    // normal many-to-many relationship to users 
    public function users() { 
     // don't forget to add in additional fields using withPivot() 
     return $this->belongsToMany('App\Models\User')->withPivot('role'); 
    } 

    // method override to instantiate custom pivot class 
    public function newPivot(Model $parent, array $attributes, $table, $exists) { 
     return new UserWorkspacePivot($parent, $attributes, $table, $exists); 
    } 
} 
+0

Tôi rất đánh giá cao phản hồi chi tiết của bạn, nhưng không may, điều này không hoạt động. 'GetRoleAttribute' và 'setRoleAttribute' không bao giờ được áp dụng. – ATLChris

+0

@ATLChris Tôi vừa thử đây là môi trường thử nghiệm và có vẻ như nó đang hoạt động. Bạn có thể đăng mã hiện tại của bạn, cũng như những gì bạn đang cố gắng làm, những gì bạn đang mong đợi xảy ra, những gì đang thực sự xảy ra, và bất kỳ lỗi nào bạn đang nhận được? – patricus

+1

@ATLChris giải pháp này đang hoạt động. Tôi đã giải quyết vấn đề này bằng cách sử dụng phương pháp này. Để biết thêm chi tiết, bạn có thể đọc bài viết [Laravel - Mô hình trục tùy chỉnh trong Eloquent] (http://softonsofa.com/laravel-custom-pivot-model-in-eloquent/) – hhsadiq

0

Đây là một câu hỏi khó. Các giải pháp tôi có thể nghĩ là có mùi và có thể gây ra một số vấn đề sau này.

Tôi sẽ mở rộng câu trả lời của Patricus để làm cho nó hoạt động.

Tôi sẽ bình luận về câu trả lời của Patricus nhưng đơn giản là quá nhiều để giải thích. Để làm cho giải pháp của mình hoạt động với attachsync, chúng ta phải làm một số điều xấu xí.

Vấn đề

Đầu tiên chúng ta hãy xác định các vấn đề với giải pháp của mình. Getters và setters của anh ta làm việc nhưng mối quan hệ của dependToMany không sử dụng mô hình Pivot khi chạy sync, attach hoặc detach. Điều này có nghĩa là mỗi khi chúng ta gọi một trong số này với tham số $attributes thì dữ liệu không biến đổi sẽ được đưa vào cột cơ sở dữ liệu.

// This will skip the mutator on our extended Pivot class 
$user->workspaces()->attach($workspace, ['role' => 'new role value']); 

Chúng tôi thể hãy cố gắng nhớ rằng mỗi khi chúng ta gọi là một trong những chúng ta không thể sử dụng tham số thứ hai để đính kèm các dữ liệu biến đổi và chỉ cần gọi updateExistingPivot với các dữ liệu đó phải được biến đổi.Vì vậy, một attach sẽ là những gì Patricus nói:

$user->workspaces()->attach($workspace); 
$user->workspaces()->updateExistingPivot($workspaceId, ['role' => 'new role value']); 

và chúng tôi không bao giờ có thể sử dụng một cách chính xác đi qua các trục thuộc tính giống như attach phương pháp tham số thứ hai thể hiện trong ví dụ đầu tiên. Điều này sẽ dẫn đến nhiều câu lệnh cơ sở dữ liệu và thối mã vì bạn luôn phải nhớ không làm theo cách thông thường. Bạn có thể gặp phải các vấn đề nghiêm trọng sau này nếu bạn giả sử mọi nhà phát triển, hoặc thậm chí là chính mình, sẽ chỉ biết không sử dụng phương thức attach với tham số thứ hai như dự định.

Giải pháp (chưa được kiểm tra và không hoàn hảo)

Để có thể gọi attach với mutator trên các cột trục bạn phải làm một số kéo dài điên. Tôi chưa thử nghiệm điều này nhưng nó có thể giúp bạn đi đúng hướng nếu bạn muốn thử. Đầu tiên chúng ta phải tạo lớp mối quan hệ của chúng ta kéo dài BelongsToMany và thực hiện attach phương pháp tùy chỉnh của chúng tôi:

use Illuminate\Database\Eloquent\Relations\BelongsToMany; 

class UserWorkspaceBelongsToMany extends BelongsToMany { 
    public function attach($id, array $attributes = [], $touch = true) 
    { 
     $role = $attributes['role']; 
     unset($attributes['role']); 
     parent::attach($id, $attributes, $touch); 
     $this->updateExistingPivot($id, ['role' => $role], $touch); 
    } 
    // You will need sync here too 
} 

Bây giờ chúng ta phải làm cho mỗi Model::belongsToMany sử dụng lớp mới UserWorkspaceBelongsToMany của chúng tôi thay vì bình thường BelongsToMany. Chúng tôi làm điều này bằng cách chế giễu belongsToMany trong chúng ta sử dụng và Workspace lớp:

// put this in the User and Workspace Class 
public function userWorkspaceBelongsToMany($related, $table = null, $foreignKey = null, $otherKey = null, $relation = null) 
{ 
    if (is_null($relation)) { 
     $relation = $this->getBelongsToManyCaller(); 
    } 

    $foreignKey = $foreignKey ?: $this->getForeignKey(); 

    $instance = new $related; 

    $otherKey = $otherKey ?: $instance->getForeignKey(); 

    if (is_null($table)) { 
     $table = $this->joiningTable($related); 
    } 

    $query = $instance->newQuery(); 

    return new UserWorkspaceBelongsToMany($query, $this, $table, $foreignKey, $otherKey, $relation); 
} 

Như bạn thấy, chúng tôi vẫn gọi cơ sở dữ liệu hơn nhưng chúng tôi không phải lo lắng về một người nào đó gọi attach với các thuộc tính trục và chúng không bị đột biến.

Bây giờ sử dụng trong mô hình của bạn thay vì belongsToMany bình thường:

class User extends Model { 
    public function workspaces() { 
     return $this->userWorkspaceBelongsToMany('App\Models\Workspace')->withPivot('role'); 
    } 
} 

class Workspace extends Model { 
    public function users() { 
     return $this->userWorkspaceBelongsToMany('App\Models\User')->withPivot('role'); 
    } 
} 
+0

Bạn đang thực sự mã hóa cứng trên lớp 'UserWorkspaceBelongsToMany'. – lcjury

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