عرض مشاركة واحدة
قديم 23-02-2019, 04:51 PM   #1
تاريخ التسجيل: Feb 2019
المشاركات: 1,010
التقييم: 10
تاريخ التسجيل: Feb 2019
المشاركات: 1,010
التقييم: 10
افتراضي إدارة الصور في laravel 5 أساسيات إدارة الصور في 5 Laravel - الجزء الثالث

إن توابع وعروض edit وdelete غير موجودة لحد الساعة، فلننشئها، سنبدأ بالعمل على edit أولا.
عدل على تابع المتحكم:

public function edit($id)
{
$marketingImage = Marketingimage::findOrFail($id);
return view('marketingimage.edit', compact('marketingImage'));
}
مرة أخرى قمنا باستخدام تابع findOrFail وقمنا بإرسال الكائن إلى العرض لأننا نريد أن نقوم بتعبئة الاستمارة مسبقا بالقيم المناسبة من سجلات البيانات.

عرض Edit
عدل على ملف views/marektingimage/edit.blade.php ليكون كالتالي:

@extends('layouts.master')

@section('content')
{!! Breadcrumb::withLinks(['Home' => '/',
'marketing images' => '/marketingimage',
"edit $marketingImage->image_name.$marketingImage->image_extension"
]) !!}

<h1>Edit {{ $marketingImage->image_name. '.' . $marketingImage->image_extension }} </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

<div>
Note: name and path values cannot be changed. If you wish to change these, then delete and create a new photo:
</div>
<br>


{!! Form::model($marketingImage, ['route' => ['marketingimage.update', $marketingImage->id],
'method' => 'PATCH',
'class' => 'form',
'files' => true]
) !!}

<!-- image name Form Input -->
<div>
<ul>
<li> <h4>Image Name: {{ $marketingImage->image_name. '.' . $marketingImage->image_extension }} </h4> </li>
<li> <h4>Image Path: {{ $marketingImage->image_path }} </h4> </li>
<li> <h4>Mobile Name: {{ $marketingImage->mobile_image_name. '.' . $marketingImage->mobile_extension }} </h4> </li>
<li> <h4>Mobile Path: {{ $marketingImage->mobile_image_path }} </h4> </li>
</ul>
</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('class'=>'form-control')) !!}
</div>

<!-- form field for file -->
<div class="form-group">
{!! Form::label('mobile_image', 'Mobile Image') !!}
{!! Form::file('mobile_image', null, array('class'=>'form-control')) !!}
</div>

<div class="form-group">
{!! Form::submit('Edit', array('class'=>'btn btn-primary')) !!}
</div>

{!! Form::close() !!}
<div>
{!! Form::model($marketingImage, ['route' => ['marketingimage.destroy', $marketingImage->id],
'method' => 'DELETE',
'class' => 'form',
'files' => true]
) !!}

<div class="form-group">
{!! Form::submit('Delete Photos', array('class'=>'btn btn-danger', 'Onclick' => 'return ConfirmDelete();')) !!}
</div>

{!! Form::close() !!}
</div>
@endsection

@section('scripts')
<script>
function ConfirmDelete()
{
var x = confirm("Are you sure you want to delete?");
if (x)
return true;
else
return false;
}
</script>
@endsection
لم نسمح للمستخدم بتعديل أسماء الصور أومساراتها لأننا نريدهم أن يقوموا بحذف السجلات والبدء من جديد وإلا سيكون الأمر معقدا عندما نقوم بتعديل الأسماء التي قمنا بحفظها في السجلات وهذا الأمر لا يدخل في نطاق الدرس.

ماهي الاختلافات الأخرى في الاستمارة ؟ سوف تلاحظ أننا نستخدم حقول أقل وقمنا باستخدام الربط بين النموذج والاستمارة في مساعدي الاستمارة (form helper):

{!! Form::model($marketingImage, ['route' => ['marketingimage.update', $marketingImage->id],
'method' => 'PATCH',
'class' => 'form',
'files' => true]
) !!}
إن مثيل النموذج marketingImage$ مرتبط بالاستمارة لذلك سيتم تعبئة الحقول بشكل مسبق، ولاحظ أننا قمنا أيضا بتحديد marketingImage->id$ حتى نتمكن من إرسال ذلك إلى تابع المتحكم وتعديل السجل الصحيح.

ولقد قمنا بتعيين قيمة PATCH إلى method وهذه سوف تتغير تلقائيا لأن HTML لا يدعم PATCH، ولقد قمنا بتعيين قيمة true إلى files حتى نتمكن من إرسال الملفات.

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

EditImageRequest
الفرق في عملية التحقق بين create و update هو أنه عندما تقوم بإنشاء صورة سيكون ملف الصورة إلزاميا على عكس التحديث، لذلك قررت لأجل البساطة والوضوح أن نقوم بإنشاء صنف request منفصل باسم EditImageRequest بدلا من وضعه في صنف request واحد.

المشكلة التي واجهتها هي أنني لا أعرف كيف أجعلها شرطية فعلى أي تابع يجب وضع الصنف، لذلك بدأت في التفكير في الأمر، فبدلا من ذلك، يمكنني أن أقوم بتمرير حقل خفي والذي سوف يُعرف الاستمارة وسوف أقوم بوضع فيه عنصر تحكم منطقي (controlling logic)، فإذا كانت الاستمارة استمارة create، فستكون الصور إلزامية، لكنني في النهاية قررت أنه من الأسهل أن أقوم بعمل صنف منفصل.

لذلك قم بتنفيذ هذا الأمر من سطر الأوامر:

php artisan make:request EditImageRequest
ثم قم بتعيين قيمة return true في تابع authorize في ذلك الصنف وعدل تابع rules إلى التالي:

public function rules()
{
return [
'is_active' => 'boolean',
'is_featured' => 'boolean',
'image' => 'mimes:jpeg,jpg,bmp,png | max:1000',
'mobile_image' => 'mimes:jpeg,jpg,bmp,png | max:1000'
];
}
قمنا بالفعل بالتحدث عن تابع rules سابقا ولا داعي لإعادة شرحه هنا.

تابع Update
لنقم الآن بالانتقال إلى تابع update في MarketingImageController، عدله كما يلي:

public function update($id, EditImageRequest $request)
{
$marketingImage = Marketingimage::findOrFail($id);

$marketingImage->is_active = $request->get('is_active');
$marketingImage->is_featured = $request->get('is_featured');

$this->formatCheckboxValue($marketingImage);
$marketingImage->save();

if ( ! empty(Input::file('image'))){

$destinationFolder = '/imgs/marketing/';
$destinationThumbnail = '/imgs/marketing/thumbnails/';

$file = Input::file('image');

$imageName = $marketingImage->image_name;
$extension = $request->file('image')->getClientOriginalExtension();

//create instance of image from temp upload
$image = Image::make($file->getRealPath());

//save image with thumbnail
$image->save(public_path() . $destinationFolder . $imageName . '.' . $extension)
->resize(60, 60)
// ->greyscale()
->save(public_path() . $destinationThumbnail . 'thumb-' . $imageName . '.' . $extension);

}

if ( ! empty(Input::file('mobile_image'))) {

$destinationMobile = '/imgs/marketing/mobile/';
$mobileFile = Input::file('mobile_image');

$mobileImageName = $marketingImage->mobile_image_name;
$mobileExtension = $request->file('mobile_image')->getClientOriginalExtension();

//create instance of image from temp upload
$mobileImage = Image::make($mobileFile->getRealPath());
$mobileImage->save(public_path() . $destinationMobile . $mobileImageName . '.' . $mobileExtension);
}

flash()->success('image edited!');
return view('marketingimage.edit', compact('marketingImage'));
}
دعونا نبدأ بتوقيع التابع:

public function update($id, EditImageRequest $request)
{
سوف ترى أننا نقوم بسحب مثيل من كائن request الصحيح، وقمنا باستخدام findOrFail في نموذج السجل حتى نتمكن من تعيين القيم من مثيل request، وبعد ذلك قمنا بتهيئة (format) قيم خانة الاختيار (checkbox) ثم حفظناها:

$marketingImage = Marketingimage::findOrFail($id);

$marketingImage->is_active = $request->get('is_active');
$marketingImage->is_featured = $request->get('is_featured');

$this->formatCheckboxValue($marketingImage);
$marketingImage->save();
إذا لم تكن الصورة الأولية فارغة، سوف نقوم بالتحديث:

if ( ! empty(Input::file('image'))){

$destinationFolder = '/imgs/marketing/';
$destinationThumbnail = '/imgs/marketing/thumbnails/';

$file = Input::file('image');

$imageName = $marketingImage->image_name;
$extension = $request->file('image')->getClientOriginalExtension();

//create instance of image from temp upload
$image = Image::make($file->getRealPath());

//save image with thumbnail
$image->save(public_path() . $destinationFolder . $imageName . '.' . $extension)
->resize(60, 60)
// ->greyscale()
->save(public_path() . $destinationThumbnail . 'thumb-' . $imageName . '.' . $extension);

}
ثم سنفعل نفس الشيء على صور الهاتف:

if ( ! empty(Input::file('mobile_image'))) {

$destinationMobile = '/imgs/marketing/mobile/';
$mobileFile = Input::file('mobile_image');

$mobileImageName = $marketingImage->mobile_image_name;
$mobileExtension = $request->file('mobile_image')->getClientOriginalExtension();

//create instance of image from temp upload
$mobileImage = Image::make($mobileFile->getRealPath());
$mobileImage->save(public_path() . $destinationMobile . $mobileImageName . '.' . $mobileExtension);
}
ثم قمنا بتنفيذ flash لـ success وبعد ذلك قمنا بالعودة return وفي حالتنا هذه إلى صفحة التعديل edit، لكن يمكنك تغيير العودة إلى أي صفحة تريدها:

flash()->success('image edited!');
return view('marketingimage.edit', compact('marketingImage'));
أرجو ملاحظة أنه إذا كنت تقوم بعمل هذا لشركة تطوير، ربما قد تريد أن تجعل هذه الشيفرة أقوى عن طريق التحقق من أن الملف قد تم إنشاءه، وسوف تتعامل مع الأمر بشكل مختلف إذا لم يعمل لبعض الأسباب، لكن كل هذا خارج نطاق الدرس.

حسنا، الآن آخر خطوة في درسنا.

تابع Destroy
سوف نحتاج إلى كتابة تابع destroy للتعامل مع حذف الصور:

public function destroy($id)
{
$marketingImage = Marketingimage::findOrFail($id);
$thumbPath = $marketingImage->image_path.'thumbnails/';

File::delete(public_path($marketingImage->image_path).
$marketingImage->image_name . '.' .
$marketingImage->image_extension);

File::delete(public_path($marketingImage->mobile_image_path).
$marketingImage->mobile_image_name . '.' .
$marketingImage->mobile_extension);
File::delete(public_path($thumbPath). 'thumb-' .
$marketingImage->image_name . '.' .
$marketingImage->image_extension);

Marketingimage::destroy($id);

flash()->success('image deleted!');

return redirect()->route('marketingimage.index');

}
يمكنك أن ترى أننا قمنا باستخدام findOrFail على id الذي تم استلامه عن طريق التوقيع، ثم استخدمنا مساعدي الملف (File helper) لـ Laravel للحذف، وهكذا تحصلنا مرة أخرى على صياغة جميلة لتبين لنا ما نقوم بفعله.
قمنا أيضا باستخدام تابع ()public_path ووضعنا مكونات الصورة داخل ذلك التوقيع، وبعد ذلك قمنا بتكرار نفس الأمر مع كل نوع من الصور مرتبط مع السجل، ثم استخدمنا تابع destroy لحذف السجل من قاعدة البيانات، وقمنا بتنفيذ flash لتابع success ومن ثم قمنا بإعادة التوجيه إلى صفحة index، وهاقد انتهينا.

الفارس غير متواجد حالياً   اقتباس