-
المساهمات
5196 -
تاريخ الانضمام
-
تاريخ آخر زيارة
-
عدد الأيام التي تصدر بها
52
نوع المحتوى
ريادة الأعمال
البرمجة
التصميم
DevOps
التسويق والمبيعات
العمل الحر
البرامج والتطبيقات
آخر التحديثات
قصص نجاح
أسئلة وأجوبة
كتب
دورات
كل منشورات العضو Adnane Kadri
-
هل تستعمل أي ملفات تنسيقات خارجية ضمن وسم الـ head ؟ قمت بمحاكاة الكود على جهازي ولم أواجه أي مشكلة . كما أنه يجب عليك تنظيف الكود و إعتماد كتابة أنظف أكثر حتى تتجنب أي التباس , قد يساعد هذا قراءة الكود و إتضاح المشاكل , كما أنه سيصبح من السهل التطوير و الإضافة عليه و في حالة الأخطاء سيتم تضييق الإحتماليات على عدد أقل بكثير . أمثلة : تقسيم بنية الملفات إلى css و js و تضمينها بالملف الرئيسي . تقسيم المكونات الكبيرة إلى مكونات أصغر يسهل تضمينها و التعامل معها و تطويرها . (من مثل : صف المورد في الجدول ) .
-
لا حاجة لإستعمال المساعد asset في هاته الحالة , فعمل هذا المساعد يتلخص في إضافة المسار الكامل المرافق لملفات الـ assets بداخل مجلد الـ public و بطبيعة الحال فإن هذا لا يتضمن أي روابط خارجية أو cdn . لحل المشكلة و ظهور ملفات التنسيقات بشكل صحيح قم بتمرير الرابط ككل على هذا النحو : <link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"> أو يمكنك تحميل الملف و وضعه بداخل مجلد public ثم إستدعاءه عن طريق المساعد asset على هذا النحو : <link href="{{ asset('font-awesome.min.css') }}" rel="stylesheet"> بحيث أن هذا سيتم ترجمته إلى هذا : <link href="http://your_domain.com/font-awesome.min.css" rel="stylesheet">
- 3 اجابة
-
- 2
-
لا علاقة لهذا الخطأ بمتغيرات البيئة , يحدث هذا عادة بسبب نسيان تمرير csrf ضمن طلبات الـ POST . يمكنك تمرير المتغير عن طريق إضافة الحقل ضمن نموذج المدخلات على هذا النحو : <form action="path/to/action" method="POST"> @csrf </form> أو : <form action="path/to/action" method="POST"> <input type="hidden" name="_token" value="{{ csrf_token() }}" /> </form>
-
مرحبا أخي وعليكم السلام . أرجوا التدقيق جيدا فيما قلت سابقا . فالمشكلة أساسا ليست في غلق الوسوم و إنما هي في إمتلاك الحاويات للمودل للوضعية الثابتة أو النسبية . أما بالنسبة لحالة عدم غلق الوسم هي في أنها سيتم إعتبار الوسم المفتوح حاويا لما بعده و بالتالي ستقوم وضعيته الثابتة أو النسبية بالتأثير على ظهور الموديل. صحيح أنك تقوم بغلق الوسوم بالفعل و لكن يحدث ذلك بعد إحتواءها لعنصر المودل نفسه و هذا ما يعطل ظهورها بشكل طبيعي و يجلعها تتخذ السلوك السابق . فالحل هو إما إخراجها من العناصر التي تمتلك وضعية ثابتة أو نسبية . أو إزالة الوضعية الثابتة أو النسبية في العناصر الحاوية . العنصر الحاوي المقصود : <div class="app-container app-theme-white body-tabs-shadow fixed-sidebar fixed-header">
-
و ذلك لأنه لا يوجد إلا مودل واحد و العديد من الأزرار التي تقوم بإظهار هذا المودل . يمكنك إنشاء مودل خاص بكل مورد عن طريق إدخال عنصر الـ modal داخل الدور while و تكراره كذا مرة . ليس هذا فقط , بل تحتاج أيضا تعريف كل مودل بمعرف id فريد و ربطه بالزر المرافق حتى تتم التفاعلية وفق المطلوب , قد نحتاج للـ id الخاص بالمورد القادم من قاعدة البيانات حتى نقوم بإنشاء معرف فريد خاص بكل مودل . و سيكون ذلك كفيلا بحل المشكل . مثال عملي : <?php //الاستعلام $result = $conn->query("SELECT * FROM supplier ORDER BY id DESC"); // تعريف المتغيرات while ($row = $result->fetch_assoc()) { //تعريف بنود التوريد $id = $row['id']; $factory = $row['facory']; $supplying_data = ' <select class="form-select form-select-lg mb-3" aria-label="بنود التوريد"> <option selected>افتح لمشاهدة بنود التوريد</option>'; if ($row['sFabric'] == "true") $supplying_data .= '<option>قماش</option> '; if ($row['sAcc'] == "true") $supplying_data .= '<option>اكسسوارات</option>'; if ($row['sCarton'] == "true") $supplying_data .= '<option>كرتون</option>'; if ($row['sLine'] == "true") $supplying_data .= '<option>خيوط</option>'; if ($row['sNeedle'] == "true") $supplying_data .= '<option>إبر حياكة</option>'; if ($row['sMac'] == "true") $supplying_data .= '<option>مكن</option>'; if ($row['sBag'] == "true") $supplying_data .= '<option>أكياس</option>'; $supplying_data .= '</select>'; //نهاية تعريف بنود التوريد //الجدول echo' <tr class="table-light" align="center"> <th scope="row">' . $row['id'] . '</th> <td >' . $row['facory'] . '</td> <td>' . $supplying_data . '</td> <td align="center"> <button class="btn btn-outline-primary m-auto mt-2 more" data-toggle="modal" data-target="#more_'.$row['id'].'">عرض المزيد</button> <!-- قم بوضع المودل هنا --> <div class="modal fade" id="more_'.$row['id'].'" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"> </div> <!-- زر التعديل --> <a href="edit_supplier.php?id=' . $row['id'] . '" target="_blank"></a> <button type="button" class="btn btn-primary">تعديل</button> <!-- زر الحذف --> <button type="button" class="btn btn-danger">حذف</button> </td> </tr>'; } ?> و عوضا عن طباعة العناصر بإستعمال echo يمكنك كتابتها مباشرة كعناصر HTML هكذا : <?php //الاستعلام $result = $conn->query("SELECT * FROM supplier ORDER BY id DESC"); # بداية الدور while ($row = $result->fetch_assoc()) { $id = $row['id']; $factory = $row['facory']; //تعريف بنود التوريد $supplying_data = ' <select class="form-select form-select-lg mb-3" aria-label="بنود التوريد"> <option selected>افتح لمشاهدة بنود التوريد</option>'; if ($row['sFabric'] == "true") $supplying_data .= '<option>قماش</option> '; if ($row['sAcc'] == "true") $supplying_data .= '<option>اكسسوارات</option>'; if ($row['sCarton'] == "true") $supplying_data .= '<option>كرتون</option>'; if ($row['sLine'] == "true") $supplying_data .= '<option>خيوط</option>'; if ($row['sNeedle'] == "true") $supplying_data .= '<option>إبر حياكة</option>'; if ($row['sMac'] == "true") $supplying_data .= '<option>مكن</option>'; if ($row['sBag'] == "true") $supplying_data .= '<option>أكياس</option>'; $supplying_data .= '</select>'; //نهاية تعريف بنود التوريد //الجدول ?> <tr class="table-light" align="center"> <th scope="row"> <?php echo $row['id']; ?></th> <td ><?php echo $row['facory']; ?></td> <td> <?php echo $supplying_data; ?></td> <td align="center"> <button class="btn btn-outline-primary m-auto mt-2 more" data-toggle="modal" data-target="#more_<?php echo $row['id']; ?>"> عرض المزيد </button> <!-- قم بوضع المودل هنا --> <div class="modal fade" id="more_<?php echo $row['id']; ?>" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"> </div> <!-- زر التعديل --> <a href="edit_supplier.php?id=<?php $row['id']; ?>" target="_blank"></a> <button type="button" class="btn btn-primary">تعديل</button> <!-- زر الحذف --> <button type="button" class="btn btn-danger">حذف</button> </td> </tr> <?php } # نهاية الدور ?> كما يمكنك إنشاء ملف خارجي بإسم supplier_row و تضمينه في الدور ليتم إنشاءه كذا مرة وفق البيانات المعطاة على هذا النحو : سيحمل الملف supplier_row المحتويات التالية : <?php $id = $row['id']; $factory = $row['facory']; //تعريف بنود التوريد $supplying_data = ' <select class="form-select form-select-lg mb-3" aria-label="بنود التوريد"> <option selected>افتح لمشاهدة بنود التوريد</option>'; if ($row['sFabric'] == "true") $supplying_data .= '<option>قماش</option> '; if ($row['sAcc'] == "true") $supplying_data .= '<option>اكسسوارات</option>'; if ($row['sCarton'] == "true") $supplying_data .= '<option>كرتون</option>'; if ($row['sLine'] == "true") $supplying_data .= '<option>خيوط</option>'; if ($row['sNeedle'] == "true") $supplying_data .= '<option>إبر حياكة</option>'; if ($row['sMac'] == "true") $supplying_data .= '<option>مكن</option>'; if ($row['sBag'] == "true") $supplying_data .= '<option>أكياس</option>'; $supplying_data .= '</select>'; //نهاية تعريف بنود التوريد ?> <tr class="table-light" align="center"> <th scope="row"> <?php echo $row['id']; ?></th> <td ><?php echo $row['facory']; ?></td> <td> <?php echo $supplying_data; ?></td> <td align="center"> <button class="btn btn-outline-primary m-auto mt-2 more" data-toggle="modal" data-target="#more_<?php echo $row['id']; ?>"> عرض المزيد </button> <!-- قم بوضع المودل هنا --> <div class="modal fade" id="more_<?php echo $row['id']; ?>" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"> </div> <!-- زر التعديل --> <a href="edit_supplier.php?id=<?php $row['id']; ?>" target="_blank"></a> <button type="button" class="btn btn-primary">تعديل</button> <!-- زر الحذف --> <button type="button" class="btn btn-danger">حذف</button> </td> </tr> ثم تضمين الملف بالملف الرئيسي على هذا النحو : <?php $result = $conn->query("SELECT * FROM supplier ORDER BY id DESC"); while ($row = $result->fetch_assoc()) { include('supplier_row.php'); } ?> تحديث : قد يحدث بعض التداخل كونك تستعمل الدور داخل جدول بالفعل من جهة و تستعمل وسوم جداول من مثل tbody و theader داخل عنصر المودل , للتخلص من هذا التداخل قم بإستبدال الوسوم الخاصة بالجدول داخل المودل بوسوم تقسيمات عادية div , ولا بأس بترك الكلاسات مثل ما هي حتى لا تخسر التنسيق أو تضطر إلى إعادته .
-
الظاهر أن خلفية المودل modal-backdrop تظهر فوق المودل modal نفسه . يحدث هذا السلوك عادة بسبب إمتلاك الحاوي لعنصر المودل الوضعية الثابتة fixed أو النسبية relative لذلك ينصح دوما بوضع المودل قبل وسم إغلاق الـ body مباشرة لتجنب هاته المشكلة أو التأكد من إمتلاك كل الحاويات لعنصر المودل الوضعية الإفتراضية . لكن في هاته الحالة ألحظ أنه يوجد بعض الوسوم المفتوحة التي لم يتم إغلاقها . في هاته الحالة تم إعتبارها كحاويات لما بعدها من عناصر مفتوحة أو مغلقة متضمنة المودل نفسه . لاحظ : <div class="app-container app-theme-white body-tabs-shadow fixed-sidebar fixed-header"> <div class="app-main"> <div class="app-main__outer"> <div class="app-main__inner"> <div class="app-page-title"> </div> # < < < من المفروض وجود وسم إغلاق # < < < من المفروض وجود وسم إغلاق # < < < من المفروض وجود وسم إغلاق # < < < من المفروض وجود وسم إغلاق <table class="table table-primary table-bordered" dir="rtl"> ... </table> لاحظ أيضا أن الحاوي الأول (عدم إغلاقه سيجعله حاويا لكل الوسوم المغلقة أو المفتوحة بعده) يملك الوضعية الثابتة بسبب الصفوف fixed-header و fixed-sidebar و هذا غالبا ما أدى إلى ظهور المشكلة . فحل المشكلة ببساطة هو في إغلاق الوسوم المفتوحة . إذ لم يكن هذا كفيلا بحل المشكلة يمكنك إعادة ترتيب العناصر على المحور Z عن طريق الخاصية z-index . فعندما تتداخل العناصر يمكن عن طريق تحديد قيمة هذه الخاصية تحديد ما هو العنصر الذي سيظهر أعلى بقية العناصر . يمكنك إعطاء العنصر بالصف modal-backdrop قيمة أقل : .modal-backdrop { z-index: -1; }
- 6 اجابة
-
- 1
-
أفهم أنك تريد إعادة إعداد الترتيب التلقائي بعد حذف أي صف في قواعد البيانات . مثلا : | id | name | | -- | ---- | | 1 | jhon | | 2 | hsoub| | 3 | ahmed| | 4 | ola | | 5 | walid| ثم قمت بحذف الصفين باﻷسماء jhon و hsoub تكون الصفوف مرتبة كالتالي : | id | name | | -- | ---- | | 1 | ahmed| | 2 | ola | | 3 | walid| طبعا يمكنك إعادة الترتيب بعد كل حذف على هذا النحو : ALTER TABLE products AUTO_INCREMENT=1; غير أن هذا اﻷمر أو أي تعديل ثان على صف المعرف غير مقترح عمله ﻷن أي تعديل بالمعرف الخاص بالصف سيؤدي إلى خرب علاقاته مع الجداول الأخرى ,كما أن هذا لن يقوم بترتيب الصفوف اعتبارا للصفوف التي تم حذفها , وإنما يقوم بتجنيبك مشكلة إدراج صفوف جديدة بترتيبات قد تم حذفها بالفعل (مثال : قمت بحذف الصف الأخير بالترتيب 6 , أريد من الصف التالي أن يأخذ الترتيب 6 لا 7 ) . عوضا عن ذلك يمكنك قراءة البيانات بشكل عادي من قاعدة البيانات دون أي تعديل عليها , ثم على مستوى الـ PHP سيتم إضافة عمود ترتيبي لقراءة الصفوف مرتبة بدون المساس بالمعرف id أو أي صف ثان . سيكون الأمر مشابها للتالي : نقوم بجلب كل المنتجات (مثلا) من قواعد البيانات و نضيف لكل صف رقما مميزا مرتبا على هذا النحو : <?php $servername = "localhost"; $username = "username"; $password = "password"; $dbname = "db"; // إنشاء إتصال $conn = new mysqli($servername, $username, $password, $dbname); // التحقق من الإتصال if ($conn->connect_error) { die("فشل الإتصال :" . $conn->connect_error); } // إنشاء إستعلام $sql = "SELECT * FROM products"; // تنفيذ الإستعلام $result = $conn->query($sql); $products = []; if ($result->num_rows > 0) { // إضافة عمود مرتب لكل صف $i = 1; while($row = $result->fetch_assoc()) { $row['special_number'] = $i; array_push($products ,$row); $i++; } } // => return $products // إغلاق الإتصال $conn->close(); ?> لاحظ أن العملية مرنة أكثر من تعديلك لصف معين بقاعدة البيانات بعد كل تعديل على أي صف . فيمكنك تعديل بداية الترتيب و التحكم فيه , كما أنه أيضا يمكنك التحكم في ترتيب الصفوف التي جلبها من قاعدة البيانات عن طريق الإستعلام ORDER BY .
-
مرونة لارافل , و البرمجة الخاصة بشكل أعم , تجعل طرق تحقيق نفس غرض الـ shortcodes مثل ما في الوردبرس كثيرة و شاسعة , و لعل من أبسط الطرق : عن طريق تخصيص توابع الـ blade أو كما تسمى الـ blade directives ( في حالة الإستعمال في ملفات blade فقط ): نقوم بتعريف التوابع بملف BladeServiceProvider.php بداخل مجلد App/Providers بداخل الدالة boot على هذا النحو : (قد تحتاج لإنشاء Provider بنفس الإسم إن لم يكن الملف موجودا . يمكنك ذلك عن طريق الأمر : php artisan make:provider BladeServiceProvider ) . <?php namespace App\Providers; use Illuminate\Support\ServiceProvider; class BladeServiceProvider extends ServiceProvider { /** * Bootstrap any application services. * * @return string */ public function boot() { // video Blade::directive('video', function ($expression) { return '<video width="320" height="240" controls> <source src="'.$expression.'" type="video/mp4"> </video>'; }); // audio Blade::directive('audio', function ($expression) { return '<audio controls> <source src="'.$expression.'" type="audio/ogg"> </audio>'; }); } /** * Register any application services. * * @return void */ public function register() { // } } ثم يمكن إستعمال أي لاحقة أو أي shortcode بملفات الـ blade عن طريق : @video('path/to/video.mp4') @audio('path/to/audio.mp3') 2. عن طريق تعريف واجهة تحمل الدوال المسؤولة عن اختصار الكود : نقوم بإنشاء مجلد واجهات Facades بداخل مجلد App و ننشئ به ملف Shortcodes.php ليحمل المحتوى التالي : <?php namespace App\Facades; class Shortcodes { /** * create video from a given source. * * @return string */ public static function video($source) { return '<video width="320" height="240" controls> <source src="'.$source.'" type="video/mp4"> </video>'; } /** * create audio from a given source. * * @return string */ public static function audio($source) { return '<audio controls> <source src="'.$source.'" type="audio/ogg"> </audio>'; } } ثم يمكن إستدعاءه من أي مكان في التطبيق عن طريق : <?php echo App\Facades\Shortcodes::video('path/to/video.mp4'); echo App\Facades\Shortcodes::audio('path/to/audio.mp3'); كما يمكنك تعريف مكافئ بملف app.php لإستدعاء أنظف : <?php 'aliases' => [ ........ 'Shortcode'=> App\Facades\Shortcodes:class, ] ثم يتم الإستدعاء هكذا : <?php echo \Shortcode::video('path/to/video.mp4'); echo \Shortcode::audio('path/to/audio.mp3'); 3. إن كانت حاجتك للـ shortcodes حاجة لتلخيص أكواد الـ html فقط فيمكن تعريفها كملفات blade و تضمينها كمكونات . على سبيل المثال : نقوم بإنشاء مجلد components بداخل مجلد views . نقوم بإنشاء ملف video.blade.php و يكون محتواه كالتالي : <video width="320" height="240" controls> <source src="{{ $source }}" type="video/mp4"> </video> ثم نقوم بإستدعاءه من ملفات الـ blade الأخرى عن طريق تضمينه وتمرير المتغير source معه : @include('components/video' ,['source' => 'path/to/video.mp4']) أو يمكن أيضا تعريفها عن طريق مساعد helper بشكل globally و إستعماله بأي مكان من أجزاء التطبيق مثل ما اقترح المدرب@محمد أبو عواد. فكل الطرق تحقق نفس الغرض و تقوم بمثل عمل الـ shortcodes بالوردبرس . و بنفس الطريقة يمكنك أيضا معاملة الـ shortcodes الأخرى الخاصة بالوردبرس من مثل embed , gallery , playlist و caption بنفس المنطق و إنشاء دوال مكافئة تختصر عملها و يسهل إستدعاءها من أي مكان من التطبيق , و لعلها فكرة جميلة تجعل الكود أنظف و أسهل من ناحية التحكم .
-
يوجد الكثير من الإستضافات التي تقدم خدمة الإستضافة المجانية بمميزات مختلفة نذكر من بينها : إستضافة Firebase من Google : بجانب Google Cloud تقدم غوغل خدمة Firebase للإستضافات , لعل من أفضل ميزاتها أنها تسمح لك بإضافة بحجز نطاق مدفوع و ربطه مع موقعك , كما أنها دائمة و ليست مؤقتة كبعض الإستضافات المجانية الأخرى , قد تكون أفضل خيار لك في حالة ما احتجت رفع الـ API الخاص بموقعك. إستضافة 00webhost , تابعة لمنصة hostinger . رغم مميزاتها العديدة إلا أني لا أفضلها على غيرها . فهي تقوم بوضع علامة الإستضافة على كل صفحات الموقع و هو شيء ليس بالإحترافي في حالة عرض العمل بمعرض الأعمال . إستضافة Heroku , و لعلها الأفضل على الإطلاق . بحيث توفر cli يسهل به إدارة ملفات الموقع كما توفر نظام إدارة نسخ version control system أي أنك تستطيع التحكم بموقعك عن طريق أوامر الـ git , و هي جد مناسبة في حالة تطبيقات اللارافل فهي توفر الكثير من الـ add-ons التي تناسب تطبيقك .كما أنه يمكن ربط موقعك بمستودع على الغيت هب و تفعيل التحديث التلقائي عليها . وهذا بجانب أنك تستطيع إضافة نطاقك الخاص و ربطه مع الموقع . إستضافة infinity free , و رغم أني لا أحبذ إستعمالها إلا أنها واحدة من أفضل الإستضافات . إستضافة Free hosting , بحيث تقوم بتوفير خطط إستضافة مجانية تتضمن مساحة 10GB و هو شيء لا تقدمه الإستضافات الأخرى , رغم أنها تطلب إمتلاك نطاق مدفوع مسبقا . أما و الشيء الأسوء على الإطلاق هو اقتطاع الاستضافة من حسابك في حالة تجاوزك للحد الشهري المطلوب و هذا دون مراجعتك بهذا الأمر .
- 4 اجابة
-
- 1
-
لاحظ أنك لا تقوم بإرسال أي متغيرات بالمسميات id و type في تحضيرك للطلب POST . فمن المفروض أن يتم تعريف الـ id الخاص بالمورد ضمن نموذج المدخلات ومن ثم إرساله ضمن طلب الـ POST حتى يتم قراءة البيانات من الطلب وتحديث المورد المقصود . مثال عملي : تعريف الـ id كحقل مخفي في نموذج المدخلات : <input type="hidden" value="ضع الايدي هنا" name="supplier_id"/> قراءة المتغير على هذا النحو : var id = $(".spplier_id").val(); إرساله مع باقي المتغيرات في البيانات الممررة عبر الطلب : data:{ "id": id, } و نفس الشيء بالنسبة لـ type . فأرى أنك تقوم بتمرير كامل المتغيرات ما عداهما . ثم سيتم إستقبال الطلب و معالجته بشكل عادي .
- 6 اجابة
-
- 1
-
و هذا لأن الطلب POST فارغ و لا توجد به أي متغيرات بالمسميات id و index في الحالة الإفتراضية . لحل المشكلة يمكنك إعطاءها أي قيم إفتراضية على هذا النحو : <?php $id = $_POST['id'] ?? null; $type = $_POST['type'] ?? null; أو تمريرها داخل الشرط مثل ما اقترح @بلال زيادة فتكون معرفة في حالة طلبات الـ POST فقط . كما أنه يمكن إختصار الكثير من الأكواد المكررة المطولة لديك . أمثلة عن ذلك : تعريف المتغيرات من text1 حتى text19 و المتغيرات من check1 حتى check7: var texts = []; var checks = []; for (var i = 1; i < 20; ++i) { texts[i] = $(".text-"+i).val(); if(i < 8) { checks[i] = $(".check-" + i).prop("checked"); } } ملفات تعريف الارتباط : // حذف ملفات تعريف الارتباط بعد نجاح الطلب success: function(data) { if (data == "done") { for(var i = 1 ;i < 20; i++) { deleteCookie("text" + i); if(i < 8) { deleteCookie("check" + i); } } } } // تعريف ملفات الارتباط for(var i = 1 ;i < 20; i++) { document.cookie = "text"+ i +"=" + texts[i + 1] + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; if(i < 8) { document.cookie = "check"+ i +"=" + checks[i + 1] + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; } } ثم إرسال المصفوفتين texts و checks عبر الطلب عوضا عن كل المتغيرات فتتم المعالجة على هذا النحو : <?php if ($type == "supp") { for($i = 1;$i < 20 ;$i++) { ${"text".$i} = $_POST['texts'][$i]; if($i < 8) { ${"check".$i} = $_POST['checks'][$i]; } } } سيجعل الكود أقصر , أنظف و أسهل قراءة .
- 6 اجابة
-
- 1
-
نعم يمكنك ذلك عن طريق الإستعانة بمفهوم المسترجعات والمعدلات (Accessors & Mutators) في لارافال . مثال عملي عن ذلك : نقوم بتعريف معدل جديد بملف مودل المستخدمين على هذا النحو : <?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * Get the user's type. * * @param string $value * @return void */ public function getTypeAttribute($value) { if($value == 0 ) return 'admin'; return 'user'; } } لاحظ كيفية تعريف المعدل : get | {attr} | Attribute attr => capitialized يمكنك القراءة أكثر عن الموضوع من هنا .
- 2 اجابة
-
- 2
-
هذا الأمر لا يقتصر على فلاتر أو غيره , فكل بوابات الدفع تقدم إما واجهة تطبيق برمجية جاهزة API أو مكتبة SDK يسهل ربطها , دمجها و التعامل معها بأي إطار عمل أو منصة أو أي لغة كانت . و إختيار بوابة الدفع عموما يكون إنطلاقا من إحتياجات أو إختيار عميلك بالدرجة الأولى , ولأسباب أخرى بدرجة ثانية (من مثل المنطقة و الدول المدعومة و العمولات المخصومة على كل تحويل و العروض المتوفرة .. إلخ ) . أما عن بوابات الدفع التي تقبل إشتراك فردي (أشخاص و شركات) لا تشترط و لا تطلب أي سجل تجاري , رقم ضريبي أو بطاقة ضريبية فنذكر من بين أفضلها : بوابة دفع بيبال Paypal, بحيث توفر SDK سهل الإستخدام و الربط و خصوصا مع لغات و منصات الواجهة الأمامية من مثل فلاتر .أؤمن أنها الأفضل في كثير في الحالات , كما توفر أيضا حساب تجريبي (sandbox account) لتجربة التطبيق على مستوى التطوير . باي فورت PayFort, وهي أحد أحد أبرز بوابات الدفع الإلكتروني الرائدة في الشرق الأوسط تم إنشاءها بالإمارات و استحوذت عليها شركة أمازون الان و قد تم تغيير إسمها إلى Amazon Payment Services, تقوم بتوفير API سهل الربط مع تطبيقك . سكريل Skrill, و هي بوابة غنية عن التعريف توفر أيضا واجهة برمجية سهلة الربط . بوابة تتو تشيك أوت 2checkout , و هي واحدة من أكثر البوابات شيوعا , توفر أيضا API سهل الإستخدام بتوثيق مفصل , (قد كنت اخترتها للعديد من العملاء ممن سبق لي التعامل معهم) . للربط مع فلاتر قد تحتاج القراءة أكثر عن قنوات المنصة .
- 1 جواب
-
- 1
-
تحسين محركات البحث هو مجال شاسع و من المجحف تلخيصه في مقال واحد , وتنقسم الإستراتيجيات إلى قسمين: على الصفحة، وخارج الصفحة on-page & Off-Page . نذكر من بينها : على الصفحة: شاملة كل العمليات التي يتم القيام بها داخل الموقع نفسه , من تعديل أكواد و إلتزام بنمط معين من كتابة الكود و غيرها . أمثلة : إضافة كلمات مفتاحية و وصف الموقع و أكواد الميتا تاج meta tags ومتابعتها . إضافة عناوين للوسوم الخاصة بالصور داخل الموقع . (alt) . إضافة صفحة robots.txt التي من شأنها توجيه محركات البحث إلى الصفحات المطلوب أرشفتها و تلك الأخرى الممنوعة أو حتى حظر بعد الصفحات . إضافة صفحة خريطة الموقع sitemap.xml و تحديثها بشكل مستمر إن كان الموقع ديناميكي غير ثابت . سكربتات و أكواد الأنماط و النماذج schemas.org لصفحات الموقع لإظهارها بشكل أكثر إحترافية (يمكنك التفصل في الموضوع أكثر من هنا ). محتوى الصفحة , لا بد أن يكون فريدا و غير مأخوذ من أية مواقع أخرى . إضافة الموقع إلى Google Search Console و متابعة الموقع . تقسيم المحتوى إلى عناوين فرعية (headings). خارج الصفحة: شاملة كل العمليات التي تقوم بها خارج الموقع لكسب ثقة محركات البحث، مثل الروابط الخارجية و الـ back linking (ينبغي القراءة في هذا الموضوع بشكل أكثر حيث أن محركات البحث و خصوصا غوغل تعتبر العملية غير شرعية ولو تم كشف ذلك سيتم حظر الموقع نهائيا من الأرشفة , و ذلك لأن منطق محركات البحث هو في أن شيوع موقع يعني تناقل رابطه بين المواقع و هو أمر يجب أن يقوم به زوار و رواد الموقع لا ملاكه أو أصحابه ) . كما يمكنك الإستعانة بهاته المنصات لتحسين ظهور مواقعك و منصاتك : إضافة غوغل كروم lighthouse . Google Search Console . تحليلات غوغل . منصة و أدوات SEMrush لتحسين محركات البحث . أدوات Screaming Frog طبعا تحسين ظهور موقعك لن يكون آنيا و إنما هي عملية تحتاج صبر , وقت و متابعة دائمة .
- 5 اجابة
-
- 2
-
يمكن القول أنها فقط عبارة عن كنية أو إسم مختصر للمستودع البعيد Remote Repo الذي تم استنساخ المشروع منه . فهو يستخدم بدلا عن عنوان الـ URL للمستودع الأصلي و بالتالي يسهل الرجوع إليه و يكون عوضا عن طباعة هذا كل مرة : git push git@github.com:USERNAME/REPOSITORY-NAME.git YOUR-BRANCH يمكن فقط تنفيذ الأمر بهذا : git push origin YOUR-BRANCH ( طبعا يكون هذا بعد تسجيل المستودع البعيد في حالة إنشاء مشروع جديد . ويكون معينا افتراضيا عن طريق الـ git عند استنساخ مستودع ما . ) طبعا يمكن إعادة تعيين هذا فهو إعداد افتراضي و ليس إلزاما , عن طريق هذا الأمر : git remote rename origin something_else كما يتم تعريفه في مشروع محلي جديد كالتالي : git remote add origin git@github.com:USERNAME/REPOSITORY-NAME.git ليس بالضرورة أن يتم تخصيص branch في حالة ما كان يوجد branch واحد على المستودع البعيد , وليكن master مثلا , يكون الأمر السابق عوضا و بدلا عن الأمر التالي : git push origin master فالأمور ببساطة هي اختصارات و اصطلاحات اعتادت عليها الأوساط البرمجية لا أكثر .
- 2 اجابة
-
- 2
-
قد قمت بتفحص مستودعك على الـغيت هب و لا أرى إلا branch واحد ليس به أي ملفات github-pages من مثل : index.md , __config.yml أو مجلد docs أو index.html أو readme.md . فحل المشكلة ببساطة هو حذف البيئة التي تستخدمها و إعادة إنشاء صفحات غيت هب من جديد بطريقة صحيحة ( و يستحسن أن تكون في branch جديد غير الـ master ) . أولا : يجب عليك حذف البيئة التي تستخدمها . يمكنك ذلك عن طريق التصفح إلى : الإعدادات settings . البيئات Environments . اضغط على زر الحذف و قم بتأكيد حذف البيئة . ثانيا : الان يمكنك إنشاء صفحة غيت هب جديدة , و احرص على إتباع الخطوات : قم بالتصفح إلى الإعدادات settings. يمكنك النزول إلى قسم صفحات غيت هب ( إن لم يظهر أي نمموذج إدخال قم بالضغط على check it out here فيتم نقلك إلى نموذج الإدخال). إحرص على عدم تعيين أي branch و قم بوضع المصدر source كـ none , هذا سيقوم تلقائيا بإنشاء branch خاصة بصفحات غيت هب و سيعطى الإسم gh-pages تلقائيا . قم بإختيار ثيم ثم قم بعمل commit عن طريق تحديد الثيم و من ثم زر commit . الان يمكنك التصفح إلى المسار الموصوف و سيتم عمل الصفحة بشكل عادي , و تأكد أن تقوم بمسح الملفات المؤقتة في حالة لم تعمل من المرة الأولى .
- 4 اجابة
-
- 1
-
غرض تمرير بيانات في المسار هو لجعل الصفحة تظهر بشكل ديناميكي غير ثابت , ولفعل هذا في مكتبة gatspy ستحتاج الواجهة createPage لبناء أي صفحات ديناميكية و متغيرة (مثل صفحات البروفايل أو صفحة المنتج أو المقالة و غيرها) , في حين أن كل الصفحات الثابتة تبنى و تصدر بطريقة عادية بداخل src/pages . مثال عملي : بداخل ملف gatsby-node.js نقوم بتصدير الثابت createPages على هذا النحو : export const createPages = ({ actions }) => { const { createPage } = actions; createPage({ // تعريف المسار path: '/users/YOURID', // تعريف المكون المعاد في المسار component: YourRelatedComponent, // إرسال بيانات مخصصة للمكون context: { userID: 'YOURID', }, }); }; ثم يمكنك الوصول للبيانات الممررة بشكل عادي . إقرأ أكثر عن إنشاء و تعديل الصفحات في Gatspy هنا.
- 1 جواب
-
- 1
-
يبدو أن المشكلة في الوصول إلى الـ loader بداخل مجلد الـ node_modules . تأكد أن تقوم بإعادة تثبيت url-loader عن طريق الأمر : npm install url-loader --save-dev ثم قم بإعادة البناء . و أيضا , قم بالتأكد أنك تقوم بتمرير اللاحقة loader- لكل الـ loaders المعنية على هذا النحو : loaders: [ { test: /\.css$/, loader: "style-loader!css-loader" }, ] و ذلك عوضا عن : loaders: [ { test: /\.css$/, loader: "style!css" }, ] هذا سيقوم بتجنب مشكلة إعتبار style أو css مثلا (دون لاحقة) كالـ module المعني بالعملية في حين أن القائم بالعملية هي الموديلات css-loader و url-loader و هكذا .
- 2 اجابة
-
- 1
-
يظهر من الصورة أنك تقومين بفتح مشروع الـ webpack عن طريق ملف الـ index بداخل مجلد dist . و هذا في الغالب سيؤدي بكل مسارات الملفات من الشكل main.css/ التي قد قمت بتضمينها تظهر على هذا النحو بعد البناء : file:///main.css و بالتالي فهي غير قابلة للوصول من الأساس و لو قمت بفتح الـ console ستجدين خطأ يخبرك أن الملفات غير موجودة . فالحل هو فتح المشروع عن طريق طباعة الأمر : npm run serve الذي سيقوم بدوره بطباعة التالي : Project is running at http://localhost:9000/ webpack output is served from / Content not from webpack is served from /path/to/some/path/project/dist wait until bundle finished: / Compiled successfully. بعد البناء بنجاح يمكنك التصفح إلى المسار الموصوف على هذا النحو : http://localhost:9000/ و سيتم إظهار كل الملفات شاملة ملفات التنسيق و السكربتات بشكل صحيح . ملاحظات : في حالة ما لم يعمل الأمر بشكل صحيح و قمت بمواجهة خطأ من هذا النوع : missing script: serve فتأكدي أن تقومي بتسجيل الأمر و إضافته إلى كائن scripts بملف package.json على هذا النحو : "scripts": { "serve": "webpack serve --mode development" }, و الان يمكنك طباعة الأمر و التصفح إلى المسار الموصوف بعد نجاح البناء , و إستعراض مشروعك بشكل عادي .
- 3 اجابة
-
- 2
-
يمكننا إستغلال ميزة قواعد البيانات العلائقية لتحقيق الغرض بمنطق مشابه للتالي : لنقم بإنشاء جدول للمواضيع بقاعدة البيانات و ليكن topics . نقوم بإنشاء جدول للصور و ليحتوي على مفتاح أجنبي كعمود : topic_id , يمثل عمود الـ id بجدول المواضيع . فتكون العلاقة بين جدول المواضيع و الصور one to many . طباعة وتنفيذ إستعلام لجلب الصور ذات موضوع محدد على هذا النحو : SELECT * FROM PHOTOS WHERE topic_id = 'YOUR_TOPIC_ID_HERE'; و سيسهل عرضها مباشرة عن طريق الفلاتر .
- 3 اجابة
-
- 1
-
للمشكلة عدة أسباب محتملة .ولكن الأرجح أنها قد تكون بسبب إستعمال loader واحد لنفس نوع الملف أكثر من مرة فيتم بناء مسار الصورة أكثر من مرة فيتم كسر المسار . مثال عن ذلك : إن كنت تقوم بتحميل الملفات باللواحق woff , woff2 , eot, ttf , png , svg بإستعمال url-loader ثم تقوم بتحميل الملفات باللواحق jpeg , jpg , gif , png , svg بإستعمال url-loader ضمن كائن loader جديد فسيتم كسر مسارات الصور بالصيغ png و svg ولن تظهر في المتصفح . loaders: [ .. { test: /\.(jpe?g|gif|png|svg)$/i, loader: 'url-loader', }, { test: /\.(png|woff|woff2|eot|ttf|svg)$/, loader: 'url-loader' } .. ], الحل : تحميل الملفات من نفس النوع مرة واحدة , بحذف الملفات ذات اللواحق png , svg المكررة فيكون : loaders: [ .. { test: /\.(jpe?g|gif|png|svg)$/i, loader: 'url-loader', }, { test: /\.(woff|woff2|eot|ttf)$/, loader: 'url-loader' } .. ], ملاحظة : ليس بالضرورة أن يكون url-loader , المهم في الإحتمال هو أن يكون قد تم إستعمال نفس الـ loader لنفس لواحق الملفات كذا مرة لا مرة واحدة .
-
يمكنك معاملة Role كأي Laravel Class ثان , و ليكن في العلم أنه توجد علاقة one To Many بين الدور \App\Models\Role::class و الأذونات \App\Models\Permission::class . يمكنك الوصول إلى الأذونات الخاصة بدور محدد عن طريق : <?php Role::where('name', 'admin')->first()->permissions;
- 4 اجابة
-
- 1
-
تحديث تحقيقا لنفس الغرض يمكنك جلب الأذونات الخاصة بمستخدم ما عن طريق إستعمال الدالة allPermissions على هذا النحو : <?php dd($user->allPermissions()); سيتم إعادة مجموعة Illuminate\Database\Eloquent\Collection بجميع الأذونات المتعلقة بمستخدم ما , و يمكنك تصفية المجموعات بحسب دور Role معين .
- 4 اجابة
-
- 1
-
سيكون عليك بناء نموذج إدخال و الواجهة الخلفية للبرنامج حتى يتم ذلك بشكل سليم . يمكنك تطبيق العملية وفق الخطوتين التاليتين : بناء نموذج إدخال البيانات على هذا النحو : <form action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>" method="POST"> <input type="checkbox" name="myCheckBox"/> <input type="hidden" name="idRelated" value="قم بوضع معرف العنصر المراد تغييره هنا"/> <button type="submit">submit</button> </form> بناء الواجهة الخلفية للبرنامج : <?php if($_SERVER["REQUEST_METHOD"] == "POST"){ // إنشاء إتصال بقواعد البيانات و التحقق منه $servername = "localhost"; $username = "username"; $password = "password"; $dbname = "myDB"; $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { die("فشل الإتصال : " . $conn->connect_error); } // تحضير الإستعلام و تنفيذه $checked = isset($_POST['myCheckbox']) ? 1 : 0; $sql = "UPDATE YourTable SET my_column='".$checked."' WHERE id=".$_POST["idRelated"]; if ($conn->query($sql) === TRUE) { echo "تم تحديث العنصر"; } else { echo "حدث خطأ : " . $conn->error; } $conn->close(); }) فيكون الكود كاملا كالتالي : <?php if($_SERVER["REQUEST_METHOD"] == "POST"){ // إنشاء إتصال بقواعد البيانات و التحقق منه $servername = "localhost"; $username = "username"; $password = "password"; $dbname = "myDB"; $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { die("فشل الإتصال : " . $conn->connect_error); } // تحضير الإستعلام و تنفيذه $checked = isset($_POST['myCheckbox']) ? 1 : 0; $sql = "UPDATE YourTable SET my_column='".$checked."' WHERE id=".$_POST["idRelated"]; if ($conn->query($sql) === TRUE) { echo "تم تحديث العنصر"; } else { echo "حدث خطأ : " . $conn->error; } $conn->close(); }) ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>UPDATE ITEM</title> </head> <body> <form action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>" method="POST"> <input type="checkbox" name="myCheckBox"/> <input type="hidden" name="idRelated" value="قم بوضع معرف العنصر المراد تغييره هنا"/> <button type="submit">submit</button> </form> </body> </html> و هذا هو الشكل الأبسط و منطق العملية . يمكنك فعل الأمر عن طريق طلبات Ajax أو تضمين الكود و منطق العملية بصفحة أو نموذج إدخال اخر. الأمر فقط هو في التحقق من تحديد الـ checkbox من عدمه , العملية تبسط في : <?php $checked = null; if(isset($_POST['myCheckbox'])) { $checked = 1; } else() { $checked = 0; } // كتابة مختصرة $checked = isset($_POST['myCheckbox']) ? 1 : 0; ثم يمكنك إدراج القيمة المتحصل عليها بقاعدة البيانات مثل ما هو موصوف في المثال الأول .
- 1 جواب
-
- 2