iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 29
1
Software Development

從零開始的Laravel RESTful api系列 第 29

Day 29 : category ( modify PostsController )

接下來會為 post 添加 category,首先將 migration 進行 refresh 以便將所有資料清除掉 ( 因為 foreign key 會阻止你刪除單一個 table 的資料 ),除此之外也可以順便產出 categories 的假資料

$ php artisan migrate:refresh --seed

之後先自己手動添加一個 admin user ( 不會的同學參考前面文章 )

  • PostController@store

    首先驗證使用者輸入,其中多了3個 category 的欄位 ( 只有一個是必填的 ),然而必須先建立貼文,然後才會賦予種類。在 Laravel 當中,賦予種類的方式為 attach(),參數可以放一個 id 或多的 id (以 array 的方式)

    public function store(Request $request)
    {
         $auth_user = request()->get('auth_user')->first();
    
            $rules = [
                'title' => 'required|string|min:2|max:500',
                'content' => 'required|string|min:2|max:1500',
                // 添加3個 category 欄位,其中有一個是必填
                'cat1' => 'required|integer',
                'cat2' => 'integer',
                'cat3' => 'integer',
            ];
            $validator = Validator::make($request->all(), $rules);
            if($validator->fails()){
                return response(['message' => $validator->errors()]);
            }
            $data = $request->only(['title', 'content']);
            $data['user_id'] = $auth_user['id'];
    
            $post = Post::create($data);
    
             // 取得所有 category 欄位的值
            $cat = request(['cat1', 'cat2', 'cat3']);
            $categories = Category::find($cat);
    
    
            // 將貼文透過 attach method 賦予種類
            $post->categories()->attach($categories);
    
            // 將貼文以及其種類印出來
            return response(['data' => $post, 'categories' => $post->categories()->get()]);
    
    }
    
    
  • PostsController@update

    使用者輸入的部份多了3個 category 的欄位,然而 category 沒辦法直接用 update method 做更改,在此處會先更改 title 或 content,然後把之前的 category 作 detach() 的動作,之後在重新 attach() 新的值。

    <P.S.> detach() 的參數若都沒有加則表示 detach 所有種類,若有添加參數,則參數的規則與 ttach 相同。

    public function update(Request $request, $id)
    {
        $rules = [
            'title' => 'string|min:2|max:500',
            'content' => 'string|min:2|max:1500',
    
            // 添加3個 category 欄位,其中有一個是必填
            'cat1' => 'required|integer',
            'cat2' => 'integer',
            'cat3' => 'integer',
        ];
    
        $validator = Validator::make($request->all(), $rules);
        if($validator->fails()){
            return response(['message' => $validator->errors()]);
        }
    
        $auth_user = request()->get('auth_user')->first();
        $post = Post::find($id);
    
    
        if(!is_null($post)){
            if($auth_user->can('update', $post)){
                $post->update($request->only(['title', 'content']));
    
                // 先將之前的所有種類 detach()
                $post->categories()->detach();
    
                // 取得所有 category 欄位的值
                $cat = request(['cat1', 'cat2', 'cat3']);
                $categories = Category::find($cat);
    
    
                // 將貼文透過 attach method 賦予種類
                $post->categories()->attach($categories);
    
                // 將貼文以及其種類印出來
                return response(['data' => $post, 'categories' => $post->categories()->get()]);
            }else{
                return response(['message' => 'Unauthorized!!']);
            }
        }else{
            return response(['message' => 'Post not found!']);
        }
    
    }
    
    
    
  • PostsController@destroy

    要成功刪除資料,必須要用 detach() 解除 post 和 category 之間的關聯性,也就是避免因為 foreign 而無法刪除

    public function destroy($id)
    {
        $auth_user = request()->get('auth_user')->first();
        $post = Post::find($id);
        if(!is_null($post)){
            if($auth_user->can('delete', $post)){
    
                // 先將所有種類給 detach()
                $post->categories()->detach();
    
                $post->delete();
                return response(['message' => 'Post deleted!!']);
            }else{
                return response(['message' => 'Unauthorized!!']);
            }
        }else{
            return response(['message' => 'Post not found!']);
        }
    }
    
  • PostsController@index

    印出所有資料時,也將 category 的 name 一併印出

    public function index()
    {
        // return response(['data' => Post::get()]);
        // return response(['data' => Post::with('user')->get()]);
        return response(['data' => Post::with(['user:id,name', 'categories:name'])->get()]);
    }
    
  • PostsController@show

    印出特定資料時,也將 category 的 name 一併印出

    public function show($id)
    {
        $post = Post::with(['user:id,name','categories:name'])->find($id);
        if(!is_null($post)){
            return response(['data' => $post]);
        }
        return response(['message' => 'Post not found']);
    }
    
  • PostsController@userPosts

    印出特定資料時,也將 category 的 name 一併印出

    public function userPosts($user_id)
    {
        $user = User::find($user_id);
        if(!is_null($user)){
            return response(['data' => $user->posts()->with('categories:name')->get()]);
        }
    
        return response(['message' => 'User not found']);
    }
    
    

Postman 測試

  • store

    image alt

  • update

    image alt

  • destroy

    image alt

  • index

    image alt

  • show

    image alt

  • userPosts

    image alt

即將邁入最後一篇。

參考資料:

  1. Attaching / Detaching : https://laravel.com/docs/6.x/eloquent-relationships#updating-many-to-many-relationships

上一篇
Day 28 : database seeding
下一篇
Day 30 : category ( api routes & controller -- index & categoryPosts )
系列文
從零開始的Laravel RESTful api30

尚未有邦友留言

立即登入留言