ساخت یک اپلیکیشن با لاراول و AngularJS – قسمت سوم
ﺯﻣﺎﻥ ﻣﻄﺎﻟﻌﻪ: 8 دقیقه

ساخت یک اپلیکیشن با لاراول و AngularJS – قسمت سوم

در ادامه ی قسمت‌های قبل این سری آموزش‌ها, در این قسمت کار API لاراول رو به اتمام می رسونیم و بخش Angular رو در قسمت بعدی توضیح می دهیم.

پیاده‌سازی درخواست های POST, PUT, DELETE

فایل کنترلر JokesController.php رو باز کرده و متدهای اون رو بصورت زیر آپدیت کنید.

اول این خط رو بالای کد قرار دهید :

use Illuminate\Http\Request;

سپس بصورت زیر تغییرات رو اعمال کنید :

public function store(Request $request)

    {



        if(! $request->body or ! $request->user_id){

            return Response::json([

                'error' => [

                    'message' => 'Please Provide Both body and user_id'

                ]

            ], 422);

        }

        $joke = Joke::create($request->all());



        return Response::json([

                'message' => 'Joke Created Succesfully',

                'data' => $this->transform($joke)

        ]);

    }



public function update(Request $request, $id)

    {    

        if(! $request->body or ! $request->user_id){

            return Response::json([

                'error' => [

                    'message' => 'Please Provide Both body and user_id'

                ]

            ], 422);

        }

        

        $joke = Joke::find($id);

        $joke->body = $request->body;

        $joke->user_id = $request->user_id;

        $joke->save(); 



        return Response::json([

                'message' => 'Joke Updated Succesfully'

        ]);

    }



   public function destroy($id)

    {

        Joke::destroy($id);

    }

برای تست درخواست POST افزونه postman رو باز کرده و بصورت زیر درخواست POST رو ارسال نمایید :

درخواست های DLETE و UPDATE رو هم به سادگی میتونید انجام بدید.

صفحه بندی

برای صفحه بندی, لاراول یک متد ساده به اسم ()paginate داره, در ادامه با استفاده از این متد صفحه بندی رو پیاده‌سازی می کنیم. کنترلر JokesController رو باز کرده و متد index رو بصورت زیر آپدیت نمایید :

public function index(){

        $jokes = Joke::with(

                array('User'=>function($query){

                    $query->select('id','name');

                })

                )->select('id', 'body', 'user_id')->paginate(5); 

        return Response::json($this->transformCollection($jokes), 200);

    }

حالا اگر وارد مسیر شوید به ارور برمیخورید :

مشکل اینه که ما باید متد transformCollection رو در کنترلر JokesController آپدیت کنیم :

private function transformCollection($jokes){

        $jokesArray = $jokes->toArray();

        return [

            'total' => $jokesArray['total'],

            'per_page' => intval($jokesArray['per_page']),

            'current_page' => $jokesArray['current_page'],

            'last_page' => $jokesArray['last_page'],

            'next_page_url' => $jokesArray['next_page_url'],

            'prev_page_url' => $jokesArray['prev_page_url'],

            'from' => $jokesArray['from'],

            'to' =>$jokesArray['to'],

            'data' => array_map([$this, 'transform'], $jokesArray['data'])

        ];

    }

حالا به مسیر تعیین شده برید و صفحه بندی انجام شده رو مشاهده کنید :

درحال حاضر ما به 5 آیتم در هر صفحه صفحه بندی کردیم اما ما میتونیم از query string هم برای این کار استفاده کنیم :

public function index(Request $request)

    {              



        $limit = $request->input('limit')?$request->input('limit'):5;



        $jokes = Joke::with(

        array('User'=>function($query){

            $query->select('id','name');

        })

        )->select('id', 'body', 'user_id')->paginate($limit); 



        $jokes->appends(array(            

            'limit' => $limit

        ));



        return Response::json($this->transformCollection($jokes), 200);

    }

بدین شکل که اگر query string مورد نظر موجود باشه اون درنظر گرفته شه وگرنه عدد 5 جایگزین میشه.

پیاده‌سازی جستجو

حالا بیایم درمورد نحوه پیاده‌سازی جستجو صحبت کنیم. اول متد index رو به صورت زیر آپدیت کنید:

public function index(Request $request)

    {      

        $search_term = $request->input('search');

        $limit = $request->input('limit')?$request->input('limit'):5;



        if ($search_term)

        {

            $jokes = Joke::orderBy('id', 'DESC')->where('body', 'LIKE', "%$search_term%")->with(

            array('User'=>function($query){

                $query->select('id','name');

            })

            )->select('id', 'body', 'user_id')->paginate($limit); 



            $jokes->appends(array(

                'search' => $search_term,

                'limit' => $limit

            ));

        }

        else

        {

            $jokes = Joke::orderBy('id', 'DESC')->with(

            array('User'=>function($query){

                $query->select('id','name');

            })

            )->select('id', 'body', 'user_id')->paginate($limit); 



            $jokes->appends(array(            

                'limit' => $limit

            ));

        }

        

        return Response::json($this->transformCollection($jokes), 200);

    }

حالا میتونید بصورت زیر تستش کنید :

افزودن JWT Auth

حالا میخوایم مسیرها رو امنیتی تر کنیم, طوری که فقط کاربران احراز هویت شده بتونند درخواست اطلاعات بدهند و کاربران دیگر خطا دریافت کنند! ما از auth پایه که لاراول فراهم کرده استفاده می‌کنیم کنترلر JokesController باز کرده و تغییر زیر ایجاد کنید :

