عنوان مقاله :

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

گردآوری و تالیف : امیررضا سیستانه ای
تاریخ انتشار : 18 مرداد 1396
دسته بندی ها : لاراول , جاوا اسکریپت

در ادامه ی قسمت‌های قبل این سری آموزش‌ها, در این قسمت کار 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 صحبت می کنیم.

منبع

برچسب : ,

مقالات پیشنهادی

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

لاراول و AngularJS با همدیگه به خوبی کار می کنند, به شرطی که در مسیر درست از اون ها استفاده کنید. در این مقاله ما می‌خواهیم یک اپلیکیشن بسازیم که در ا...

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

در قسمت قبلی این سری مقاله ها بحث لاراول رو کامل کردیم اینبار میخواهیم بیشتر درمورد نقش Angular در پروژه مون صحبت کنیم.

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

در قسمت قبل این سری آموزش‌ها درمورد کلیات پروژه ای که میخوایم انجام بدیم, نحوه پیاده‌سازی پروژه لاراول و نحوه ایجاد جداول توسط migration ها صحبت کردیم...

آموزش ساخت برنامه موبایل توسط React Native – قسمت دوم

در قسمت قبل با ساختار و نحوه راه اندازی React Native آشنا شدیم, در این قسمت میخواهیم بیشتر روی کار عملی تمرکز کنیم و پروژه رو جلو ببریم.

دیدگاه های ارزشمند شما

برای ارسال نظر لازم است ابتدا وارد سایت شوید
حسین حسین پور | 4 ماه پیش

لطفا توجه داشته باشید که AngularJs نام نسخه 1 فریمورک angular هستش و از نسخه 1 به بعد Angular معرفی میشه و پسوند js نداره ( ویا Angular+version) چون نسخه 1 زمین تا آسمون با بقیه نسخه ها فرق میکنه. پس لطفا اگر از نسخه 1 استفاده نمی کنید ، نام نویسی رو تصحیح کنید.

حسام موسوی | 4 ماه پیش

بله ورژن بندی تغییر کرده و از نسخه ۲ به بعد با عنوان angular میشناسن هنوز نمی دونم قسمت بعد از angularJs استفاده میشه یا از angular

امیررضا سیستانه ای | 4 ماه پیش

بله همینطور که فرموردید منظور AngularJS هست که در عنوان هم نوشته شده.