数据库表通常相互关联。例如,一篇博客文章可能有很多评论,或者一个订单对应一个下单用户。 ORM 让这些关联的管理和使用变得简单,并支持多种类型的关联
composer require devweyes/db-orm
class Model extends \Jcsp\Orm\Eloquent\Model
一般只需定义两个注解,及Getter Setter。 @RelationPassive() 为切面注解,如需预加载,必不可缺。
字段 | 是否必填 | 描述 |
---|---|---|
entity | 是 | 目标实体 |
foreign | 是 | 目标关联字段(xxx_id获取 xxx表示本实体转蛇形) |
owner | 否 | 本字段(keyName主键获取) |
<?php declare(strict_types=1);
namespace App\Model\Entity;
use Swoft\Orm\Annotation\Mapping\HasOne;
use Swoft\Orm\Annotation\Mapping\RelationPassive;
use Swoft\Db\Eloquent\Model;
/**
*
* Class Api
*
* @since 2.0
*
* @Entity(table="users")
*/
class User extends Model
{
/**
* @HasOne(
* entity=Role::class,
* foreign="id",
* owner="user_id"
* )
* @var mixed
*/
private $roles;
/**
* @param $roles
*/
public function setRoles($roles)
{
$this->roles = $roles;
}
/**
* 获取一个角色
* @RelationPassive()
* @return mixed
*/
public function getRoles()
{
return $this->roles;
}
}
字段 | 是否必填 | 描述 |
---|---|---|
entity | 是 | 目标实体 |
foreign | 是 | 目标关联字段(xxx_id获取 xxx表示本实体转蛇形) |
owner | 否 | 本字段(keyName主键获取) |
<?php declare(strict_types=1);
namespace App\Model\Entity;
use Swoft\Orm\Annotation\Mapping\HasMany;
use Swoft\Orm\Annotation\Mapping\RelationPassive;
use Swoft\Db\Eloquent\Model;
/**
*
* Class Api
*
* @since 2.0
*
* @Entity(table="users")
*/
class User extends Model
{
/**
* @HasMany(
* entity=Role::class,
* foreign="id",
* owner="user_id"
* )
* @var mixed
*/
private $roles;
/**
* @param $roles
*/
public function setRoles($roles)
{
$this->roles = $roles;
}
/**
* 获取专属的多个角色
* @RelationPassive()
* @return mixed
*/
public function getRoles()
{
return $this->roles;
}
}
字段 | 是否必填 | 描述 |
---|---|---|
entity | 是 | 目标实体 |
owner | 否 | 本表字段(xxx_id获取 xxx表示关系名,id表示目标主键) |
foreign | 是 | 目标表字段(keyName主键获取) |
<?php declare(strict_types=1);
namespace App\Model\Entity;
use Swoft\Orm\Annotation\Mapping\BelongsTo;
use Swoft\Orm\Annotation\Mapping\RelationPassive;
use Swoft\Db\Eloquent\Model;
/**
*
* Class Api
*
* @since 2.0
*
* @Entity(table="roles")
*/
class Role extends Model
{
/**
* @BelongsTo(
* entity=User::class,
* foreign="user_id",
* owner="id"
* )
* @var mixed
*/
private $users;
/**
* @param $roles
*/
public function setUsers($users)
{
$this->users = $users;
}
/**
* 获取角色的账号
* @RelationPassive()
* @return mixed
*/
public function getUsers()
{
return $this->users;
}
}
字段 | 是否必填 | 描述 |
---|---|---|
entity | 是 | 目标实体 |
pointEntity | 是 | 中间实体 |
foreignPivot | 是 | 中间实体关联本字段的字段(xxx_id获取) |
ownerPivot | 否 | 中间实体关联目标字段的字段(xxx_id获取) |
foreign | 否 | 目标关联字段(id获取) |
owner | 否 | 本字段(id获取) |
<?php declare(strict_types=1);
namespace App\Model\Entity;
use Swoft\Orm\Annotation\Mapping\BelongsToMany;
use Swoft\Orm\Annotation\Mapping\RelationPassive;
/**
*
* Class Api
*
* @since 2.0
*
* @Entity(table="users")
*/
class User extends Model
{
/**
* @BelongsToMany(
* entity=Role::class,
* pointEntity=UserRole::class,
* foreignPivot="api_id",
* ownerPivot="cat_id",
* foreign="id",
* owner="id"
* )
* @var mixed
*/
private $roles;
/**
* @param $cats
*/
public function setRoles($roles)
{
$this->roles = $roles;
}
/**
* 获取多个角色
* @RelationPassive()
* @return mixed
*/
public function getRoles()
{
return $this->roles;
}
}
当通过模型获取数据时,你可能希望限制在一个已存在的关系上。比如说,你想要获取至少包含一条评论的博客文章。你就应该这样做,使用针对关联关系的 has and orHas 方法:
// 获取至少有一条评论的文章
$posts = App\Post::has('comments')->get();
// 获取至少有3
$posts = App\Post::has('comments', '>=', 3)->get();
// 获取至少有一条评论的文章,并加载评论的投票信息
$posts = App\Post::has('comments.votes')->get();
如果你想要做更多特性,你还可以使用 whereHas 和 orWhereHas 方法,在方法中,你可以指定 「where」 条件在你的 has 语句之中。这些方法允许你在关联查询之中添加自定义的条件约束,比如检查评论的内容:
// 获取所有至少有一条评论的文章且评论内容以 foo 开头
$posts = App\Post::whereHas('comments', function ($query) {
$query->where('content', 'like', 'foo%');
})->get();
//获取书作者
$books = App\Book::with('author')->get();
foreach ($books as $book) {
echo $book->getAuthor()->getName;
}
//或书的作者及作者联系人
$books = App\Book::with('author.contacts')->get();
foreach ($books as $book) {
echo $book->getAuthor()->getContacts()->getName;
}
//获取书及作者 并且作者为tom,只需要作者的id name信息,且按照作者id排序
$users = App\Book::with(['author' => function ($query) {
$query->where('name', '=', '%tom%')
->select('id','name')
->orderBy('id');
}])->get();
有可能你还希望在模型加载完成后在进行预加载。举例来说,如果你想要动态的加载关联数据,那么 load 方法对你来说会非常有用:
$books = App\Book::all();
if ($someCondition) {
$books->load('author', 'publisher');
}
$books->load(['author' => function ($query) {
$query->orderBy('published_date', 'asc');
}]);