259 lines
6.5 KiB
PHP
259 lines
6.5 KiB
PHP
<?php
|
|
|
|
namespace app\common\app\common\arw\adjfut\src\Model;
|
|
use think\model\Collection;
|
|
use app\common\arw\adjfut\src\Exception\ErrorMsg;
|
|
|
|
/**
|
|
* 中间表关联
|
|
*
|
|
* @date 2022-12-29
|
|
* @example
|
|
* @author arw
|
|
* @since 1.0.0
|
|
*/
|
|
class Pivot
|
|
{
|
|
/**
|
|
* 中间表
|
|
*
|
|
* @var string
|
|
*/
|
|
private $pivotClass = '';
|
|
/**
|
|
* 主表
|
|
*
|
|
* @var string
|
|
*/
|
|
private $masterClass = '';
|
|
/**
|
|
* 子表
|
|
*
|
|
* @var string
|
|
*/
|
|
private $subClass = '';
|
|
/**
|
|
* 中间表主键
|
|
*
|
|
* @var string
|
|
*/
|
|
private $pivotPk = '';
|
|
/**
|
|
* 主表主键
|
|
*
|
|
* @var string
|
|
*/
|
|
private $masterPk = '';
|
|
/**
|
|
* 子表主键
|
|
*
|
|
* @var string
|
|
*/
|
|
private $subPk = '';
|
|
/**
|
|
* 是否软删除
|
|
*
|
|
* @var boolean
|
|
*/
|
|
private $softDelete = false;
|
|
/**
|
|
* 初始化
|
|
*
|
|
* @param string $pivotClass 中间表
|
|
* @param string $masterClass 主表
|
|
* @param string $subClass 子表
|
|
* @date 2022-12-29
|
|
* @example
|
|
* @author arw
|
|
* @since 1.0.0
|
|
*/
|
|
public function __construct(
|
|
string $pivotClass,
|
|
string $masterClass,
|
|
string $subClass,
|
|
bool $softDelete = false
|
|
) {
|
|
$this->pivotClass = $pivotClass;
|
|
$this->masterClass = $masterClass;
|
|
$this->subClass = $subClass;
|
|
$this->softDelete = $softDelete;
|
|
|
|
$this->pivotPk = (new $pivotClass)->getPk();
|
|
$this->masterPk = (new $masterClass)->getPk();
|
|
$this->subPk = (new $subClass)->getPk();
|
|
}
|
|
|
|
/**
|
|
* 绑定
|
|
*
|
|
* @param array|Collection $masters
|
|
* @param array|Collection $subs
|
|
* @param array $extra 中间表额外数据
|
|
* @return void
|
|
* @date 2022-12-29
|
|
* @example
|
|
* @author arw
|
|
* @since 1.0.0
|
|
*/
|
|
public function bind($masters, $subs, array $extra = []): void
|
|
{
|
|
$this->_bind($masters, $subs, $extra, false);
|
|
}
|
|
|
|
/**
|
|
* 解绑
|
|
*
|
|
* @param array|Collection $masters
|
|
* @param array|Collection $subs
|
|
* @return void
|
|
* @date 2022-12-29
|
|
* @example
|
|
* @author arw
|
|
* @since 1.0.0
|
|
*/
|
|
public function unbind(array $masters, array $subs): void
|
|
{
|
|
$masters = self::formatModel($masters, $this->masterClass);
|
|
$subs = self::formatModel($subs, $this->subClass);
|
|
|
|
$pivotClass = $this->pivotClass;
|
|
|
|
$pivotPk = $this->pivotPk;
|
|
$masterPk = $this->masterPk;
|
|
$subPk = $this->subPk;
|
|
|
|
foreach ($masters as $master) {
|
|
// 查询已绑定的数据
|
|
$subPks = $pivotClass::where([
|
|
$masterPk => $master->$masterPk
|
|
])->column($subPk);
|
|
foreach ($subs as $sub) {
|
|
if (in_array($sub->$subPk, $subPks)) {
|
|
$pivotClass::where([
|
|
$subPk => $sub->$subPk,
|
|
$masterPk => $master->$masterPk
|
|
])->field([
|
|
$pivotPk
|
|
])->select()->delete();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 重新绑定
|
|
*
|
|
* @param array|Collection $masters
|
|
* @param array|Collection $subs
|
|
* @param array $extra 中间表额外数据
|
|
* @return void
|
|
* @date 2022-12-29
|
|
* @example
|
|
* @author arw
|
|
* @since 1.0.0
|
|
*/
|
|
public function rebind($masters, $subs, array $extra = []): void
|
|
{
|
|
$this->_bind($masters, $subs, $extra, true);
|
|
}
|
|
|
|
/**
|
|
* 格式化模型
|
|
*
|
|
* @param array|Collection $models
|
|
* @param string $class
|
|
* @return Collection
|
|
* @date 2022-12-29
|
|
* @example
|
|
* @author arw
|
|
* @since 1.0.0
|
|
*/
|
|
private static function formatModel($models, string $class): Collection
|
|
{
|
|
if ($models instanceof Collection) {
|
|
return $models;
|
|
} else if (is_array($models)) {
|
|
$Collection = new Collection();
|
|
foreach ($models as $model) {
|
|
if ($model instanceof $class) {
|
|
} else if (is_string($model) || is_numeric($model)) {
|
|
$model = $class::find($model);
|
|
}
|
|
$Collection->push($model);
|
|
}
|
|
return $Collection;
|
|
} else {
|
|
throw new ErrorMsg("类型异常", 1);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 绑定数据
|
|
*
|
|
* @param array|Collection $masters
|
|
* @param array|Collection $subs
|
|
* @param array $extra
|
|
* @param boolean $rebind
|
|
* @return void
|
|
* @date 2022-12-29
|
|
* @example
|
|
* @author arw
|
|
* @since 1.0.0
|
|
*/
|
|
private function _bind($masters, $subs, array $extra = [], bool $rebind = false)
|
|
{
|
|
$masters = self::formatModel($masters, $this->masterClass);
|
|
$subs = self::formatModel($subs, $this->subClass);
|
|
|
|
$pivotClass = $this->pivotClass;
|
|
|
|
$softDelete = $this->softDelete;
|
|
|
|
$pivotPk = $this->pivotPk;
|
|
$masterPk = $this->masterPk;
|
|
$subPk = $this->subPk;
|
|
|
|
foreach ($masters as $master) {
|
|
if ($rebind) {
|
|
$pivots = $pivotClass::where([
|
|
[$masterPk, '=', $master->$masterPk],
|
|
[$subPk, 'not in', $subs->column($subPk)],
|
|
])->select();
|
|
if (!$pivots->isEmpty()) {
|
|
// 重新绑定
|
|
$this->unbind([$master], $pivots->column($subPk));
|
|
}
|
|
}
|
|
foreach ($subs as $sub) {
|
|
$pivot = null;
|
|
if ($softDelete) {
|
|
$pivot = $pivotClass::withTrashed()->where([
|
|
$subPk => $sub->$subPk,
|
|
$masterPk => $master->$masterPk
|
|
])->find();
|
|
} else {
|
|
$pivot = $pivotClass::where([
|
|
$subPk => $sub->$subPk,
|
|
$masterPk => $master->$masterPk
|
|
])->find();
|
|
}
|
|
if (is_null($pivot) || $pivot->isEmpty()) {
|
|
$pivotClass::create($extra + [
|
|
$subPk => $sub->$subPk,
|
|
$masterPk => $master->$masterPk
|
|
]);
|
|
} else {
|
|
if ($softDelete) {
|
|
$pivot->restore();
|
|
}
|
|
if ($extra) {
|
|
$pivotClass::update($extra, [
|
|
$pivotPk => $pivot->$pivotPk
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|