Skip to content

devweyes/swoft-db-orm

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 

Repository files navigation

ORM 模型关联

数据库表通常相互关联。例如,一篇博客文章可能有很多评论,或者一个订单对应一个下单用户。 ORM 让这些关联的管理和使用变得简单,并支持多种类型的关联

1.1 composer

composer require devweyes/db-orm

1.2 实体需继承 Model

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');
}]);