public function __construct(){

        //$this->middleware('auth.basic', ['only' => 'store']);

        $this->middleware('auth.basic');
}

این یعنی استفاده از auth در تمام مسیرها. وقتی ما بخوایم وارد مسیر بشیم ابتدا باید به سیستم وارد بشیم :

اما ما نمی‌خواهیم از این سیستم برای api خودمون استفاده کنیم چون بهتره از یک سیستم احراز هویت token base استفاده کنیم. که یعنی وقتی کاربر تأیید هویت میشه یک توکن برای تولید میشه و اون هربار توکن رو همراه با درخواستش می فرسته و اگر توکن معتبر بود اطلاعات نمایش داده میشه. 

برای اینکار ما از پکیجی به نام jwt-auth استفاده می کنیم.

ابتدا خط زیر رو به فایل composer.json اضافه کنید :

"tymon/jwt-auth": "0.5.*"

سپس دستور زیر رو اجرا کنید :

composer update

بعد از دانلود این پکیج خط زیر رو به providers در فایل config/app.php بیافزایید :

Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class

و خطوط زیر رو به قسمت aliases

'JWTAuth'   => Tymon\JWTAuth\Facades\JWTAuth::class,

'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class

توسط دستور زیر اون رو منتشر کنید :

php artisan vendor:publish –provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"

حالا یک فایل جدید به اسم jwt.php به پوشه کانفیگ اضافه میشه. دستور زیر رو برای ساخت کلید jwt وارد نمایید :

php artisan jwt:generate

حالا فایل routes/web.php باز کرده و خطوط زیر بیافزایید :

Route::group(['prefix' => 'api/v1'], function()

{

    Route::resource('authenticate', 'AuthenticateController', ['only' => ['index']]);

    Route::post('authenticate', 'AuthenticateController@authenticate');

    Route::get('authenticate/user', 'AuthenticateController@getAuthenticatedUser');

});

حالا middleware رو به کنترلر اضافه کنید :

public function __construct(){

        $this->middleware('jwt.auth');

}

و کنترلر AuthenticateController باز کرده و تغییرات زیر رو اعمال کنید :

namespace App\Http\Controllers;



use Illuminate\Http\Request;

use App\Http\Requests;

use App\Http\Controllers\Controller;

use App\User;

use JWTAuth;

use Tymon\JWTAuth\Exceptions\JWTException;



class AuthenticateController extends Controller

{



    public function __construct()

   {

       $this->middleware('jwt.auth', ['except' => ['authenticate']]);

   }



    /**

     * Display a listing of the resource.

     *

     * @return \Illuminate\Http\Response

     */

    public function index()

    {

        return "Auth index";

    }



    public function authenticate(Request $request)

    {

        $credentials = $request->only('email', 'password');



        try {

            // verify the credentials and create a token for the user

            if (! $token = JWTAuth::attempt($credentials)) {

                return response()->json(['error' => 'invalid_credentials'], 401);

            }

        } catch (JWTException $e) {

            // something went wrong

            return response()->json(['error' => 'could_not_create_token'], 500);

        }



        // if no errors are encountered we can return a JWT

        return response()->json(compact('token'));

    }



    public function getAuthenticatedUser()

    {

        try {



            if (! $user = JWTAuth::parseToken()->authenticate()) {

                return response()->json(['user_not_found'], 404);

            }



        } catch (Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {



            return response()->json(['token_expired'], $e->getStatusCode());



        } catch (Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {



            return response()->json(['token_invalid'], $e->getStatusCode());



        } catch (Tymon\JWTAuth\Exceptions\JWTException $e) {



            return response()->json(['token_absent'], $e->getStatusCode());



        }



        // the token is valid and we have found the user via the sub claim

        return response()->json(compact('user'));

    }

}

اگر وارد مسیر /api/v1/jokes بشید با ارور token not provided مواجه میشید.

برای ساخت توکن به api/v1/authenticate رفته و ایمیل و پسورد رو وارد کنید :

حالا میتونید به صورت زیر درخواست رو همراه توکن فرستاده و نتیجه رو ببینید :

مبارزه با CORS

برای اینکه مباحث امنیتی api رو تکمیل کنیم نباید اجازه بدیم کسی با استفاده از cross domain restrictions به api دسترسی پیدا کنه. پس از پکیج laravel-cors استفاده می کنیم.

composer require barryvdh/laravel-cors 0.7.x

افزودن provider :

Barryvdh\Cors\ServiceProvider::class

درنهایت تغییراتی در فایل routes/web.php :

Route::group(['middleware' => 'cors', 'prefix' => 'api/v1'], function()

{

    Route::resource('authenticate', 'AuthenticateController', ['only' => ['index']]);

    Route::post('authenticate', 'AuthenticateController@authenticate');

    Route::get('authenticate/user', 'AuthenticateController@getAuthenticatedUser');

});



Route::group(['middleware' => 'cors', 'prefix' => 'api/v1'], function(){

Route::resource('jokes', 'JokesController');

});

در قسمت بعد بیشتر درباره بخش Angular صحبت می کنیم.

منبع

چه امتیازی برای این مقاله میدهید؟

خیلی بد
بد
متوسط
خوب
عالی
در انتظار ثبت رای

دیدگاه و پرسش

برای ارسال دیدگاه لازم است وارد شده یا ثبت‌نام کنید ورود یا ثبت‌نام

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

در حال دریافت نظرات از سرور، لطفا منتظر بمانید