اذهب إلى المحتوى

Adnane Kadri

الأعضاء
  • المساهمات

    5129
  • تاريخ الانضمام

  • تاريخ آخر زيارة

  • عدد الأيام التي تصدر بها

    51

كل منشورات العضو Adnane Kadri

  1. يمكن ذلك عن طريق الإستعانة بمفهوم الويب سوكيت . بحيث نقوم : في الواجهة الخلفية للتطبيق بإنشاء قناة أو قنوات بحدث أو أحداث معينة . في الواجهة الأمامية للتطبيق بالإشتراك في هاته القنوات و الإستماع لهاته الأحداث . مثال عن الإستعمال : لما يضغط عمر زر الإعجاب بمنشور أحمد سيتم إرسال طلب HTTP إلى الخادم . سيقوم الخادم بمعالجة طلب عمر و تسجيل الإعجاب , و في نفس الوقت سيقوم بإثارة الحدث المرتبط بالعملية و ليكن NewLikeEvent ضمن القناة AhmedChannel . أحمد مشترك في القناة AhmedChannel و يستمع لأية إثارة لأحداثها , ففي حالة إثارة أية حدث سيقوم بالتقاط البيانات التي تم تمريرها عبره دون تحديث الصفحة . لما يتم إثارة الحدث NewLikeEvent ضمن القناة AhmedChannel ستقوم الواجهة الأمامية لأحمد بالتصرف بناء على البيانات التي تلتقطها عبر هاته القناة في هذا الحدث . كأن تقوم بإظهار إشعار أو تنبيه نصي . قد نحتاج إلى دريفر لمساعدتنا في تمرير البيانات و إنشاء القنوات من مثل Pusher. و للتوضيح أكثر سنقوم بإستعمال Pusher كونه معدا مسبقا للعمل مع لارافل بشكل متسق , و هو ما سنقوم به في هذا المثال .. يمكن عمل الفكرة عن طريق المنطق التالي : تثبيت حزمة خادم Pusher في تطبيق الللارافل : composer require pusher/pusher-php-server إنشاء تطبيق Pusher : نحتاج في هاته الخطوة إلى التسجيل في pusher.com و تسجيل تطبيق جديد . بعد ذلك سنحتاج نسخ معلومات التوثيق و نقوم بوضعها في ملف الإعداد env. كما يلي : PUSHER_APP_ID=PUT_YOUR_PUSHER_ID_HERE PUSHER_APP_KEY=PUT_YOUR_PUSHER_KEY_HERE PUSHER_APP_SECRET=PUT_YOUR_PUSHER_SECRET_HERE PUSHER_APP_CLUSTER=PUT_YOUR_PUSHER_CLUSTER_HERE كما أنه يجب تغيير قيمة BROADCAST_DRIVER: BROADCAST_DRIVER=pusher نقوم بإنشاء حدث معين : php artisan make:event Notify سنلاحظ إضافة ملف Notify.php داخل مجلد events , لنتأكد من أنه سيتم تعديله ليكون على هذا النحو : <?php namespace App\Events; use Illuminate\Broadcasting\Channel; use Illuminate\Queue\SerializesModels; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Broadcasting\PresenceChannel; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; class Notify implements ShouldBroadcast { use Dispatchable, InteractsWithSockets, SerializesModels; public $data; /** * هنا يتم التقاط أية بيانات و تسجيلها ضمن هذا الكائن * * @return void */ public function __construct($passed_data) { $this->data = $passed_data; } /** * هنا يتم تعريف القنوات التي من المفترض أن ينتمي إليها هذا الحدث * * @return \Illuminate\Broadcasting\Channel|array */ public function broadcastOn() { return new Channel('notify-channel'); } } إنشاء متحكم يختص بالعملية : php artisan make:controller NotificationController ثم لنتأكد من وضع المحتوى التالي به : <?php namespace App\Http\Controllers; use Illuminate\Http\Request; class NotificationController extends Controller { public function notify() { // تحضير مصفوفة بيانات لتمريرها $data['message'] = 'قم بتمرير هاته الرسالة'; // Notify إثارة الحدث event(new App\Events\Norify($data)); } } سيكون علينا تعريف مسارين , مسار لإستهداف تابع المتحكم NotificationController و اخر لعرض الصفحة notification.blade.php : //web.php Route::get('notify','NotificationController@notify'); Route::view('/notification', 'notification'); ثم بملف ما بالواجهة الأمامية سيكون علينا فقط : الإشتراك في هاته القناة + الإستماع لأحداث هاته القناة : <!-- notification.blade.php --> <!DOCTYPE html> <head> <title>مثال عن إشعار</title> <script src="https://js.pusher.com/4.1/pusher.min.js"></script> <script> // الإشتراك ضمن نفس تطبيق البوشر var pusher = new Pusher('{{env("MIX_PUSHER_APP_KEY")}}', { cluster: '{{env("PUSHER_APP_CLUSTER")}}', encrypted: true }); // الاشتراك في نفس القناة var channel = pusher.subscribe('notify-channel'); // Notify الاستماع للحدث channel.bind('App\\Events\\Notify', function(data) { // إن تم اثارة الحدث قم بعرض البيانات alert(data.message); }); </script> </head> بدون تحديث الصفحة سيكون علينا التصفح إلى المسار notify/ و سنلاحظ ظهور التنبيه في مسار notifications/ . المسار الأول يمثل الطلب الذي أرسله عمر , و المسار الثاني يمثل صفحة عرض الاشعارات بالنسبة لأحمد . و بالطبع فإن هذا هو الشكل الأبسط للعملية , يمكن تطوير العملية كأن نقوم بتخصيص طريقة العرض في قائمة إشعارات منظمة و منسدلة مع ظهور إشعار جانبي في كل إثارة للحدث , كما يمكن تخصيص قنوات خاصة بكل مستخدم منفرد أو نقوم بتمرير بيانات أخرى و تطبيق العديد من الأفكار عليها .
  2. تذكر جيدا ما أشرت إليه سابقا : لكن هذا لا يمنع من تقديم شيفرة كمثال متكامل . لاحظ المثال التالي : 1. نقوم بإنشاء بنية الملفات التالية : 2. بملف index.html سيكون علينا تعريف بنية مشابهة للتالي , كما أنه يجب علينا تحضير طلب الأجاكس و إرساله : <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>مثال عن رفع ملف</title> </head> <body> <section> <div> <label>قم بتحديد ملف</label> <input type="file" id="my_file"> </div> <div> <button type="button" id="submit_file_form">رفع الملف</button> </div> </section> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script> $(document).ready(function(){ // 1 - إضافة حدث عن تقديم الاستمارة و رفع الملف $("#submit_file_form").click(function(){ // 2 - FormData تحضير نموذج عن الكائن var fd = new FormData(); // 3 - تحديد الملف var files = $('#my_file')[0].files; // 4 - التحقق من تحميل ملف if(files.length > 0 ){ // 5 - إضافة الملف إلى نموذج الكائن fd.append('file',files[0]); // 6 - تحضير طلب الاجاكس و إرسال نموذج الكائن $.ajax({ url: 'file_uploader.php', type: 'POST', data: fd, contentType: false, processData: false, success: function(response){ if(response){ alert('تم رفع الملف'); }else{ alert('لم يتم رفع الملف'); } }, }); }else{ alert("قم بتحديد ملف لرفعه."); } }); }); </script> </body> </html> 3. بملف file_uploader.php سيكون علينا إستقبال الطلب الحامل للملف و معالجته بشكل طبيعي تماما على نحو مشابه : <?php if(isset($_FILES['file']['name'])){ /* جلب اسم الملف */ $filename = $_FILES['file']['name']; /* تحضير وجهة تخزين للملف */ $location = "uploaded/".$filename; /* تحضير متغير يحمل حالة الرد */ $response = false; /* تخزين الملف */ $file_uploaded = move_uploaded_file($_FILES['file']['tmp_name'],$location); /* تغيير الحالة ان تم تخزين الملف بنجاح */ if($file_uploaded){ $response = true; } /* إعادة قيمة بوليانية في الرد */ return $response; } return false;
  3. بداية يجب عليك معاملة أية مشاكل و صعوبات تظهر معك كأشياء طبيعية في المجال و من جانب اخر هي إمتحانات لك و لا يجب عليك التفكير في التوقف عن ما أقدمت عليه بسبب أشياء تواجهها لأنه , و بهاته الطريقة , سيكون لديك الكثير لتتوقف من أجله . كما أنه يجب عليك الإستفادة من الإجابات التي طرحها عليك الزملاء في أسئلتك السابقة : و بشكل عام فإنه يجب عليك فهم منطق هاته العمليات لا التوغل في مثال عن كود واحد و إعتباره كمعيار أو دستور للعملية . فمثلا : التشفير و فك التشفير : للتشفير : سيكون عليك تشفير سلسلة نصية معينة قبل إستعمالها , ولقراءته سنحتاج فك هذا التشفير . مثال عن الإستعمال : تشفير كلمة المرور قبل إدخالها في قاعدة البيانات في عملية تسجيل المستخدم - أ - , ثم فك تشفيرها للتحقق من مطابقتها لكلمة مرور قام المستخدم - أ - بإدخالها في عملية تسجيل دخوله لاحقا. أي : أننا نحتاج دالة تشفير و دالة فك تشفير . أو دالة و دالة معاكسة لها لعمل الفكرة , و قد تكتب خوارزميتك الخاصة للتشفير وفك التشفير أنت ذاتك فالعملية ليست حكرا على أحد لكن يقترح إستعمال المكتبات و الدوال المسبق تعريفها لأمان و سرعة أكثر . و دوال التشفير كثيرة من PHP نذكر من بينها : openssl_encrypt و الدالة المعاكسة لها : openssl_decrypt : توثيق . أمثلة : <?php $example = '@123456'; # السلسلة النصية المراد تشفيرها $cipher_algo = 'AES-128-CTR'; # خوارزمية التشفير $encryption_key = 'HsoubAcademy'; # مفتاح التشفير $options = 0; # خيارات التشفير $encryption_iv = 1234567891011121; # يعبر عن بادئة التشفير $encrypted_example = openssl_encrypt($example , $cipher_algo , $encryption_key , $options , $encryption_iv); echo $encrypted_example; // النتيجة : nLTaaXcr1A== $decrypted_example = openssl_decrypt($encrypted_example , $cipher_algo , $encryption_key , $options , $encryption_iv); echo $decrypted_example; // النتيجة : @123456 base64_encode و الدالة المعاكسة لها : base64_decode . توثيق . أمثلة : <?php $example = '@123456'; # السلسلة النصية المراد تشفيرها $encrypted_example = base64_encode($example); echo $encrypted_example; // النتيجة : QDEyMzQ1Ng== $decrypted_example = base64_decode($encrypted_example); echo $decrypted_example; // النتيجة : @123456 bin2hex و الدالة المعاكسة لها : hex2bin . توثيق و أمثلة . و غيرها الكثير .. كما يمكنك القراءة عن الموضوع أكثر هنا : رفع الصور و الملفات عن طريق الأجاكس : جافاسكربت تجعل ذلك بسيطا عن طريق إستعمال كائن يختص بنماذج البيانات و هو الكائن FormData , و لإرسال صورة أو ملف ما علينا إلا : إرسال نموذج من الكائن FormData يحمل الملف. لاحظ جيدا منطق الخطوات بالمثال التالي : $(document).ready(function(){ // 1 - إضافة حدث عن تقديم الاستمارة و رفع الملف $("#submit_file_form").click(function(){ // 2 - FormData تحضير نموذج عن الكائن var fd = new FormData(); // 3 - تحديد الملف var files = $('#my_file')[0].files; // 4 - التحقق من تحميل ملف if(files.length > 0 ){ // 5 - إضافة الملف إلى نموذج الكائن fd.append('file',files[0]); // 6 - تحضير طلب الاجاكس و إرسال نموذج الكائن $.ajax({ url: 'path/to/endpoint', type: 'POST', data: fd, contentType: false, processData: false, success: function(response){ if(response){ alert('تم رفع الملف'); }else{ alert('لم يتم رفع الملف'); } }, }); }else{ alert("قم بتحديد ملف لرفعه."); } }); }); معيارية MVC : و هي إختصار لـ Model , View , Controller و ببساطة شديدة هو نموذج معيارية Design Pattern يقضي بعزل منطق العمل عن واجهة المستخدم بهدف تحقيق إستقلالية كل منهما و تسهيل التعامل معهما في التطوير , الفحص و الصيانة . و يحقق بذلك أحد مبادئ التصميم المشهورة في علوم الحاسب : مبدأ فصل الإهتمامات separation of concerns (SoC). تقوم معيارية MVC بتقسيم التطبيق إلى ثلاث أجزاء : النموذج Model : يعبر عن المكون المركزي و الرئيسي للنمط Pattern . و يمثل بنية البيانات الخاصة بالتطبيق ، فعن طريقه تتم مباشرة إدارة بيانات وقواعد التطبيق . العرض View : و هي أي تمثيل للمعلومات مثل صفحة ويب , جداول أو نصوص . و تمثل ها هنا واجهة المستخدم . المتحكم Controller : و يقوم بإستقبال المدخلات و التحكم فيها و التحقق من إمكانية تمريرها للنموذج Model حتى يتصرف بناء عليها . هذا الفصل بين المكونات الثلاث هاته يجعلها تتفاعل فيما بينها بهاته الطريقة : النموذج Model مسؤول عن إدارة بيانات التطبيق . بحيث يتلقى مدخلات المستخدم من وحدة التحكم Controller . تستجيب وحدة التحكم Controller لإدخال المستخدم , وتتحقق من سلامتها ثم تقوم بتمرير مدخل المستخدم إلى النموذج Model , أو تقوم إستجابة لمدخل المستخدم بعرض View بتنسيق معين . و بشكل عام فإن أي فصل لهاته الثلاث مكونات , اهتمامات و وظائف هي معيارية تصميم MVC مثلها مثل أي معيارية أخرى , يتطلب التعمق فيها فهما أوسع و أعمق لأنماط ومعياريات التصميم Design Patterns . إن لم يكن لك إطلاع مسبق عنها فيمكنك أخذ فكرة عن الموضوع هنا و أيضا هنا . كما يمكنك الإطلاع عن الكود المصدري لهاته النماذج المصغرة لمعيارية MVC هنا و هنا . و بالطبع فإنه يمكنك التدرب على فصل هاته المكونات الثلاث لتطبيق الفكرة عمليا .
  4. الكود مثال عن رفع ملف إلى الواجهة الخلفية , مكتوب بالجيكوري . يمكنك الإشارة إلى النقطة الغير مفهومة و سيتم شرحها بإسهاب أكثر .
  5. يمكنك إرسال نموذج عن الكائن FormData يتضمن الملف , بإستعمال POST عبر طلب الأجاكس . سيتبع الكود منطقا مشابها : $(document).ready(function(){ // إضافة حدث عن تقديم الاستمارة و رفع الملف $("#submit_file_form").click(function(){ // FormData تحضير نموذج عن الكائن var fd = new FormData(); // تحديد الملف var files = $('#my_file')[0].files; // التحقق من تحميل ملف if(files.length > 0 ){ // إضافة الملف إلى نموذج الكائن fd.append('file',files[0]); // تحضير طلب الاجاكس و إرسال نموذج الكائن $.ajax({ url: 'path/to/endpoint', type: 'POST', data: fd, contentType: false, processData: false, success: function(response){ if(response != 0){ alert('تم رفع الملف'); }else{ alert('لم يتم رفع الملف'); } }, }); }else{ alert("قم بتحديد ملف لرفعه."); } }); });
  6. لا أظن أن الفكرة ممكنة عن طريق تابع ضمن الكائن Blueprint , و لكن يمكنك إضافة أي قيد عن طريق مفهوم المعدلات Mutators قبل أي إدراج بقواعد البيانات . نقوم بتعريف المعدل setSalaryAttribute بداخل ملف النموذج المستهدف على هذا النحو : class YourModel extends Model{ public function setSalaryAttribute($value){ $this->attributes['salary'] = $value < 500.00 ? $value : 500.00; } } في هذا المثال سيقوم بالتحقق , كل مرة نحاول فيها إدراج أو تحديث القيمة salary , إن كانت القيمة salary أقل من 500.00 و إلا فسيضع 500.00 نفسها .
  7. قد تكون المشكلة بسبب تداخل النسخ أو تكرارها , لاحظ تثبيتك لأكثر من حزمة في نفس الأمر : npm install tailwindcss@npm:@tailwindcss/postcss7-compat @tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ لذلك تأكد أولا أن تقوم بإزالتها , إما عن طريق الأمر : npm uninstall tailwindcss postcss autoprefixer أو إزالة الأسطر الخاصة بالحزم المعنية من ملف package.json ثم تنفيذ الأمر : npm install ثم الان نأتي لتثبيت tailwind على نحو صحيح : يكون أمر تثبيت الحزمة و الحزم المطلوبة على هذا النحو : npm install -D tailwindcss@latest postcss@latest autoprefixer@latest قد لا تحتاج الخطوتين التاليتين كونك تقوم بإنشاء ملف إعداد tailwind على نحو صحيح . 2. قم بإنشاء ملف إعداد tailwind عن طريق طباعة الأمر : npx tailwindcss init 3. قم بهيئة Tailwind لإزالة التنسيقات الغير المستخدمة في بيئة الإنتاج : // tailwind.config.js module.exports = { purge: [], purge: [ './resources/**/*.blade.php', './resources/**/*.js', './resources/**/*.vue', ], darkMode: false, // or 'media' or 'class' theme: { extend: {}, }, variants: { extend: {}, }, plugins: [], } 4. إعداد tailwind عن طريق webpack : mix.js("resources/js/app.js", "public/js") .postCss("resources/css/app.css", "public/css", [ require("tailwindcss"), ]); الان يمكنك استعمال tailwind و تضمينه في ملفات css المعنية . و يمكنك البناء عن طريق تشغيل الأمر : npm run build
  8. بداية يجب عليك إنشاء الحقل و تعيينه كمفتاح أولي بملف التهجير الخاص بالجدول المعني على هذا النحو : Schema::create('users', function (Blueprint $table) { $table->uuid('id')->unique()->primary(); $table->string('name'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); } لاحظ أن العمود id لا يملك أي قيمة افتراضية و لذلك يجب تعيين ذلك مع كل طلب : App\Models\User::create([ 'id' => $uuid, 'name'=> 'Hsoub', 'email'=> 'Academy', 'password'=> Illuminate\Support\Facades\Hash::make('HsoubAcademy'), ]); و لإختصار الأمر و توليد معرف فريد مع كل استعلام إدراج لصف جديد نحتاج الاستماع للحدث creating ضمن النموذج المستهدف ,وليكن App\Models\User/php , ضمن الثابت boot على هذا النحو : public static function boot() { parent::boot(); self::creating(function($model){ $model->uuid = $uuid; }); } و لتعيين قيمة للمتغير uuid يمكنك إستعمال المساعد Str في لارافل مثل ما شرح المدربان أو يمكنك إستعمال أحد هاته الحزم : webpatser/laravel-uuid أو ramsey/uuid مثلا . كما يمكنك إنشاء مساعدك الخاص الذي يقوم بتوليد معرفات فريدة وفق منطق معين .
  9. يحدث المشكل أحيانا بسبب محاولة فك تشفير نص إما غير مشفر من الأساس أو قد فك تشفيره قبل ذلك . مثال : إن كنت تستخدم مسترجع أو معدل Mutator على خاصية كلمة المرور في ملف النموذج : public function getPasswordAttribute($value) { return Crypt::decryptString($value); } ثم تقوم بقراءتها على هذا النحو : $pass = Crypt::decryptString($user->password); سيؤدي هذا إلى ظهور المشكل لأننا نحاول فك التشفير مرتين , و بالتالي و لحل المشكل تأكد أنك لا تقوم بذلك أو بأي عملية بنفس المنطق . إن لم يحل هذا مشكلتك يرجى إرفاق الكود المسبب للمشكلة حتى يتم النظر فيه بشكل أكثر دقة . يمكنك القراءة عن إرشادات طرح الأسئلة .
  10. ما قصدك بالكود الأصلي للدالة ؟ و في أي لغة تريدين ذلك ؟
  11. يظهر الخطأ في القراءة من الإستعلام في عناصر التوريد و بالضبط في هذا السطر : <input type="text" class="form-control contact-name" placeholder="الاسم" value="<?php echo $item['supplying_items.name']; ?>" disabled > وهذا لأن طريقة القراءة في كود PHP تختلف عن طريقة القراءة في إستعلام SQL . في PHP لا يوجد أي عنصر بالفهرس supplying_items.name من الناتج و لكن يوجد مصفوفة بإسم supplying_items تحوي عنصر بالفهرس name . أي أن القراءة تكون على هذا النحو : <input type="text" class="form-control contact-name" placeholder="الاسم" value="<?php echo $item['supplying_items']['name']; ?>" disabled > أو : <input type="text" class="form-control contact-name" placeholder="الاسم" value="<?php echo $item['name']; ?>" disabled > إن كنت تقوم بالتكرار حول عناصر التوريد supplying_items لأن الدور الخاص بك غير واضح . إن لم يقم هذا بحل مشكلتك يرجى إرفاق كامل الكود .
  12. بالطبع فإنه يمكنك معاملة إستعلام إدراج و إنشاء الجداول كأي إستعلام CRUD اخر مثلا. مثال عملي : <?php /* mysqli تحضير كائن جديد*/ $mysqli = new mysqli("localhost", "root", "", "demo"); // التحقق من الاتصال if($mysqli === false){ die("حدث خطأ في الاتصال " . $mysqli->connect_error); } // جلب مجموعة الاستعلامات من ملف قواعد البيانات $sql = file_get_contents('data.sql'); if($mysqli->query($sql) === true){ echo "تم إنشاء الجداول بقواعد البيانات بنجاح"; } else{ echo "حدث خطأ" . $mysqli->error; } // إغلاق الاتصال $mysqli->close(); ?> قد تحتاج أيضا إضافة شرط الوجود في استعلام الـ sql على هذا النحو : CREATE TABLE IF NOT EXISTS `users` ( `user_id` INT(8) NOT NULL AUTO_INCREMENT, `user_name` VARCHAR (30) NOT NULL, `user_pass` VARCHAR (255) NOT NULL, `user_email` VARCHAR (255) NOT NULL, `user_date` DATETIME NOT NULL, `user_level` INT(8) NOT NULL, UNIQUE INDEX `user_name_unique` (`user_name`), PRIMARY KEY (`user_id`) ) Engine=InnoDB;
  13. يمكنك ذلك عن طريق الإستعانة بطلبات Ajax . بحيث ستحتاج إلى : إرسال طلبات إلى نقاط وصول معينة عن طريق XmlHttpRequest . القراءة من الطلب . تكرار إنشاء الصفوف كذا مرة بحسب البيانات التي تم جلبها و عرضها على الصفحة عن طريق الـ DOM. مثال عملي : ليكن لدينا الجدول التالي : <table id="myTable"> <tr> <th>الاسم</th> <th>اللقب</th> </tr> </table> نقوم بتحضير طلب Ajax لجلب الطلبة مثلا على هذا النحو : var xhttp = new XMLHttpRequest(); // نقوم بتعريف كائن طلب جديد xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var response = JSON.parse(xhttp.responseText); // جلب البيانات response.forEach(element => createRowFromData(element)); // إنشاء صف لكل عنصر من المصفوفة } }; xhttp.open("GET", "path/to/get/students", true); // فتح الطلب xhttp.send(); // إرسال الطلب function createRowFromData(data) { var table = document.getElementById("myTable"), tr = document.createElement("tr"), td = document.createElement("td"), tdText = document.createTextNode(data.name), td2 = document.createElement("td"), td2Text = document.createTextNode(data.family_name); td.appendChild(tdText); td2.appendChild(td2Text); tr.appendChild(td) .appendChild(td2); table.appendChild(tr); }
  14. أظن أن قصدك أن يكون الناتج كالتالي: <ul class="sec-1"> <li>res 1</li> <li>res 2</li> <li>res 3</li> <li>res 4</li> </ul> <ul class="sec-2"> <li>res 5</li> <li>res 6</li> <li>res 7</li> <li>res 8</li> </ul> في لارافيل , يمكنك تقسيم نتائج الإستعلام إلى أكثر من مجموعة عن طريق الإستعانة بمتغيرات الدور التي تكون معرفة ضمن كل تكرار من الدور foreach أو عن طريق الإستعانة بمفهوم المجموعات collections . فمثلا لتقسيم العناصر إلى مجموعات بـ 5 عناصر عن طريق الإستعانة بمتغيرات الدور : @foreach($items as $item) @if($loop->first or $loop->iteration % 5 == 0) <ul> @endif <li> res {{ $loop->iteration }} </li> @if($loop->last == true or $loop->iteration % 5 == 0) </ul> @endif @endforeach حيث أننا نقوم بفتح وسم جديد كل مرة يكون فيها التكرار جديدا أو قابلا للقسمة على 5 . و ليكن في العلم أن الخاصية first تعيد إما true أو false بحسب ترتيب الدور في حين أن الخاصية iteration تمثل التكرار الحالي , و نفس الشيء بالنسبة لغلق الوسم و المتغير last . لكن ,و كطريقة أفضل , يمكنك الإستعانة بالتابع chunk لتشكيل كل مرة مجموعة مستقلة في كل دورة عن طريق : @foreach($items->chunk(5) as $chunk) <ul> @foreach($chunk as $item) <li> res {{ $loop->iteration }} </li> @endforeach </ul> @endforeach بحيث أن هذا سيقوم بتشكيل مجموعات ذات خمسة عناصر , و سيكون من السهل التكرار داخلها أو القراءة منها . طبعا يمكنك بنفس المنطق تطويع العملية بحسب بنية الـ HTML لديك .
  15. هل يمكنك شرح المطلوب أكثر حتى يمكن مساعدتك بشكل أفضل ؟ يمكنك القراءة أكثر عن كيف أحصل على جواب لسؤالي .
  16. يمكنك فعل هذا عن طريق مفهومي معمل النماذج Model Factories و بذر البيانات Database seeding . ستحتاج إنشاء معمل نموذج جديد عن طريق الأمر : php artisan make:factory TaskFactory -m Task ثم نحتاج لإستعمال مكتبة faker لتوليد بيانات حقول تلقائية على هذا النحو في ملف TaskFactory.php ضمن التابع definition : return [ 'name' => $this->faker->name, 'email' => $this->faker->unique()->email, 'contact_number' => $this->faker->phoneNumber, ]; سنحتاج أيضا إلى إضافة المعمل إلى ملف البذر DatabaseSeeder.php إلى التابع run : App\Models\Task::factory(10)->create(); ثم أخيرا يمكننا تشغيل أمر البذر : php artisan db:seed كما يمكن تشغيله بعد أمر التهجير على هذا النحو : php artisan migrate:fresh --seed
  17. بداية تأكد أنك تقوم بتضمين الواجهة File في الملف قبل إستعماله . <?php namespace App\Http\Controllers; use Illuminate\Support\Facades\File; // أو use File; كما يمكنك تشغيل وضع الـ Debug و ضبطه كـ ON حتى يتم تشخيص الأخطاء و تسجيلها بشكل أفضل . في ملف متغيرات البيئة env. قم بإعطاء القيمة true عوضا عن false للمتغير APP_DEBUG : APP_DEBUG=true قد تحتاج كخطوة إضافية لمحو الملفات المؤقتة : php artisan cache:clear الان قم بالتصفح إلى مسار الملف و سيظهر لك الخطأ بشكل أفضل و أكثر تفصيلا . إن لم يقم تضمين الواجهة بحل مشكلتك يمكنك إرفاق صورة بالخطأ الذي يظهر معك و سيتم تشخيص المشكلة بشكل أوسع .
  18. طبعا سيتطلب هذا إنشاء خوارزمية بحث تقوم بفلترة نتائج البحث و إظهار الأقرب كتابة كنتائج تظهر . مثال عملي : // قم بجلب أسماء كل المدن و تخزينها في مصفوفة const cities = [ 'Abudabi', 'Algiers', 'Oran', 'New York', 'Los Angelos', 'Las Vigas' ]; // سيكون عليك الوصول إلى نص الحقل و استخراجه لإستعماله ككلمة مفتاحية const keyWord = 'b'; // فلترة النتائج بحسب عملية البحث const filteredCities = cities.filter( /* فلترة عناصر المصفوفة بحسب الحرف الأول يشترط الترتيب */ city => city.trim() // إزالة الفراغات .toLowerCase() .startsWith(keyWord.trim().toLowerCase()) /* لفلترة النتائح بحسب أي حرف ضمن الكلمة لا يشترط الترتيب city => city.trim() .toLowerCase() .includes(keyWord.trim().toLowerCase()) */ ); console.log(filteredCities);
  19. في الحقيقة فإن الشخص قد قام بالطريقتين معا ، فتويتر لا تعطيك أي بيانات عبر واجهة تطبيقها البرمجية إلا بعد تسجيلك عندهم كمطور . و أخيرا يمكنك كتابة الكود وفق المنطق الموصوف في التعليق السابق .
  20. طبعا سيكون عليك إرسال طلب GET إلى نقطة الوصول هاته : GET https://api.twitter.com/1.1/followers/ids.json?screen_name=TwitterScreenUserName ستقوم بإستقبال مصفوفة JSON بمجموعة معرفات المستخدمين المتابعين لهذا المستخدم . سيكون عليك عد عناصر مجموعة المعرفات و عرضها . يمكنك أيضا تمرير هاته البارمترات عبر الطلب : user_id : معرّف المستخدم المراد إرجاع النتائج له. screen_name : اسم الشاشة للمستخدم المراد إرجاع النتائج له. cursor : يمكنك تخصيص تقسيم قائمة الاتصالات إلى صفحات لا تزيد عن 5000 معرف في المرة الواحدة. لا يمكن ضمان أن يكون عدد المعرفات التي تم إرجاعها 5000 معرف حيث يتم تصفية المستخدمين المعلقين بعد الاستعلام عن الاتصالات. إذا لم يتم توفير مؤشر ، فسيتم افتراض القيمة -1 ، وهي "الصفحة" الأولى. count : يحدد عدد المعرفات التي تحاول استرجاعها بحد أقصى 5000 لكل طلب مميز. طبعا ,مثل ما شرح المدرب @Sam Ahw, كل هذا يحتاج منك حساب مطور في تويتر حتى تقوم بإرسال بيانات التوثيق مع كل طلب .
  21. كل الأمور تعمل بشكل طبيعي و صحيح غير أن العملية غير منطقية و غير حسنة من ناحية تجربة المستخدم بعض الشيء . فالعملية ليست عملية بحث و إنما فلترة بحسب المدينة لذلك لا يجدر بك استخدام حقول الإدخال من النوع نص . خطوات عملية : عوضا عن البحث عن اسم المدينة و إظهار مربع بحث عن اسم المدينة قم بعمل قائمة منسدلة بخيارات المدن المتوفرة , فالمدن محدودة من جهة . و عملية البحث ليست عليها و إنما هو فلترة بحسب المدينة . بعد ذلك يمكنك ربط التغير بقيم القائمة المنسدلة بحادثة تحميل حيوانات جديدة تخص تلك المدينة دون غيرها عوضا عن تحميلها كلها أو تحميل تلك الخاصة بـ AbuDhabi مثلما تقوم بفعله . طبعا تحتاج إخفاء كل مربعات الحيوانات القديمة كل مرة تقوم بعملية بحث و فلترة . طبعا هذا هو منطق العملية موصوفة فقط و تحتاج تحويل العملية إلى كود عملي يمكنك من عمل الفكرة بشكل محترف .
  22. طبعا فإن لارافل توفر الكثير من دريفرات التخزين المؤقت و كل منها جيد و ممتاز في أداء مهمته في بيئة ما أو حسب شروط ما. فمثلا : لحل المشاكل و الـ Debuging ستكون الـ array أفضل خيار لك . لتوفير تخزين بشكل دائم سيكون الـ file أفضل خيار . لتجربة التطبيق و الـ Testing لن يكون هناك أفضل من قاعدة البيانات (MySql , SQLite) . لكن إذا كان لديك خادم مخصص و تريد إختيار درايفر تخزين مؤقت لتطبيق اللارافل لديك على بيئة الإنتاج ، عليك بالتأكيد اختيار memcached أو redis . فكل منها يمتلك نظام تخزين مؤقت مجاني ومفتوح المصدر و عالي الأداء و لن يكون عليك القلق بشأن ضغط الملفات على الخادم أو إنهيار الخادم . يمكنك القراءة عن الكثير من المقارنات بينهما من حيث نمط و حجم البيانات , الثبات , الأداء , توثيق النظام و غيرها من العوامل . لكن يبقى كل منهما يحقق الغرض بأداء و جودة عاليتين و لو وجد تفاوت بينهما فسيكون تفاوتا طفيفا لن يؤثر عليك. عن نفسي أفضل استخدام redis نظرًا لقدرته على الاحتفاظ بحجم كبير من البيانات ، لكن يبقى إستعمال أي من أحدهما حلاً جيدًا جدا . أما عن فكرة تخزين الملفات المؤقتة في ذاكرة المستخدم أو حاسب المتصفح فالمتصفحات تكفيك تخزين بعض ملفات الواجهة الأمامية و لا أظن أنه توجد طريقة أصلا لإعتمادها كدريفر تخزين.
  23. نعم يمكنك ذلك عن طريق أي أمر تهجير عادي مرفقا بمسار الملف . يمكنك بتخصيص مسار الملف عن طريق استعمال الخاصية path . سيكون الأمر على هذا النحو : php artisan migrate --path=/database/migrations/migration_file_name.php
  24. هل يمكنك إرفاق ملف الإتصال بقاعدة البيانات حتى نستطيع مساعدتك بشكل أفضل ؟
  25. كل المقترح مجاني , يمكنك طبعا اشتراء لوحة تحكم بمواصفات تريدها من codecanyon . لا يوجد الأفضل و إنما الأنسب لحاجتك و مشروعك . فقد تختصر عليك لوحة SB admin الوقت و تنزع عنك حرية التطوير و التعديل بشكل واسع غير محدود و هكذا . أما عن نفسي فأحب إستعمال backpack for laravel فهي مرنة جدا و سهلة للتطوير و التعديل , و الأكثر اختصارا للوقت في كثير من الحالات . لكن أفضل عليها الحرية الكاملة في التطوير و التعديل عن طريق بناء لوحتك الخاصة .
×
×
  • أضف...