14. Laravel 4 Eloquent 模型对象关系

一对一

定义一对一关系(hasOne)

class User extends Eloquent {
    public function phone()
    { // 传递给 hasOne 函数的第一个参数是相关模型的名字
        return $this->hasOne('Phone');
    }
}
动态属性调用
$phone = User::find(1)->phone;

这条语句所产生的 SQL 语句如下:

select * from users where id = 1
select * from phones where user_id = 1

注意 Eloquent 假设关系的外键基于模型的名字。在这个例子中假设 Phone 模型使用一个 user_id 外键。

自定义外键
return $this->hasOne('Phone', 'custom_key');

定义逆向关系(belongsTo)

class Phone extends Eloquent {
    public function user()
    {
        return $this->belongsTo('User');
    }
}

在上面的例子中,Eloquent 将在 phones 表中寻找 user_id 字段。如果您想定义一个不同的外键字段,您可以通过 belongsTo 函数的第二个参数传递它:

return $this->belongsTo('User', 'custom_key');

一对多

定义一对多关系(hasMany)

class Post extends Eloquent {
    public function comments()
    {
        return $this->hasMany('Comment');
    }
}
动态属性调用
$comments = Post::find(1)->comments;
动态属性调用,增加约束条件
$comments = Post::find(1)->comments()->where('title', '=', 'foo')->first();
自定义外键
return $this->hasMany('Comment', 'custom_key');

定义逆向关系(belongsTo)

class Comment extends Eloquent {
    public function post()
    {
        return $this->belongsTo('Post');
    }
}

多对多

定义多对多关系(belongsToMany)

class User extends Eloquent {
    public function roles()
    {
        return $this->belongsToMany('Role');
    }
}

注意:需要中间关系表,本例中为 role_user 并且有 user_idrole_id 字段。

自定义外键及关系表
return $this->belongsToMany('Role', 'user_roles', 'user_id', 'foo_id');

定义逆向关系(belongsToMany)

class Role extends Eloquent {
    public function users()
    {
        return $this->belongsToMany('User');
    }
}

多态关系

定义多态关系(morphTo|morphMany)

class Photo extends Eloquent {
    public function imageable()
    {
        return $this->morphTo();
    }
}
class Staff extends Eloquent {
    public function photos()
    {
        return $this->morphMany('Photo', 'imageable');
    }
}
class Order extends Eloquent {
    public function photos()
    {
        return $this->morphMany('Photo', 'imageable');
    }
}

获取多态关系

$staff = Staff::find(1);
foreach ($staff->photos as $photo) { }

获取多态关系的属主

$photo = Photo::find(1);
$imageable = $photo->imageable;

多态关系的数据库结构

staff
    id - integer
    name - string
orders
    id - integer
    price - integer
photos
    id - integer
    path - string
    imageable_id - integer  // 所属模型 ID
    imageable_type - string // 所属模型

查询关系(has)

// 获取至少有1条评论的文章
$posts = Post::has('comments')->get();
// 获取至少有3条评论的文章
$posts = Post::has('comments', '>=', 3)->get();

预加载(with)

foreach (Book::with('author')->get() as $book)
{
    echo $book->author->name;
}

在上面的循环中,只有两个查询被执行:

select * from books
select * from authors where id in (1, 2, 3, 4, 5, ...)

预加载多个关系

$books = Book::with('author', 'publisher')->get();

预加载嵌套关系

$books = Book::with('author.contacts')->get();

指定条件的预加载

$users = User::with(array('posts' => function($query)
{
    $query->where('title', 'like', '%first%');
}))->get();

延迟预加载(load)对已在使用中的模型进行预加载

$books = Book::all();
$books->load('author', 'publisher');

向相关模型插入数据

从父模型向子模型插入数据

// 注意:下面这种实例化时直接赋值的方法,需要开启集体赋值
$comment = new Comment(array('message' => 'A new comment.'));
$post = Post::find(1);
$comment = $post->comments()->save($comment);

在这个例子中,所插入评论的 post_id 字段将自动设置。

为方便理解,上面的第一行相当于:

$comment = new Comment;
$comment->message = 'A new comment.';
// 或者
$comment = with(new Comment)->push(array('message' => 'A new comment.'));

从子模型向父模型插入数据

$comment = new Comment(array('message' => 'A new comment.'));
$post = Post::find(1);
$comment = $comment->post()->associate($post)->save();

向中间表插入数据,多对多关系时的插入方法

增加多对多关系(attach)向中间表增加关系数据(会产生重复数据)

$user = User::find(1);
$user->roles()->attach(1); // 指定 role_id 为1

同时向中间表插入其它字段的值:

$user->roles()->attach(1, array('describe' => '关系描述'));

删除多对多关系(detach)删除中间表指定关系数据

$user->roles()->detach(1);

同步多对多关系(sync)向中间表增加关系数据(不会产生重复数据)

// 只有数组中的 IDs 将会存在关系表中,其它关系将被剔除
$user->roles()->sync(array(1, 2, 3));

同时向中间表插入其它字段的值:

$user->roles()->sync(array(1 => array('describe' => '关系描述')));

中间表自动关联数据(通过关联 save 数据)

$role = new Role(array('name' => 'Editor'));
User::find(1)->roles()->save($role);

同时向中间表插入其它字段的值:

User::find(1)->roles()->save($role, array('describe' => '关系描述'));

触发父模型 updated_at 时间戳(protected $touches)

class Comment extends Eloquent {
    // 子模型中指定更新时需要触发的父模型
    protected $touches = array('post');
    public function post()
    {
        return $this->belongsTo('Post');
    }
}

与中间表交互(pivot)数据透视表对象

在数据子集中访问数据透视对象

$user = User::find(1);
foreach ($user->roles as $role)
{
    echo $role->pivot->created_at;
}

让数据透视对象包含关联外键以外的其它字段

需要在定义多对多关系时完成:

return $this->belongsToMany('Role')->withPivot('foo', 'bar');

让数据透视对象自动维护 created_at 和 updated_at 时间戳

需要在定义多对多关系时完成:

return $this->belongsToMany('Role')->withTimestamps();

你可能感兴趣的:(laravel,eloquent)