首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通过雄辩的关系转换为继承的类

通过雄辩的关系转换为继承的类
EN

Stack Overflow用户
提问于 2019-03-27 23:54:01
回答 2查看 99关注 0票数 1

我想我会问这个问题,因为Laravel是我遇到的最优雅的框架,我想知道是否有“更好的方式”来做到这一点。

我有一个记录账本的系统,这样:

代码语言:javascript
复制
class Chapter extends Model
{
    public function book()
    {
        return $this->belongsTo('\App\Book');
    }
}

在系统中,有许多其他模型是从"Book“扩展而来的,如”小说“、”传记“等。有没有办法让Eloquent在给定正确信息的情况下为我提供正确转换的对象(即命名空间类)?目前,我正在使用https://gist.github.com/borzilleri/960035中的函数获取这本书并对其进行造型,该函数可以工作,但感觉不是很“整洁”。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-03-28 21:29:05

这应该归功于Joshua Dwire,因为他让我走上了这个解决方案的道路。我对他提到的扩展标准BelongsTo类并让它为我工作很感兴趣。理想情况下,我希望能够调用自定义关系:

代码语言:javascript
复制
$this->belongsToBook('\App\Book');

并使该函数返回一个正确转换的对象。

在浏览代码时,我发现负责返回关系的是Model使用的特征HasRelationship。通过改变这种关系,我们可以改变实现,从而改变返回的对象。

我还想复制Laravel使用的相同方法,以便在我自己的应用程序中模仿它。

考虑到所有这些,第一步是创建一个新的特征HasBookRelationship,可以在模型中使用它来处理对$this->belongsToBook('\App\Book')的调用

代码语言:javascript
复制
trait HasBookRelationship
{
    public function belongsToBook($related, $foreignKey = null, $ownerKey = null, $relation = null)
    {
        if (is_null($relation)) {
            $relation = $this->guessBelongsToRelation();
        }
        $instance = $this->newRelatedInstance($related);

        if (is_null($foreignKey)) {
            $foreignKey = \Str::snake($relation).'_'.$instance->getKeyName();
        }

        $ownerKey = $ownerKey ?: $instance->getKeyName();

        //We change the return relationship here
        **return new BelongsToBook(
            $instance->newQuery(), $this, $foreignKey, $ownerKey, $relation
        );**
    }
}

这只是从HasRelationships特征中现有的belongsTo方法复制而来。这里的关键是我们将返回一个自定义关系BelongsToBook,并使用它覆盖返回的内容。方法的最后一行被更改为返回我们想要的关系类。

我们使用的类是从BelongsTo扩展而来的,但我们更改了get方法,以便在返回对象之前对其进行强制转换。

代码语言:javascript
复制
class BelongsToBook extends BelongsTo
{
    public function __construct(Builder $query, Model $child, $foreignKey, $ownerKey, $relationName)
    {
        parent::__construct($query, $child, $foreignKey, $ownerKey, $relationName);
    }

    public function get($columns = ['*'])
    {
        $objs = $this->query->get($columns);

        //iterate over the collated objects...
        $objs->transform(function($item)
        {
            //..and return a cast object with whatever method you want
            return castTheCorrectObject($item);
        });

        return $objs;
    }
}

castTheCorrectObject可以是您喜欢的任何类型转换函数,可以设置为关系中的帮助器或另一个方法。

一旦这些都设置好了,我们就可以在我们自己的模型中使用它:

代码语言:javascript
复制
class Author extends Model
{
    use HasBookRelationship;

    public function books()
    {
        return $this->belongsToBook('\App\Book');
    }
}

这将返回正确转换的对象的集合,并维护关系。

不过,有一件事确实让我困惑不已。我在BelongsToBook类中覆盖的方法是get(),而不是Joshua建议的getResults()get()是在Relation中定义的,并由BelongsTo继承,而as getResults()是在BelongsTo中定义的。我不确定getResults()get()之间的区别是什么,也不知道为什么我必须覆盖get()而不是getResults()。如果有人能提供任何线索,我将不胜感激。

票数 1
EN

Stack Overflow用户

发布于 2019-03-28 00:17:03

我可以在这里看到一些不同的选项。一种是像这样编写你的类:

代码语言:javascript
复制
class Chapter extends Model
{
    public function book()
    {
        return $this->belongsTo('\App\Book');
    }

    public function biography()
    {
        return $this->belongsTo('\App\Biography')->where('type', 'biography');
    }

    public function novel()
    {
        return $this->belongsTo('\App\Novel')->where('type', 'novel');
    }
}

然后你需要提前知道它是哪种类型的书。另一种方法是这样做:

代码语言:javascript
复制
class Chapter extends Model
{
    protected function parent_book()
    {
        return $this->belongsTo('\App\Book');
    }

    public function getBookAttribute()
    {
        $book = $this->parent_book;
        if (!$book) return $book; // No related book.

        if ($book->type == 'novel') return (Novel)$book;
        if ($book->type == 'biography') return (Biography)$book;

        return $book;
    }
}

你仍然需要自己做所有的转换,但至少所有的转换都在一个地方,并且对应用程序的其余部分是透明的,因为它仍然可以在第二个解决方案中引用$chapter->book,如果你设置了$chapter->book = new Book(),你还需要确保创建一个setBookAttribute()函数。

一种更复杂的可能性是创建您自己的自定义关系类型,方法是扩展BelongsTo类,并在返回结果之前将getResults()覆盖到转换。从外部看,这是非常透明的,并且允许您仍然调用$章节->book()并将其视为一种关系。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55381463

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档