الاستجابات HTTP في Laravel

من موسوعة حسوب

إنشاء الردود

السلاسل النصيّة والمصفوفات

يجب على جميع الطرق ووحدات التحكّم رد استجابة لإرسالها مرّة أخرى إلى متصفّح المستخدم. يوفر Laravel عدة طرق مختلفة لإرجاع الردود. أكثر رد أساسي هو رد سلسلة نصيّة من مسار أو جهاز تحكّم. سيُحوّل إطار العمل السلسلة النصيّة إلى استجابة HTTP كاملة تلقائيًا:

Route::get('/', function () {
    return 'Hello World';
});

يمكنك بالإضافة لرد السلاسل من مساراتك ووحدات تحكّمك رد مصفوفات. سيُحوّل إطار العمل تلقائيًا المصفوفة لاستجابة JSON:

Route::get('/', function () {
    return [1, 2, 3];
});

ملاحظة: هل تعلم أنك تستطيع أيضًا رد مجموعات Eloquent من مساراتك أو وحدات لتحكّمك؟ ستُحوّل تلقائيًا إلى JSON. جرّبها!

كائنات الاستجابة

عادة، لن تردّ فقط بسلاسل نصيّة أو مصفوفات بسيطة من أفعال مسارك. بل ستردّ نُسخ أو واجهات Illuminate\Http\Response كاملة.

يتيح لك رد نسخة Response كاملة تخصيص رمز حالة HTTP وترويسات الاستجابة. ترث النسخة Response من الصنف Symfony\Component\HttpFoundation\Response التي توفّر عدّة توابع متنوّعة لبناء الاستجابات HTTP:

Route::get('home', function () {
    return response('Hello World', 200)
                  ->header('Content-Type', 'text/plain');
});

ضع بالحسبان أن معظم توابع الاستجابة قابلة للاستدعاء كسلسلة (chainable)، أي استدعاء أحدها بعد الآخر مباشرةً مما يسمح ببناء سلس لنُسخ الاستجابات. تستطيع على سبيل المثال استخدام التابع header لإضافة سلسلة من الترويسات للاستجابة قبل ردّها للمستخدم:

return response($content)
            ->header('Content-Type', $type)
            ->header('X-Header-One', 'Header Value')
            ->header('X-Header-Two', 'Header Value');

أو تستطيع استخدام التابع withHeaders لتحديد مصفوفة من الترويسات المُراد إضافتها للاستجابة:

return response($content)
            ->withHeaders([
                'Content-Type' => $type,
                'X-Header-One' => 'Header Value',
                'X-Header-Two' => 'Header Value',
            ]);

إرفاق ملفات تعريف الارتباط بالردود

يسمح لك التابع cookie في نُسخ الاستجابات بإرفاق ملفات تعريف الارتباط بالرد بسهولة. تستطيع على سبيل المثال استخدام التابع cookie لتوليد ملف تعريف الارتباط وإضافته بسلاسة لنسخة الاستجابة كما يلي:

return response($content)
                ->header('Content-Type', $type)
                ->cookie('name', 'value', $minutes);

يتقبّل التابع cookie أيضًا بضع متغيّرات وسيطة أخرى تُستخدم بشكل أندر. لهذه المتغيّرات الوسيطة عمومًا نفس الغرض والمعنى التي يُعطى للتابع setcookie المحلي في PHP:

->cookie($name, $value, $minutes, $path, $domain, $secure, $httpOnly)

تستطيع كبديل لذلك استخدام الواجهة الساكنة Cookie لصفّ ملفات تعريف الارتباط المعدّة للإرفاق بالاستجابة الصادرة من تطبيقك في "طابور". يقبل التابع queue نسخة Cookie أو المتغيّرات الوسيطة اللازمة لإنشاء نسخة Cookie. ستُرفق ملفات تعريف الارتباط بالاستجابة الصادرة قبل إرسالها إلى المتصفح:

Cookie::queue(Cookie::make('name', 'value', $minutes));

Cookie::queue('name', 'value', $minutes);

ملفات تعريف الارتباط والتشفير

تُشفّر كافة ملفات تعريف الارتباط التي ينشئها Laravel وتُوقّع كي لا يستطيع العميل تعديلها أو قراءتها. إن رغبت بتعطيل التشفير لمجموعة فرعية من ملفات تعريف الارتباط التي أنشأها تطبيقك، تستطيع استخدام الخاصيّة except$ من البرمجيّة الوسيطة App\Http\Middleware\EncryptCookies الموجودة في مُجلّد التطبيق app/Http/Middleware:

/**
 * أسماء الكعكات التي لا ينبغي تشفيرها.
 *
 * @var array
 */
protected $except = [
    'cookie_name',
];

إعادات التوجيه (Redirects)

إعادات توجيه الاستجابات (Redirect responses) هي نُسخ من الصنف Illuminate\Http\RedirectResponse، وتحتوي على الترويسات المناسبة المطلوبة لإعادة توجيه المستخدم لعنوان URL آخر. توجد عدّة طرق لإنشاء نُسخة RedirectResponse. أبسط طريقة هي استخدام مساعد إعادة التوجيه العام (global redirect helper):

Route::get('dashboard', function () {
    return redirect('home/dashboard');
});

قد ترغب أحيانًا في إعادة توجيه المستخدم إلى موقعه السابق، مثلًا عندما يكون النموذج المقدّم غير صالح. تستطيع فعل ذلك باستخدام الدالّة المُساعدة العامّة back. بما أنّ هذه الميزة تستخدم الجلسة، تأكّد من أنّ المسار الذي يستدعي الدالّة back يستخدم مجموعة البرمجيّة web الوسيطة أو يحتوي كلّ برمجيّات الجلسات المُطبّقة الوسيطة:

Route::post('user/profile', function () {
   // Validate the request...

    return back()->withInput();
});

إعادة التوجيه لمسارات مسمّاة

عند مناداة المُساعد redirect بدون أية معاملات، تُردّ نسخة من Illuminate\Routing\Redirector، ممّا يسمح لك بمناداة أي تابع بالنسخة Redirector. تستطيع مثلًا استخدام التابع route لإنشاء RedirectResponse لمسار مسمّى:

return redirect()->route('login');

إن احتوى مسارك على معاملات، تستطيع تمريرها كمُتغيّر وسيط ثاني للتابع route:

// URI: profile/{id} لمسار بالعنوان 

return redirect()->route('profile', ['id' => 1]);

ملء المعاملات عبر نماذج Eloquent

إن أعدت التوجيه إلى مسار ما بمعاملة "ID" مملوءة من طرف نموذج Eloquent، تستطيع تمرير النموذج ذاته. سيُستخرج المعرّف ID تلقائيًا:

// URI: profile/{id} لمسار بالعنوان 

return redirect()->route('profile', [$user]);

يجب إعادة تعريف (override) التابع getRouteKey على نموذجك Eloquent إن رغبت في تخصيص القيمة الموضوعة في معاملة التوجيه:

/**
 * احصل على قيمة مفتاح مسار النموذج
 *
 * @return mixed
 */
public function getRouteKey()
{
    return $this->slug;
}

إعادة التوجيه لأفعال وحدة التحكّم

تستطيع توليد إعادات توجيه لأفعال وحدة التحكم. للقيام بذلك، مرّر وحدة التحكّم واسم الفعل للتابع action. تذكّر أنّك لا تحتاج لتحديد مجال الاسم الكامل لوحدة التحكّم بما أنّ RouteServiceProvider في Laravel سيضع مجال اسم وحدة التحكّم تلقائيًّا:

return redirect()->action('HomeController@index');

تستطيع ،إن تتطلّب مسار وحدة تحكّمك معاملات، تمريرها كمتغيّر وسيط ثاني للتابع action:

return redirect()->action(
    'UserController@profile', ['id' => 1]
);

إعادة توجيه لنطاقات خارجيّة

قد تحتاج في بعض الأحيان لإعادة التوجيه إلى نطاق خارج تطبيقك. تستطيع ذلك عن طريق مناداة التابع away ممّا ينشئ RedirectResponse دون أي ترميز (encoding) أو تحقق إضافي من صحة عنوان URL:

return redirect()->away('https://www.google.com');

إعادة التوجيه مع بيانات جلسة مومَضة (Redirecting With Flashed Session Data)

عادةً ما يُعاد التوجيه لعنوان URL جديد وتوميض (flashing) البيانات للجلسة في نفس الوقت. يحدث ذلك عادةً بعد تنفيذ فعل ما بنجاح عندما تومض رسالة نجاح لجلسة العمل. لتوفير الجهد، يمكنك إنشاء نسخة RedirectResponse وتمويض بيانات إلى الجلسة في سلسلة تابع وحيد سلس:

Route::post('user/profile', function () {
   // تحديث ملف المستخدم...

    return redirect('dashboard')->with('status', 'Profile updated!');
});

بعد إعادة توجيه المستخدم، يمكنك عرض الرسالة المومضة من الجلسة باستخدام صيغة Blade مثلًا:

@if (session('status'))
    <div class="alert alert-success">
        {{ session('status') }}
    </div>
@endif

أنواع استجابات أخرى

يمكن استخدام المُساعد response لتوليد أنواع أخرى من نُسخ الاستجابة. عند مناداة المساعد response بدون متغيّرات وسيطة، يردّ تعريف استخدام للعقد Illuminate\Contracts\Routing\ResponseFactory. يوفّر هذا العقد عدّة توابع مفيدة لتوليد الاستجابات.

استجابات الواجهات

إن احتجت للتحكّم في حالة (status) الاستجابة وترويساتها مع احتياجك أيضًا لردّ واجهة كمحتوى الاستجابة، عليك استخدام التابع view:

return response()
            ->view('hello', $data, 200)
            ->header('Content-Type', $type);

عليك استخدام دالّة المُساعدة العامّة view إن لم تكن بحاجة إلى تمرير رمز حالة HTTP أو ترويسات مخصّصة.

الاستجابات JSON

يضع التابع json الترويسة Content-Type على application/json تلقائيًا، إضافة إلى تحويل المصفوفة المحدّدة إلى JSON باستخدام دالّة PHP المسماة json_encode:

return response()->json([
    'name' => 'Abigail',
    'state' => 'CA'
]);

إذا رغبت في إنشاء استجابة JSONP، تستطيع استخدام التابع json مع التابع withCallback:

return response()
            ->json(['name' => 'Abigail', 'state' => 'CA'])
            ->withCallback($request->input('callback'));

تنزيل الملفّات

يمكن استخدام التابع download لإنشاء استجابة تجبر متصفّح المستخدم على تحميل الملف في المسار المحدّد. يتقبّل التابع download اسم الملف كمتغيّره الوسيط الثاني والذي سيحدد اسم الملف الذي يراه المستخدم مُنزّل الملف. وأخيرًا تستطيع تمرير مصفوفة من الترويسات HTTP كمتغيّر وسيط ثالث للتابع:

return response()->download($pathToFile);

return response()->download($pathToFile, $name, $headers);

return response()->download($pathToFile)->deleteFileAfterSend(true);

ملاحظة: تشترط Symfony HttpFoundation ، التي تدير تنزيلات الملفات أن يكون للملف المنزّل اسم ملف ASCII.

التنزيلات الجارية (Streamed Downloads)

قد ترغب في بعض الأحيان بتحويل سلسلة الاستجابة النصيّة لعمليّة معينة إلى استجابة قابلة للتنزيل دون الحاجة إلى كتابة محتويات العملية إلى القرص. تستطيع استخدام التابع streamDownload في هذا السيناريو. تقبل هذه الطريقة رد نداء، واسم ملف، ومجموعة ترويسات اختيارية كمتغيّرياتها الوسيطة:

return response()->streamDownload(function () {
    echo GitHub::api('repo')
                ->contents()
                ->readme('laravel', 'laravel')['contents'];
}, 'laravel-readme.md');

استجابات الملفّات

يمكن استخدام التابع file لعرض ملف، مثل صورة أو ملف PDF، مباشرة في متصفّح المستخدم بدلًا من البدء في تنزيل. يقبل هذا التابع المسار للملف كمتغيّره الوسيط الأول ومصفوفة من الترويسات كمتغيّره الثاني:

return response()->file($pathToFile);

return response()->file($pathToFile, $headers);

ماكرو الاستجابات (Response Macros)

تستطيع استخدام التابع macro على الواجهة الساكنة Response إن رغبت في تعريف استجابة مخصّصة يمكنك إعادة استخدامها في عدّة مسارات ووحدات تحكّم. على سبيل المثال، من التابع boot لمُوفّر خدمات:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Response;

class ResponseMacroServiceProvider extends ServiceProvider
{
    /**
     * تسجيل ماكرو التطبيق للاستجابة.
     *
     * @return void
     */
    public function boot()
    {
        Response::macro('caps', function ($value) {
            return Response::make(strtoupper($value));
        });
    }
}

يقبل التابع macro الباني اسمًا كمتغيّره الوسيط الأوّل، ويكون Closure الماكرو ثانيه. سيُنفّذ Closure الماكرو عند مناداة اسم الماكرو من تعريف استخدام ResponseFactory أو المساعد response:

return response()->caps('foo');

مصادر