我在使用Laravel 5.5. 我写了一个包装器, 它把一个Eloquent模型包装成了一个 Entity
类,并且每个模型都有自己的包装器。假设,User有很多产品,一个Product属于一个用户。在包装时,我需要得到一个用户的产品,并将其传递给产品包装器,将其包装到产品实体中。在产品包装器中,我需要得到这个产品的用户所有者,将其包装成用户实体。所以,在用户包装器中,我又需要用户产品!,这就形成了一个无限循环。
EntityWrapper:
abstract class EntityWrapper
{
protected $collection;
protected $entityClass;
public $entity;
public function __construct($collection)
{
$this->collection = $collection;
$this->entity = $this->buildEntity();
}
protected function buildEntity()
{
$tempEntity = new $this->entityClass;
$Entities = collect([]);
foreach ($this->collection as $model) {
$Entities->push($this->makeEntity($tempEntity, $model));
}
return $Entities;
}
abstract protected function makeEntity($entity, $model);
}
UserEntityWrapper:
class UserEntityWrapper extends EntityWrapper
{
protected $entityClass = UserEntity::class;
protected function makeEntity($userEntity, $model)
{
$userEntity->setId($model->user_id);
$userEntity->setName($model->name);
// set other properties of user entity...
//--------------- relations -----------------
$userEntity->setProducts((new ProductEntityWrapper($model->products))->entity);
return $userEntity;
}
}
ProductEntityWrapper:
class ProductEntityWrapper extends EntityWrapper
{
protected $entityClass = ProductEntity::class;
protected function makeEntity($productEntity, $model)
{
$productEntity->setId($model->product_id);
$productEntity->setName($model->name);
// set other properties of product entity...
//--------------- relations -----------------
$productEntity->setUser((new UserEntityWrapper($model->user))->entity);
return $productEntity;
}
}
UserEntity: UserEntityWrapper: ProductEntityWrapper: UserEntity:
class UserEntity
{
private $id;
private $name;
private $products;
//... other properties
public function setProducts($products)
{
$this->products = $products;
}
// other getters and setters...
}
当我想通过调用用户实体来获得用户实体时 (new UserEntityWrapper(User::all()))->entity
,会造成无限循环。那么,如何才能防止模型之间的嵌套调用关系呢?感谢任何建议。
终于,我找到了解决方案。由于在每个封装类中,我使用动态属性来获取关系集合,除了施加额外的查询外,还会造成懒加载。所以,在把模型集合传递给每个包装器之前,先检索出必要的关系模型,每个包装器首先用方法检查关系是否存在 getRelations()
(它返回一个可用关系的数组)。如果预期的关系是可用的,关系模型的集合将被传递到适当的包装器类中。
UserEntityWrapper。
class UserEntityWrapper extends EntityWrapper
{
protected $entityClass = UserEntity::class;
protected function makeEntity($userEntity, $model)
{
$userEntity->setId($model->user_id);
$userEntity->setName($model->name);
// set other properties of user entity...
//--------------- relations -----------------
$relations = $model->getRelations();
$products = $relations['products'] ?? null;
if ($products) {
$userEntity->setProducts((new ProductEntityWrapper($products))->entity);
}
return $userEntity;
}
}
而且,类似的功能也用于其他包装器。