في أي موقع إلكتروني، هناك بعض الإعدادات التي يجب أن يتحكم بها صاحب الموقع ( العميل )، والتي تكون مشتركه في جميع الصفحات مثل إسم الموقع <title> و <description> وغيرها من الإعدادات، فمن غير المعقول أنه عند كل عملية تنقل بين الصفحات أن يتم جلب البيانات من قاعدة البيانات، الحل هنا يكمن في حفظ هذه البيانات في قاعدة البيانات ، مع إستخدام caching.
في هذا المثال، سنرى كيف يمكن عمل ذلك، دون إستخدام أي حزم packages.
php artisan make:model Setting -mcs
في ملف migration سيتم إضافة الحقلين key و value، لكن يجب أن يكون key = unique وأن لا يكون null، وذلك لأنه به سيتم تخزين المفتاتيح مثل site_name, site_description و بـ الـ value سيتم تخزين القيمة.
public function up(): void { Schema::create('settings', function (Blueprint $table) { $table->id(); $table->string('key')->unique(); $table->string('value')->nullable(); $table->timestamps(); }); }
الأن نحتاج في Setting Model أن يتم إضافة key, value إلى fillable.
class Setting extends Model { use HasFactory; protected $fillable = ['key', 'value']; }
الأن تحضير البيانات في ملف SettingSeeder
class SettingSeeder extends Seeder { public function run(): void { $settings = [ ['key' => 'site_name', 'value' => 'Palestine'], ['key' => 'description', 'value' => 'Palestine Will be free.'], ['key' => 'keyword', 'value' => 'palestine, aqsa, jerusalem, occupation'], ['key' => 'admin_email', 'value' => 'admin@admin.com'], ['key' => 'posts_per_page', 'value' => 10], ['key' => 'users_can_register', 'value' => true], ]; Setting::insert($settings); } }
الأن إستدعاء الكلاس SettingSeeder في الكلاس DatabaseSeeder
class DatabaseSeeder extends Seeder { public function run(): void { $this->call([ SettingSeeder::class, ]); } }
وأخيرا، تنفيذ الأمر migrate --seed حتى يتم إنشاء الجدول settings وإدخال البيانات في هذا الجدول.
php artisan migrate --seed
بداية سيتم تحضير routes في الملف web.php ومن ثم تحضير الدوال edit و update في Setting Controller، ومن ثم تحضير ملف settings.blade.php
تحضير الـ route في ملف routes/web.php
use App\Http\Controllers\SettingsController; Route::middleware('auth')->group(function () { Route::get('/settings', [SettingsController::class, 'edit'])->name('settings.edit'); Route::post('/settings', [SettingsController::class, 'update'])->name('settings.update'); });
class SettingController extends Controller { public function edit() { return view('settings', [ 'settings' => Setting::get(['key', 'value']) ]); } public function update(Request $request) { $data = $request->except('_token'); foreach ($data as $key => $value) { Setting::where('key', $key)->update(['value' => $value]); } return to_route('settings.edit') ->withStatus('Settings updated successfully.'); } }
إنشاء ملف serrings.blade.php من أجل عرض البيانات وكذلك فورم التعديل.
<div class="container"> @if(session('status')) <div class="alert alert-info">{{ session('status') }}</div> @endif <form method="post" action="{{ route('settings.update') }}"> @csrf @foreach($settings as $setting) <div class="form-floating mb-3"> <input type="text" class="form-control" value="{{ $setting->value }}" name="{{ $setting->key }}" id="{{ $setting->key }}"> <label for="{{ $setting->key }}">{{ $setting->key }}</label> </div> @endforeach <button class="btn btn-success"> Update Settings </button> </form> </div>
وبذلك نحصل على هذا الشكل
وبذلك نكون قد إنتهينا من عرض الحقول وإمكانية التعديل عليها.
لجلب قيمة key معين من قاعدة البيانات
Setting::where('key', 'site_name')->first();
لكن هذه الجمله يتم تنفيذها وإنشاء DB query في كل مره، ولجلب جميع البيانات مره واحده وعمل cach لها.
يمكن لنا القيام بذلك من خلال الذهاب للدالة boot في الكلاس AppServiceProvider
app/Providers/AppServiceProvider.php
public function boot(): void { $this->app->bind('settings', function () { return Cache::rememberForever('settings', function () { return Setting::pluck('value', 'key'); }); }); }
الأن يمكن لنا عرض البيانات بالشكل التالي
app('settings')['site_name']; <title>{{ app('settings')['site_name'] }}</title>
لكن الأن لو قام صاحب الموقع بالتعديل على site_name, site_keyword فإنه بالفعل سيتم تعديل ذلك في قاعدة البيانات، لكن في العرض سيتم عرض البيانات القديمه، وذلك لأنه تم عمل cache لها، والحل هنا يكون بإستخدام Cache::forget.
public function update(Request $request) { $data = $request->except('_token'); foreach ($data as $key => $value) { Setting::where('key', $key)->update(['value' => $value]); } Cache::forget('settings'); return to_route('settings.edit') ->withStatus('Settings updated successfully.'); }
جلب البيانات من الـ container بشكل مباشر غير مريح
app('settings')['site_name']
لذلك يمكن لنا إنشاء helper حيث نقوم بإنشاء folder بإسم helpers بداخل المجلد app وبداخل المجلد helpers ننشئ الدالة settings.
app/Helpers/settings.php
وبداخل هذه الداله
<?php if (! function_exists('settings')) { function settings(?string $key = null, $default = null) { if (is_null($key)) { return app('settings'); } return app('settings')->get($key, $default); } } ?>
ومن ثم إضافة مسار هذه الملف إلى autoload helpers في الملف composer.json
"autoload": { "psr-4": { "App\\": "app/", "Database\\Factories\\": "database/factories/", "Database\\Seeders\\": "database/seeders/" }, "files": [ "app/Helpers/settings.php" ] },
ومن ثم تنفيذ الأمر
composer dump-autoload
الأن يمكن لنا الوصول إلى أي value بشكل مباشر
{{ settings('site_name') }} <title>{{ settings('site_name') }}</title>
إذا أردنا إضافة المزيد من الحقول إلى ملف migrations، يجب أن لا ننسى مسح الكاش، وذلك من خلال إضافة cache::forget
return new class extends Migration { public function up(): void { $data = [ ['key' => 'start_of_week', 'value' => 1], ['key' => 'show_testimonials', 'value' => true], ['key' => 'allow_comments', 'value' => false], ]; Setting::insert($data); Cache::forget('settings'); } };
5- حزم Packages للتعامل مع إعدادات الموقع
يوجد مجموعه من الحزم التي تساعدنا في إعدادات الموقع، ومنها:-
https://github.com/spatie/valuestore
https://github.com/qcod/laravel-settings
هل ترغبون في عمل شرح لهذه الحزم.
إقرأ أيضا:
كيفية عمل CACHE في LARAVEL لجمل الإستعلام في لارافيل أسرع وتحسين أداء الموقع
شكرا على هذه المقالة المفيدة
ممتاز جدااا
زائر
مشكور على هذا المقال الرائع