إدارة الصور في laravel 5 أساسيات إدارة الصور في Laravel - الجزء الأول


هشام رزق الله

إدارة الصور هي واحدة من الأشياء التي غالبا ما أجدها صعبة، فأنا معتاد على التعامل مع النماذج وجداول قواعد البيانات، لكن التعامل مع الملفات ليس سهلا بالنسبة لي، فإذا كنت قد بدأت للتو مع Laravel وبدأت تشعر بالصعوبة والضيق، فأنا أشعر بألمك.

laravel5-image-management.thumb.png.5c3f

لحسن الحظ، أساسيات إدارة الصور في Laravel لن تكون صعبة إذا فهمت بعض الأمور الأساسية.

ملاحظة: إذا كنت جديدا في Laravel، فلا أنصحك بالبدء بهذا الدرس، أنصحك بقراءة بعض الدروس والدورات حول Laravel قبل المتابعة.

سوف تلاحظ أن الدرس طويل لذلك قمت بتقسيمه إلى 3 أجزاء، وسوف تلاحظ أيضا أنني لست بارعا في تصميم الواجهة الأمامية (front-end)، فلذلك فالواجهات التي سنقوم بعملها لن تكون جميلة جدا، يمكنك تزيينها بنفسك لاحقا، فالهدف الأساسي هنا هو تعلم أساسيات إدارة الصور.
لذلك على أية حال، ماهي هذه الأساسيات ؟ فكرتُ بالمتطلبات التي قد تحتاجها في تطبيقك وكتبتها في هذه القائمة:

  • إنشاء الصور
  • تخزين الصور
  • تعديل الصور
  • تحديث الصور
  • إنشاء صور مصغرة
  • تعديل صور مصغرة
  • إنشاء وتعديل صور الهواتف بشكل منفصل

بالنسبة للذين اعتادوا على إجراءات المتحكِّمات (controller actions) المريحة، ستظهر الاستمارات عند إجراءات (actions) الإنشاء create والتعديل edit وأما إجراءات التخزين store والتحديث update فوظيفتهم إنشاء وتعديل السجلات والملفات.
سنتعامل مع شيئين مهمين عند تعاملنا مع الصور، الشيء الأول هو النموذج الذي يعمل على البيانات مثل اسم الصورة و مسارها، وأما الشيء الثاني فهو ملف الصورة نفسه الذي سوف يتم تخزينه في مجلد الذي سنقوم بإسناده له.

تثبيت Intervention

سوف نبدأ بتثبيت حزمة Intervention/image، فإذا لم تقُم بذلك، عدل على ملف composer.json وأضف التعليمة التالية في جزء الاستدعاء (require) :

"intervention/image": "~2.2"

ثم أضف السطر التالي ضمن مصفوفة Providers في ملف app\config\app.php (انتبه للفواصل) :

Intervention\Image\ImageServiceProvider::class,

في نفس الملف أضف السطرين التاليين لمصفوفة Aliases:

Intervention\Image\ImageServiceProvider::class,

أنصحك بالإطلاع على صفحة Intervention للتأكد من الإصدار الأخير للحزمة.
في آخر مرة تأكدتُ فيها،كانت تعليمات التَدَخّل تستخدم النمط القديم للإشارة إلى المرجع:

'Intervention\Image\ImageServiceProvider'

يمكنك أن تلاحظ في الأعلى أننا في كلتا الحالتين استخدمنا ::class والتي هي ممارسة جيدة تعلمتها من Laracasts.com، فإذا كنت تستخدم على سبيل المثال PHP Storm، فسيكون باستطاعتك الوصول إلى الفئة class الأساسية.

إن حزمة Intervention تقوم بإعطائنا صياغة (syntax) وطريقة سهلة لصناعة الصور المصغرة بالإضافة إلى الكثير من التوابع (method) الأخرى الرائعة، لذلك سوف نستخدمها في هذا الدرس، ولمزيد من المعلومات حول هذه الحزمة أنصحك بالإطلاع على التوثيق الرسمي.

لاحظ أيضا أننا سنقوم باستخدام حزمة laravelcollective/html وحزمة patricktalmadge/bootstrapper، ولذلك قم بتثبيتهم قبل أن تتابع الدرس.

إنشاء نموذج

سوف نبدأ بإنشاء نموذج Marketingimage، يمكننا فعل ذلك عن طريق artisan من سطر الأوامر بكتابة السطر التالي:

php artisan make:model Marketingimage -m

سوف تلاحظ علم m- الذي سيخبر Laravel أنك تريد إنشاء تهجير migration في نفس الوقت، لذلك فهذه الميزة مفيدة للغاية.

حسنا، قم بتنفيذ الأمر السابق وستحصل على ملف النموذج والمسمى Marketingimage.php مباشرة تحت دليل تطبيقك وستحصل أيضا على ملف التهجير في مجلد database/migrations. دعونا نقوم بتعديل التابع في أعلى ملف التهجير إلى ما يلي:

public function up()
{
    Schema::create('marketing_images', function(Blueprint $table)
    {
        $table->increments('id');
        $table->boolean('is_active')->default(false);
        $table->boolean('is_featured')->default(false);
        $table->string('image_name')->unique();
        $table->string('image_path');
        $table->string('image_extension', 10);
        $table->string('mobile_image_name')->unique();
        $table->string('mobile_image_path');
        $table->string('mobile_extension', 10);
        $table->timestamps();
    });
}

أول شيئ يمكنك رؤيته أنني قد غيرت اسم الجدول، فأنا افضل فصل الكلمات في جدول الأسماء بسطر سفلي underscore. أنت حر في اختيار الطريقة التي تعجبك، لكن يجب أن نختار صيغة الجمع لإتباع قواعد Laravel بشكل صحيح. ففي Laravel، النموذج يكتب بصيغة المفرد وأما اسم الجدول فيكتب بصيغة الجمع.

بعد عمود المعرف الرقمي، قمنا باستخدام عمودين من نوع المنطقي boolean والتي سوف تسمح لنا بمعرفة هل الصورة نشطة أو مميزة، هذه القيود المفيدة سوف تساعد على العمل مع الصور في وقت لاحق.
ثم قمنا بإضافة أعمدة الاسم، المسار والامتدادات للصور وصور الهاتف، وهذا سيسمح لنا بالمرونة الكافية إذا أردت حفظ صورة مختلفة للهاتف، وهذا الأمر ضروري لأن تغيير حجم الصورة قد لا ينتج لنا النتائج المرجوة.

وبما أننا سوف نقوم بإنشاء صور مصغرة من الصور الأصلية، لن نحتاج إلى حفظ أية بيانات لذلك.

عن طريق حفظ مسار وإمتداد الصورة، سيكون لدينا مرجع سهل نستطيع استخدامه لإظهار الصورة في تطبيقنا، بالإضافة إدارة الصورة في قائمة الصور.

عدل على التابع ليبدو على النحو التالي:

public function down()
{
   Schema::drop('marketing_images');
}

بمجرد أن تقوم بذلك، قم بتنفيذ أمر php artisan migrate من سطر الأوامر وتأكد من أن الجدول قد تم إنشاءه.

بعد هذا، سوف نقوم بتعديل نموذج Marketingimage كما يلي:

 <?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Marketingimage extends Model
{
    protected $table = 'marketing_images';

    protected $fillable = ['is_active',
                                     'is_featured',
                                    'image_name',
                                    'image_path',
                                    'image_extension',
                                    'mobile_image_name',
                                    'mobile_image_path',
                                    'mobile_extension'
    ];
}

سوف تلاحظ أننا قمنا بإخبار النموذج الجدول الذي سيتخذه كمرجع، بالإضافة إلى توفير أعمدة مملوءة تلقائيا، حتى لا نواجه مشكلة الإحالة الكتلية mass-assignment.

المتحكم

جيد، نحن الآن مستعدين للاستمرار للخطوة القادمة، سنقوم بإنشاء المتحكِّم بإستخدام artisan:

php artisan make:controller MarketingImageController

وبهذا سوف تحصل على متحكِّم في app/Http/Controllers مع التوابع التالية:

  • index
  • create
  • store
  • show
  • edit
  • update
  • destroy

وسوف نستخدم جميع هذه التوابع.
وكنصيحة مفيدة للمبتدئين، قُم بوضع السطر التالي في تابع index:

return 'Here is the index method.';

فهذا سوف يعطيك فرصة لتجربة هذا الطريق route. (يستطيع بقية المبرمجين المحترفين تجاوز هذه الخطوة إذا أرادوا)
وبعد ذلك، سنقوم بتثبيت الطرق routes. عدل على ملف app/Http/routes.php وأضف التعليمة التالية:

Route::resource('marketingimage', 'MarketingImageController');

سوف ترى أننا قد قمنا بإضافة مورد resource، والذي سوف يقوم بإعطائنا الطرق routes لجميع الإجراءات actions بطريقة مريحة للغاية.
حسنا، سوف تستطيع الآن الذهاب إلى yourproject.com/marketingimage وسوف تحصل على النتيجة التالية:

Here is the index method.

الخطوة المنطقية التالية هي إعداد العروض views، أنشئ مجلدا باسم marketingimage أسفل resources/views، ثم أنشئ الملفات الفارغة التالية داخل مجلد marketingimages:

  • create.blade.php
  • edit.blade.php
  • index.blade.php
  • show.blade.php

إعداد المجلدات

سوف نعود إلى تلك الملفات في وقت لاحق، في الوقت الحالي، سنقوم بإنشاء مكان لتخزين صورنا الحالية، سوف أجعل هذا الأمر سهلا، أنشئ مجلدا باسم imgs مباشرة تحت مجلدك العام (public folder)، وبداخل مجلد imgs، أنشئ مجلد marketing، وبداخله أنشئ مجلدا باسم mobile وآخر بإسم thumbnails.
الآن قمنا بإنشاء جميع المجلدات للصور.

عرض الإنشاء The Create View

حسنا، دعونا الآن نتعامل مع عرض الإنشاء The Create View. أضف الأسطر التالية داخل ملف `create.blade.php`:

 @extends('layouts.master')
    
    @section('content')
    
        {!! Breadcrumb::withLinks(['Home' => '/', 'marketing images' => '/marketingimage', 'create']) !!}
    
         <h1>Upload a Photo </h1>
    
    
         <hr/>
    
         @if (count($errors) > 0)
    	 <div class="alert alert-danger">
    	 <strong>Whoops! </strong> There were some problems with your input. <br> <br>
    	 <ul>
    	     @foreach ($errors->all() as $error)
    		 <li>{{ $error }} </li>
    	     @endforeach
    
             </ul>
             </div>
    
        @endif
    
    
        {!! Form::open(array('route' => 'marketingimage.store', 'class' => 'form', 'files' => true)) !!}
    
         <!-- image name Form Input -->
         <div class="form-group">
            {!! Form::label('image name', 'Image name:') !!}
            {!! Form::text('image_name', null, ['class' => 'form-control']) !!}
         </div>
    
    
         <!-- mobile_image_name Form Input -->
         <div class="form-group">
            {!! Form::label('mobile_image_name', 'Mobile Image Name:') !!}
            {!! Form::text('mobile_image_name', null, ['class' => 'form-control']) !!}
         </div>
    
    
         <!-- is_something Form Input -->
         <div class="form-group">
            {!! Form::label('is_active', 'Is Active:') !!}
            {!! Form::checkbox('is_active') !!}
         </div>
    
         <!-- is_featured Form Input -->
         <div class="form-group">
            {!! Form::label('is_featured', 'Is Featured:') !!}
            {!! Form::checkbox('is_featured') !!}
         </div>
    
        <!-- form field for file -->
        <div class="form-group">
           {!! Form::label('image', 'Primary Image') !!}
           {!! Form::file('image', null, array('required', 'class'=>'form-control')) !!}
        </div>
    
         <!-- form field for file -->
         <div class="form-group">
            {!! Form::label('mobile_image', 'Mobile Image') !!}
            {!! Form::file('mobile_image', null, array('required', 'class'=>'form-control')) !!}
         </div>
    
         <div class="form-group">
    
            {!! Form::submit('Upload Photo', array('class'=>'btn btn-primary')) !!}
    
         </div>
    
        {!! Form::close() !!}
    
    @endsection

لاحظ أن الشيفرة في الأعلى ليست صعبة ويمكنك فهمها بسهولة دون أن تضطر إلى قراءة الشرح، ولاحظ أيضا أننا نقوم بتوسيع صفحتنا الرئيسية master page، التي بداخلها مجلد المخططات في مجلد العروض. والتي قمنا باستدعائها عن طريق هذه التعليمة:

@extends('layouts.master')

إذا كانت لديك صفحة رئيسية أخرى أو أنها موجودة في مكان مختلف، قم بتعديل ذلك حسب الحاجة، وإذا كنت لا تعرف مفهوم الصفحة الرئيسية master page، قُم بالبحث عن دروس حوله وتعلمه قبل أن تتابع الدرس.
إذا كنت لا تستخدم حزمة `Bootstrapper`، قم بحذف السطر التالي:

{!! Breadcrumb::withLinks(['Home' => '/', 'marketing images' => '/marketingimage', 'create']) !!}

لاحظ أيضا، لهذا الدرس، قمت بتضمين `if` لطباعة أخطاء الإدخال، لكن في العادة، يجب وضع هذا الجزء في جزئية العرض view partial ومن ثم الإشارة إليه بشيء مثل هذا:

@include('errors.errors')

يمكنك أيضا ملاحظة أننا نستخدم مساعد الاستمارة Form helper من حزمة `laravelcollective/html`، فلقد وجدت أن مساعد الاستمارة مفيد جدا خاصة عند استخدامه لفتح الاستمارة:

{!! Form::open(array('route' => 'marketingimage.store', 'class' => 'form', 'files' => true)) !!}

تستطيع أن ترى أننا قمنا بتضمين 'files => 'true والتي تسمح لنا برفع ملفات متعددة.
إذا كنت جديدا في استخدام مساعد الاستمارة، فيمكنك ملاحظة أننا لا نحتاج إلى استخدام POST خاصة وأننا لا نحتاج إلى استدعاء رمز CSFR لأنه يتم ذلك تلقائيا.
ثم لدينا مدخلات المختلفة للاستمارة، لا شيء مجنون للغاية هنا، ولدينا أيضا `Form::submit` والتي نستخدمها كزر، بالإضافة إلى `Form::close()`.
يمكنك أن ترى من مساعد الاستمارة أن الطريق route تم تعيينه إلى `marketingimage.store`، لذلك سوف نعرف من مورد الطريق في `routes.php` أن هذا سوف يأخذنا إلى تابع `store` في `MarketingImageController.php` والذي هو دليل المتحكِّمات.

نُكمل في الجزء الثاني من الدرس.

ترجمة -وبتصرّف- للمقال Basic Image Management Part 1 لصاحبه Bill Keck.

حقوق الصورة البارزة: Designed by Freepik.



1 شخص أعجب بهذا


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


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



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

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

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


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

تسجيل الدخول

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


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