Đâ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 attach
và sync
, 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');
}
}
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