Laravel,雄辩,从变形关系中获取相关项(建议)

时间:2019-07-29 23:11:42

标签: laravel eloquent

问题的标题可能看起来很奇怪,但我将简要解释一下。我还没有遇到任何问题,但是正在考虑有关以下方法的任何建议。

我有下表:

articles
    hasMany(tags)

movies 
    hasMany(tags)

series 
    hasMany(tags)

subs (morph)
    media_id 
    media_type
    user_id

前三个表都具有many标记,其中subs表之间具有Morph关系。

这个概念很简单,用户可以订阅movies和/或series而不能订阅articles,也就是说,选择接受movies中的记录。

将插入以下记录:

media_id => 1, media_type => movie, user_id => 1

假设我们在subs表中有1万条这样的记录。现在,我在articles中创建带有特定标签的记录。我想通知subs中所有已选择movies和/或series的用户,这些用户的标签与我从articles定位的记录完全相同

TL; DR:通知对电影或电视剧中的特定标签感兴趣的用户。

为此,我在morphTo模型中添加了subs

public function media(){
      return $this->morphTo();
}

逻辑很简单:

  1. 获取文章。
  2. 获取tags()关系并将其保存到变量中。
  3. 检查标签是否为空,如果不是,请继续
  4. 获取所有subs
  5. 获取morphTo关系并获取其标签。
  6. 比较并继续。

        $article = MediaArticle::find($notificationable_id);
        $article_tags = $article->tags;
        $subbed_users = array();
        if (empty($article_tags) === false) {
            $subs = NotificationMediaSub::all();
            foreach ($subs as $sub) {
                $sub_tags = $sub->media->tags;
                foreach ($sub_tags as $sub_tag) {
                    foreach ($article_tags as $article_tag_title) {
                        if (strcasecmp($sub_tag->title, $article_tag_title->title) === 0) {
                            array_push($subbed_users, $sub->user_id);
                        }
                    }
                }
            }
    
            // continue here
        }
    

我发现这种方法确实很费力,并且可能导致服务器速度大大降低。有没有更好的方法可以实现我的目标?

=======================

  1. 方法

我在其中将media_tags_relationship定义为模型:

public function media() {
        if ($this->taggable_type === AdminHelper::MORPH_MEDIA_TRANSLATION_MOVIE['original']) {
            return $this->belongsTo(MediaMovie::class, 'taggable_id', 'id');
        } elseif ($this->taggable_type === AdminHelper::MORPH_MEDIA_TRANSLATION_SERIES['original']) {
            return $this->belongsTo(MediaSeries::class, 'taggable_id', 'id');
        }
        return $this->belongsTo(MediaMovie::class, 'taggable_id', 'id')->where('id', 0);
    }

现在,我正在像这样获取潜艇:

$article = MediaArticle::find($notificationable_id);
        $article_tags = $article->tags;
        $subbed_users_tokens = array();
        if (empty($article_tags) === false) {
            $article_tags = $article_tags->map(function ($tag) {
                return  $tag->title;
            });

            $related_tags = MediaTag::whereIn("title", $article_tags)->get();
            $related_tags = $related_tags->map(function ($tag) {
                return  $tag->id;
            });

            $tags_relationship = MediaTagsRelationship::whereIn("tag_id", $related_tags)->where("taggable_type", "movie")->orWhere("taggable_type", "series")->get();
            foreach ($tags_relationship as $tag_relationship) {
                $media = $tag_relationship->media()->with('subs')->get();
                if (empty($media) === false) {
                  $media = $media[0];
                  $subs = $media->subs->map(function ($sub) {
                      return  $sub->firebase_token;
                  });
                  array_push($subbed_users_tokens, $subs);
                }
            }
        }

0 个答案:

没有答案