代码之家  ›  专栏  ›  技术社区  ›  Jesse Orange

拉维尔5.6-使用特征

  •  0
  • Jesse Orange  · 技术社区  · 6 年前

    在我的项目中,我的控制器中有重复的函数,因为每个控制器都需要有相似的功能,但是重复代码会让人觉得有点脏。

    在我的两个 EventController ArticleController 我有一个重复的函数 handleTags() 从字面上讲,这在每个模型中都是一样的。

    /**
    * Handle tagging of this resource
    *
    * First, get the tags field and make sure it isn't empty
    * Convert the string into an array and loop through the array
    * Create new tags if they don't exist
    *
    * @param Request $request: data from the request
    * @param int $id: the ID of the model instance have tags synced to
    */
    public function handleTags(Request $request, $id)
    {
        $event = Event::find($id);
    
        if ($request->has('tags')) {
            $tags = $request->get('tags');
    
            if (!empty($tags)) {
                // Turn a String into an array E.g. one, two
                $tagArray = array_filter(explode(", ", $tags));
    
                // Loop through the tag array that we just created
                foreach ($tagArray as $tag) {
                    Tag::firstOrCreate([
                            'name' => ucfirst(trim($tag)),
                            'slug' => str_slug($tag)
                        ]);
                }
    
                // Grab the IDs for the tags in the array
                $tags = Tag::whereIn('name', $tagArray)->get()->pluck('id');
                $event->tags()->sync($tags);
            } else {
                // If there were no tags, remove them from this model instance
                $event->tags()->sync(array());
            }
        }
    }
    

    是否可以将此功能转换为一个特性?有点像 Taggable ?

    然后你会打电话 在相关的控制器中通过trait,以同样的方式 Searchable search() 方法?

    2 回复  |  直到 6 年前
        1
  •  1
  •   Barry    6 年前

    我想一个更好的解决办法是做一个榜样,我会解释我自己。

    trait HasTags {
    
        public function handleTags($tags) 
        {
            $tags = array_filter(explode(", ", $tags))
    
            $tags = array_map(function () {
                return Tag::firstOrCreate([
                    'name' => ucfirst(trim($tag)),
                    'slug' => str_slug($tag)
                ]);
            }, $tags)
    
            $this->tags()->sync(collect($tags)->pluck('id'))
        }
    
        public function tags()
        {
            return $this->morphMany(Tag::class);
        }
    
    }
    

    模型

    class Event extends Model
    {
        use HasTags;
    }
    

    $event = Event::find($id);
    
    if ($request->has('tags')) {
        $event->handleTags($request->get('tags'));
    }
    

    我写得很快,不需要测试,但这是我的总体想法。 通过对集合使用所有数组操作,可以对事件进行更多重构。

        2
  •  1
  •   Barry    6 年前

    你可以在 app/Http/Traits/TaggableTrait.php

    您只需要传递一个对象而不是id,这样函数就独立于类类型。

    那么你的特点会是这样的:

    namespace App\Http\Traits;
    
    use App\Tag;
    
    trait TaggableTrait
    {
        /**
        * @param Request $request: data from the request
        * @param App\Article | App\Event $object: the model instance have tags synced to
        */
        public function handleTags(Request $request, $object)
        {
            if ($request->has('tags')) {
                $tags = $request->get('tags');
    
                if (!empty($tags)) {
                      // Turn a String into an array E.g. one, two
                      $tagArray = array_filter(explode(", ", $tags));
    
                      // Loop through the tag array that we just created
                      foreach ($tagArray as $tag) {
                          Tag::firstOrCreate([
                             'name' => ucfirst(trim($tag)),
                             'slug' => str_slug($tag)
                          ]);
                      }
    
                      // Grab the IDs for the tags in the array
                      $tags = Tag::whereIn('name', $tagArray)->get()->pluck('id');
                      $object->tags()->sync($tags);
                } else {
                    // If there were no tags, remove them from this model instance
                    $object->tags()->sync(array());
                }
            }
        }
    }
    

    use App\Http\Traits\TaggableTrait;
    
    class EventController extends Controller
    {
        use TaggableTrait;
    
        /*** ***** */
    
        public function update(Request $request, $id)
        {
            /** ***/
    
            $event = Event::findOrFail($id);
            handleTags($request, $event);
    
           /*** *** */
        }       
    }