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


محمد أحمد العيل

يتوفّر إطار العمل Laravel على واجهة تطبيقات برمجيّة API موّحّدة للتعامل مع الملفات. تأتي واجهة التطبيقات هذه مجهّزة مبدئيا بتعريفات Drivers تمكّن من إدارة الملفات على نظام الملفات المحلّي، خادوم FTP أو على خدمتي Amazon S3 وRackspace السّحابيتين. سنعرض في هذا الدرس لأساسيّات إدارة الملفات: رفعها Upload، تخزينها والعثور عليها في الإصدار 5.3 من إطار العمل Laravel.

laravel3.png

أقراص التخزين في Laravel

تُضبَط إعدادات تخزين الملفات ضمن الملف config/filesystems.php عن طريق ما يُسمّيه Laravel الأقراص Disks. يُمثّل كل قرص تعريفا، مسارا للتخزين وإعدادات خاصّة بالقرص. يعرّف ملفّ الإعداد مبدئيا ثلاثة أقراص public، local وs3:

'disks' => [

    'local' => [
        'driver' => 'local',
        'root' => storage_path('app'),
    ],

    'public' => [
        'driver' => 'local',
        'root' => storage_path('app/public'),
        'visibility' => 'public',
    ],

    's3' => [
        'driver' => 's3',
        'key' => 'your-key',
        'secret' => 'your-secret',
        'region' => 'your-region',
        'bucket' => 'your-bucket',
    ],

],

يستخدم القرصُ local في المثال المبدئي أعلاه التعريفَ local (نظام الملفات المحلّي) ومسار التخزين storage/app. بالنسبة للقرص s3 فهو يستخدم التعريف s3 (خدمة Amazon S3) ويتطلّب قيما ضرورية للولوج إلى الخدمة.
يشبه القرص public القرصَ local؛ إلا أنّ بينهما فرقًا جوهريًّا: هذا القرص مهيّأ للملفات التي نريد إتاحتها للعموم. تُخزَّن ملفات هذا القرص على المسار storage/app/public. يمكن ملاحظة أن المسار storage/app/public يوجد خارج المجلّد public الذي يحوي ملفّات المشروع المتاحة للعموم. نستخدم أمر Artisan التالي لجعل ملفات القرص public متاحة على الوِب:

 
php artisan storage:link

ينشئ الأمر وصلة رمزيّة على المسار public/storage ويجعلها تحيل إلىstorage/app/public الذي هو مسار تخزين القرص public. سنرى بعد قليل كيف نصل إلى الملفات الموجودة في هذا القرص.

ملحوظة: يتطلّب استخدام التعريفيْن s3 وrackspace تثبيت الحزمتييْن التاليّتيْن على التوالي (عن طريق composer):

league/flysystem-aws-s3-v3 ~1.0
league/flysystem-rackspace ~1.0

رفع ملفات وعرض روابطها في Laravel 5.3

سنهيّئ في بقيّة الدرس مشروع Laravel 5.3 للعمل عليه. سيكون هدفنا رفع صورة في المتصفّح ثم عرض هذه الصورة في صفحة الوِب.
نضيف مسارين إلى ملف مسارات الوِب routes/web.php:

Route::get('image-upload','ImageController@imageUpload');
Route::post('image-upload','ImageController@imageUploadPost');

يتلقّى الإجراء get طلبات عرض الصفحة، في ما نستخدم الإجراء post لتخزين الصّورة المحمَّلة في الصفحة التي سننشئها بعد قليل.

الخطوة التاليّة هي إنشاء المتحكّم ImageController وكتابة الدالتين imageUpload وimageUploadPost:

 
php artisan make:controller ImageController

كلّ ما تفعله الدالة imageUpload هو استدعاء العرض image-upload:

public function imageUpload()
{
    return view('image-upload');
}

بالنسبة للدالة imageUploadPost فستستقبل الصورة المحمّلة من المتصفّح، تخزّنها ثم ترسلها إلى image-upload الذي يعرضها:

public function imageUploadPost(Request $request)
{
  // TODO:
  return view('image-upload')
          ->with('message', "Image uploaded successfully")
          ->with('path', $imagePath);
}

الدالة غير مكتملة لحد الساعة، فكل ما يظهر منها هو استدعاء القالب وتمرير رسالة إليه تفيد بنجاح رفع الصورة، إضافة إلى متغيّر يمثّل رابط الصورة. استقبال الصورة، تخزينها والحصول على رابط تخزينها سيكون محلّ التعليق TODO.
ننشئ القالب image-upload قبل العودة إلى الدالة imageUploadPost.

ننشئ الملف image-upload.blade.php على المسار resources/views ونضع فيه المحتوى التالي:

<!DOCTYPE html>
<html>
<head>
        <title>Laravel 5.3 Image Upload example</title>
</head>
<body>
<div>
    @if (isset($path))
        <p>{{ $message }}</p>
        <img src="{{ url($path) }}">
    @endif

    <form action="{{ url('image-upload') }}" enctype="multipart/form-data" method="POST">
            {{ csrf_field() }}
            <div>
                    <div>
                            <input type="file" name="image" />
                    </div>
                    <div>
                            <button type="submit">Upload</button>
                    </div>
            </div>
    </form>
</div>
</body>
</html>

نتحقّق أولا، عن طريق الدالة isset، من وجود متغيّر باسم path في المعطيات الممرّرة إلى القالب. يمثّل المتغيّر path مسار الصورة التي نعرضها في حال وجود المتغيّر path. ثم يأتي دور استمارة الرّفع التي ترسل طلبا بإجراء POST إلى المسار image-upload. نحدّد نوع المُدخَل input الذي نريد استقبال الصورة عن طريقه بالنوع file ونحدّد اسمه بـimage.

نستطيع الآن العودة إلى الدالة imageUploadPost لإكمالها:

public function imageUploadPost(Request $request)
{
  // TODO:
  return view('image-upload')
          ->with('message', "Image uploaded successfully")
          ->with('path', $imagePath);
}

نستقبل الطلب في المعطى request؛ حيث يمكننا تطبيق الدالة file للحصول على الصورة التي حمّلها المتصفّح بتحديد اسم المُدخَل input الذي استقبلها في صفحة الوٍب:

 
$request->file('image');

نطبّق على الملف الدالة store لتخزينه:

 
$image = $request->file('image')->store('images', 'public');

تأخذ الدالة store معطَيَيْن، الأول منهما هو اسم المجلّد حيثُ نريد تخزين الملفّ والثاني اسم القرص الذي نريد استخدامه. إن لم نحدّد اسمَ القرص فسيُستخدَم القرص المبدئي المعرّف بالتعليمة default ضمن ملف الإعداد config/filesystems (تأخذ التعليمة مبدئيا القيمة local).

نريد أن تكون الصورة متاحة للعموم ضمن مجلد خاصّ بالصور اسمه images، لذا نمرّر القيمتيْن images وpublic للمعطييْن الأول والثاني على التوالي.

خزّنا الآن الصورة على القرص المتاح للعموم. الخطوة التاليّة هي الحصول على مسارها من أجل إرساله إلى القالب image-upload لعرضه. نستخدم الدالة url ضمن الصنف Storage والتي يمكن تطبيقها على أقراص تستخدم أحد التعريفيْن local أو s3:

 
$imagePath = Storage::url($image);

لا ننسى استيراد الصّنف Storage:

 
use Illuminate\Support\Facades\Storage;

أصبحت دالة المتحكّم مكتملة على النحو التالي:

public function imageUploadPost(Request $request)
{
  $image = $request->file('image')->store('images','public');
  $imagePath = Storage::url($image);

  return view('image-upload')
          ->with('message', "Image uploaded successfully")
          ->with('path', $imagePath);
}

لا ننسى إنشاء الوصلة الرمزية:

 
php artisan storage:link

نشغّل خادوم التطوير المضمَّن في Laravel:

 
php artisan serve    

ثم نفتح المتصفّح لزيارة المسار http://localhost:8000/image-upload. نختار صورة لرفعها ثم نضغط على الزّر Upload. يخزّن Laravel الصّورة في المجلّد storage/app/public، ثم يطلُب عرض القالب image-upload مع تمرير رابط الصّورة في المتغيّر path، إضافة إلى رسالة في المتغيّر message تفيد بنجاح الرّفع.

ملحوظة: يختار Laravel عند استخدام الدالة store اسما مميّزا للملف بتطبيق دالة تجزئة Hash عليه. إن أردت اختيار الاسم الذي يُخزَّن به الملف فيمكنك ذلك بالدالة storeAs:

  • تخزين الملف في القرص المبدئي:

    $image = $request->file('image')->storeAs('images','fileName');

     

  • تخزين الملف مع تحديد القرص:

     
$image = $request->file('image')->storeAs('images','fileName','public');

العمليّات على الملفات المرفوعة

يوفّر Laravel الصّنفَ Storage للتعامل مع الملفات والأقراص.

إضافة ملفات إلى التخزين

تُستخدَم الدالة put في الصّنف Storage لتخزين ملفات على النحو التالي:

 
Storage::put('images', $fileContents);

يُمثّل المعطى الأوّل الممرَّر إلى الدالة اسمَ المجلّد الذي تريد حفظ الملفّ فيه والثاني محتوى الملفّ. تستخدم الدالة أعلاه القرص المبدئي (التعليمة default في ملف الإعداد). إن أردت استخدام قرص مغاير فيمكنك الاستعانة بالدالة disk:

 
Storage::disk('public')->put('images', $fileContents);

يُحدَّد المجلّد المُمرَّر إلى الدالة put (المعطَى الأول) اعتمادا على المسار الجذر للقرص المستخدَم؛ أي أن المقصود بالمجلّد images في المثال السابق هو المجلد storage/app/public/images؛ نظرا لكون storage/app/public هو المسار الجذر للقرص public. يُعيَّن المسار الجذر بالتعليمة root أثناء إعداد الأقراص في ملف الإعداد config/filesystems.

استرجاع ملف من التخزين

يتيح الصّنف Storage الدالة get لاسترجاع محتوى ملف مخزّن في القرص المبدئي:

 
$contents = Storage::get('images/file.jpg');

يمكن تحديد القرص المستهدَف باستدعاء الدالة disk قبل تطبيق get.

يتوفّر الصّنف Storage على الدالة exists التي تتيح التأكد من وجود الملفّ:

 
$exists = Storage::disk('s3')->exists('file.jpg');

الحصول على بيانات ملفّ

استخدم الدالة size على النحو التالي لمعرفة حجم ملفّ موجود في القرص المبدئي:

 
$size = Storage::size('file1.jpg');

أو بتحديد القرص المستهدَف:

 
$size = Storage::disk('s3')->size('file1.jpg');

يمكن على نفس المنوال معرفة تاريخ آخر تعديل على الملف على صيغة ختم زمني Timestamp:

$time = Storage::lastModified('file1.jpg');

 





تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن