لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 04/13/22 في كل الموقع
-
السلام عليكم هل في مجال لتغيير الدوره المسجل فيها (دورة علوم الحاسب) إلى (دورة تطوير واجهات المستخدم) والسبب عدم اطلاعي على محتويات الدوره بشكل كامل مسبقا وعدم تناسبها لاحتياجاتي😅1 نقطة
-
لغة C++ وهو مطلوب كتابة برنامج يقوم بقراءة قيمة المبيعات لأحد المندوبين كعدد صحيح من المستخدم ثم طباعة رسالة تشجيعية على النحو التالي: . "Excellent" للمبيعات أكبر من أو تساوي 9000 ريال . و"Very Good" للمبيعات أكبر من أو تساي 7000 ريال . و"Good" للمبيعات أكبر من أو تساوي 5000 ريال . و "Need improvement" للمبيعات أقل من 5000. ( يتم الحل باستخدام قاعدة If/else if /else )1 نقطة
-
استخدم هذا #include <iostream> using namespace std; int main(){ int value; cout <<"Enter the sales value: " << endl; cin >> value; if (value >=9000){ cout << "Excellent" << endl; cout << " :)" << endl; }else if (value >=7000){ cout << "Very Good" << endl; cout << " :)" << endl; } else if (value >=5000){ cout << "Good" << endl; cout << " :)" << endl; } else { cout << "Need improvement" << endl; cout << " :)" << endl; } return 0; }1 نقطة
-
هل ساتعلم javascript oop في هذه الدوره لان كل ما اكلم الدعم الفني محدش بيرد1 نقطة
-
قمت بإنشاء div وداخل هذا وضعت ايقونة i بحيث <div class="controll controll-4" data-id="contact"> <i class="fa-solid fa-briefcase "></i> </div> const allSections = document.querySelector('.main-contnet') allSections.addEventListener('click', (e) =>{ console.log(e.target.dataset.id); } الآن انا لما أضغط على الايقونة يطلعلي undefined و ليس الأيدي المطلوب حتى أضغط في الحافة يظهر لي id في console.log كيف اجعلها لما اضغط على الأيقونة يظهر id الخاص بdiv؟ أم هل من الصحيح ان اكرر الايدي بهاذا الشكل لانني جربته يعمل بشكل عادي <div class="controll controll-4" data-id="contact"> ^^^^^^^^^^^^^^^^^^ <i class="fa-solid fa-briefcase " data-id="contact" ></i> ^^^^^^^^^^^^^^^^^ </div> شكرا1 نقطة
-
أعتقد و لتقليل التعقيد لأن الأيقونات في مكان و العناصر التي نريد التنقل بينها في مكان آخر (لأب آخر) ضع يمكنك تكرار data-id لا مشكلة بما أنه يحل المسألة1 نقطة
-
إشتريت دورة علوم الحاسوب و كنت أنوي شراء دورة تطوير الويب ولاكن سعر صعد الليس هنالك كود خصم أرجوكم1 نقطة
-
في هذه الدوره هل هتعلم algorithm and data structures ام لا وبعض اساسيات البرمجه المرتبطه ب javaScript1 نقطة
-
في حاله الاشتراك في الدوره وتعلم كل الاساسيات ومع بدايه المشورع الخاص بيها في node js سوف اتعامل مع Database ام لا1 نقطة
-
أعمل على مشروع بسيط بإستخدام لارافيل Laravel وأريد إستخدام jQuery فيه، حاولت البحث عن طريقة لتضمين jQuery في الملف app.js الذي يتم توليده عبر Laravel mix ولكني لم أجد شيء مفيد، وجدت طرق لتضمين مكتبات أخرى فقط. أريد تضمين سكريبت واحد فقط بالشكل التالي: <script src="{{ asset('js/app.js') }}"></script> لتقليل عدد الطلبات requests التي تتم في الموقع كيف أقوم بتثبيت jQuery في مشروع Laravel وإستخدامها من خلال الملف app.js في لارافيل Laravel؟1 نقطة
-
1 نقطة
-
أحسنت عمل جيد، ينقص توضيح بشأن الشروط المتعاقبة if else if else سأصحح واحدة و عليك بالبقية #include <iostream> using namespace std; int main(){ int Excellent; cout <<"Enter the sales: " << endl; cin >> Excellent; if (Excellent >=9000){ cout << "Excellent" << endl; cout << " :)" << endl; }else if (Excellent >=7000 cout << "Very Good" << endl; } else if (..) { } ... else { } } ملاحظة: ليس من المحبذ استخدام كلمة Excellent كمتغير، بل مثلاً كلمة value أو mony لتدل على ما يعبر نعنه المتغير أكمل على نفس المنوال، نضع else لوحدها كآخر شرط حيث لن نستخدم if أما الشروط التي بين أول و آخر شرطين نستخدم if else1 نقطة
-
1 نقطة
-
تفضل هذه محاولتي #include <iostream> using namespace std; int main(){ int Excellent; cout <<"Enter the sales: " << endl; cin >> Excellent; if (Excellent >=900){ cout << "Excellent" << endl; cout << " :)" << endl; }else{ cout << "Very Good" << endl; } } مرحبا مجددا ، أرفقت صور وكود لمحاولتي بحل المطلوب مني ،، ولكن يبدوا لي بأني أخطت في متغير ما مثل وضع نقطة غير مخصصة لها أو عدم اختيار الانسب من قاعدة if و iles او if eles1 نقطة
-
التعليق السابق معدل أرجو تحديث الصفحة، وأرجو إرفاق الملف لديك لنجرب تعديله وإصلاح المشكلة من غير المحبذ استخدام نفس id أكثر من مرة أعط الأيقونة أبعاد 100% و قم بإلغاء الحواشي و الهوامش لتطابق الأب1 نقطة
-
في توثيق لارافيل Laravel تم ذكر الموجه section@ وكذلك yield@ وأنه يتم إستخدامهما لتعريف أماكن يمكن لوضع مكونات فيهما <html> <head> <title>App Name - @yield('title')</title> </head> <body> @section('sidebar') This is the master sidebar. @show <div class="container"> @yield('content') </div> </body> </html> لكن لم أفهم ما الفرق بين إستخدام section@ و yield@، حيث أجد أنه يمكن عمل نفس الشيء بكلا الطريقتين. هل يوجد فرق بين إستخدام section@ و yield@ في قوالب Blade في لارافيل Laravel؟1 نقطة
-
يمكنك تطبيق دالة closets على ال collection التي قمت بعمل استعلام لها وهي allSections. أي parents = allSections.closest('div'); ثم parents.forEach(function(element) { element.addEventListener('click', (e) =>{ console.log(e.target.dataset.id); } });1 نقطة
-
ما الفرق بين الامن السيبراني وامن المعلومات وما هي لغات البرمجة الخاصة بالمجالين1 نقطة
-
أرجو محاولة حل المشكلة و إرفاق البرنامح الخاص بك لنساعدك في إكماله1 نقطة
-
أحاول تشغيل سكريبت PHP قديم نوعًا ما، ولكن تظهر الكثير من التحذيرات (خصوصًا في حلفات التكرار loop)، لذلك أريد أن أقوم بإيقاف (أو إخفاء) هذه التحذيرات مؤقتًا فقط، لكن في نفس الوقت أريد أن تظهر أي أخطاء Errors لكي أتمكن من حل أي مشاكل في السكريبت كيف يتم إيقاف التحذيرات فقط في PHP؟1 نقطة
-
محتاج كورسات ايه عشان اقدر افهم كل حاجه في موقع بالمواصفات دي1 نقطة
-
if (isset($_POST['submit'])) { $name=$_POST['name']; $descr=$_POST['descr']; $info=$_POST['info']; $price=$_POST['price']; $qty=$_POST['qty']; $sku=$_POST['SKU']; $si=$_POST['size']; $chkt=implode(",",$si); $descrebtion =$_POST['descrebtion']; $discount =$_POST['discount']; $created_at= date('Y-m-d H:i:s'); $img_name = $_FILES['uploadfile1']['name']; $img_type = $_FILES['uploadfile1']['type']; $tmp_name = $_FILES['uploadfile1']['tmp_name']; $img_name2 = $_FILES['uploadfile2']['name']; $img_type2 = $_FILES['uploadfile2']['type']; $tmp_name2 = $_FILES['uploadfile2']['tmp_name']; $img_name3 = $_FILES['uploadfile3']['name']; $img_type3 = $_FILES['uploadfile3']['type']; $tmp_name3 = $_FILES['uploadfile3']['tmp_name']; $img_name4 = $_FILES['uploadfile4']['name']; $img_type4 = $_FILES['uploadfile4']['type']; $tmp_name4 = $_FILES['uploadfile4']['tmp_name']; $img_explode = explode(".",$img_name); $img_ext = end($img_explode); $img_explode2 = explode(".",$img_name2); $img_ext2 = end($img_explode2); $img_explode3 = explode(".",$img_name3); $img_ext3 = end($img_explode3); $img_explode4 = explode(".",$img_name4); $img_ext4 = end($img_explode4); $extension= ['png','jpeg','jpg','gif']; $Get_image_name = $_FILES['uploadfile1']['name']; $image_Path = "img/".basename($Get_image_name); $Get_image_name2 = $_FILES['uploadfile2']['name']; $image_Path2 = "img/".basename($Get_image_name2); $Get_image_name3 = $_FILES['uploadfile3']['name']; $image_Path3 = "img/".basename($Get_image_name3); $Get_image_name4 = $_FILES['uploadfile4']['name']; $image_Path4 = "img/".basename($Get_image_name4); $sql ="INSERT INTO product(name,descr,info, price ,qty ,img1 ,img2 ,img3 ,img4 ,SKU, size,disc_id ,cate_id,created_at) VALUES ('$name','$descr' ,'$info', '$price','$qty' ,'$Get_image_name','$Get_image_name2' ,'$Get_image_name3' ,'$Get_image_name4' ,'$sku' ,'$chkt' ,'$discount','$descrebtion','$created_at')"; mysqli_query($conn,$sql); //mysqli_query($conn,("ALTER TABLE `product` DROP FOREIGN KEY `cat`; ALTER TABLE `product` ADD CONSTRAINT `cat` FOREIGN KEY (`cate_id`) REFERENCES `productcategory`(`id`) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE `product` DROP FOREIGN KEY `disc`; ALTER TABLE `product` ADD CONSTRAINT `disc` FOREIGN KEY (`disc_id`) REFERENCES `discount`(`id`) ON DELETE CASCADE ON UPDATE CASCADE")); if (move_uploaded_file($_FILES['uploadfile1']['tmp_name'], $image_Path)){ echo "<script>alert('Uploaded Successfully');</script> <script>window.location.href = 'addprodect.php'</script>"; }else{ echo "Not Insert Image"; } if (move_uploaded_file($_FILES['uploadfile2']['tmp_name'], $image_Path2)){ echo "<script>alert('Uploaded Successfully');</script> <script>window.location.href = 'addprodect.php'</script>"; }else{ echo "Not Insert Image"; } if (move_uploaded_file($_FILES['uploadfile3']['tmp_name'], $image_Path3)){ echo "<script>alert('Uploaded Successfully');</script> <script>window.location.href = 'addprodect.php'</script>"; }else{ echo "Not Insert Image"; } if(move_uploaded_file($_FILES['uploadfile4']['tmp_name'], $image_Path4)){ echo "<script>alert('Uploaded Successfully');</script> <script>window.location.href = 'addprodect.php'</script>"; }else{ echo "Not Insert Image"; } echo "<script>alert('Uploaded Successfully');</script> <script>window.location.href = 'addprodect.php'</script>"; } كود insert ^^ if (isset($_POST["update"])) { $id= $_GET['id']; $name=$_POST['name']; $descr=$_POST['descr']; $info=$_POST['info']; $price=$_POST['price']; $descrebtion=$_POST['descrebtion']; $sku=$_POST['sku']; $siz=$_POST['size']; $discount =$_POST['discount']; $chkt=implode(",",$siz); $created_at= date('Y-m-d H:i:s'); $img1=$_FILES["uploadfile1"]["name"]; $img2=$_FILES["uploadfile2"]["name"]; $img3=$_FILES["uploadfile3"]["name"]; $img4=$_FILES["uploadfile4"]["name"]; if ($img1 =="" ) { $sql="UPDATE product set name= '$name' ,descr ='$descr', info= '$info', price=$price, cate_id='$descrebtion' ,disc_id='$discount', SKU='$sku' , size='$chkt' , created_at='$created_at' where id=$id "; mysqli_query($conn, $sql); }else { $Get_image_name = $_FILES['uploadfile1']['name']; $image_Path = "img/".basename($Get_image_name); $sql="UPDATE product set img1='$Get_image_name' , name= '$name' ,descr ='$descr', info= '$info', price=$price, cate_id='$descrebtion' ,disc_id='$discount', SKU='$sku' , size='$chkt' , created_at='$created_at' where id=$id "; mysqli_query($conn, $sql); if (move_uploaded_file($_FILES['uploadfile1']['tmp_name'], $image_Path)){ echo "<script>alert('Updated Successfully');</script> <script>window.location.href = 'editprod.php'</script>"; }else{ echo "Not Insert Image"; } } if ($img2 =="" ) { $sql="UPDATE product set name= '$name' ,descr ='$descr', info= '$info', price=$price, cate_id='$descrebtion' ,disc_id='$discount', SKU='$sku' ,size='$chkt' , created_at='$created_at' where id=$id "; mysqli_query($conn, $sql); }else { $Get_image_name2 = $_FILES['uploadfile2']['name']; $image_Path2 = "img/".basename($Get_image_name2); $sql="UPDATE product set img2='$Get_image_name2' , name= '$name' ,descr ='$descr', info= '$info', price=$price, cate_id='$descrebtion' ,disc_id='$discount', SKU='$sku' , size='$chkt' , created_at='$created_at' where id=$id "; mysqli_query($conn, $sql); if (move_uploaded_file($_FILES['uploadfile2']['tmp_name'], $image_Path2)){ echo "<script>alert('Updated Successfully');</script> <script>window.location.href = 'editprod.php'</script>"; }else{ echo "Not Insert Image"; } } if ($img3 =="" ) { $sql="UPDATE product set name= '$name' ,descr ='$descr', info= '$info', price=$price, cate_id='$descrebtion' ,disc_id='$discount', SKU='$sku' , size='$chkt' , created_at='$created_at' where id=$id "; mysqli_query($conn, $sql); }else { $Get_image_name3 = $_FILES['uploadfile3']['name']; $image_Path3 = "img/".basename($Get_image_name3); $sql="UPDATE product set img3='$Get_image_name3' , name= '$name' ,descr ='$descr', info= '$info', price=$price, cate_id='$descrebtion' ,disc_id='$discount', SKU='$sku' , size='$chkt' , created_at='$created_at' where id=$id "; mysqli_query($conn, $sql); if (move_uploaded_file($_FILES['uploadfile3']['tmp_name'], $image_Path3)){ echo "<script>alert('Updated Successfully');</script> <script>window.location.href = 'editprod.php'</script>"; }else{ echo "Not Insert Image"; } } if ($img4 =="" ) { $sql="UPDATE product set name= '$name' ,descr ='$descr', info= '$info', price=$price, cate_id='$descrebtion' ,disc_id='$discount', SKU='$sku' , size='$chkt' , created_at='$created_at' where id=$id "; mysqli_query($conn, $sql); }else { $Get_image_name4 = $_FILES['uploadfile4']['name']; $image_Path4 = "img/".basename($Get_image_name4); $sql="UPDATE product set img4='$Get_image_name4' , name= '$name' ,descr ='$descr', info= '$info', price=$price, cate_id='$descrebtion' ,disc_id='$discount', SKU='$sku' , size='$chkt' , created_at='$created_at' where id=$id "; mysqli_query($conn, $sql); if (move_uploaded_file($_FILES['uploadfile4']['tmp_name'], $image_Path4)){ echo "<script>alert('Updated Successfully');</script> <script>window.location.href = 'editprod.php'</script>"; }else{ echo "Not Insert Image"; } } echo "<script>alert('Updated final Successfully');</script> <script>window.location.href = 'editprod.php'</script>"; } كود update ^^ descrebtion و discount هي FK1 نقطة
-
لم أجد إضافة تقوم بمثل هذا الأمر إلا في الإضافات الكاملة التي تسخدم لغرض ما مثل إضافات الترويج و الاحالات و إضافات التجارة الالكترونية و لكن ربما نستخدم shortcode في wordpress لنقوم بصنع الدالة الخاص بنا بحيث نستطيع تمرير المبلغ لهذه الدالة و تطبع لنا او تحسب لنا النسبة المئوية كالتالي : في ملف functions.php يمكننا صنع دالة بالاسم التالي function commissionSales($price) { } لاحظ أن اسم الدالة هو commissionSales وقمنا بتمرير متغير يحمل قيمة المبلغ و بداخل جسم الدالة يمكننا كتابة المعادلة التي تحسب النسبة المثوية function commissionSales($price) { $amout = $price / 10; $percentage = $amout * 100; return $percentage; } ثم نقوم بإضافة الدالة إلى دالة add_shortcode كالتالي function commissionSales($price) { $amout = $price / 10; $percentage = $amout * 100; return $percentage; } add_shortcode('commission', 'commissionSales'); حيث أن دالة add_shortcode تأخذ متغيرين المتغير الأول يكون الاسم الفريد و المتغير الثاني تكون دالة الاستدعاء التي نريد إضافتها لهذا الاسم الفريد و من ثم يمكننا استخدام الدالة في أي مكان نريده في ملفاتنا عن طريق استخدام الدالة do_shortcode التي تأخذ متغير واحد و هو الاسم الفريد لدالة حساب النسبة المئوية كالتالي <?php echo do_shortcode('[commission price="'.$price.'"]'); حيث يمكنك مناداة دالة shortcode الذي قمت بصنعها أكثر من مرة في البرنامج .1 نقطة
-
لكي يتم طباعة أي قيمة في console فإنك بحاجة إلى الضغط على أي زر في الصفحة، وذلك لأنك حددت مسبقًا كل الأزرار buttons وأضفت حدث event لتنفيذ الدالة btnAction عند الضغط على أي زر، أيضًا يجب أن يحتوي الزر الذي تضغط عليه الخاصية data-cookie لكي يتم طباعة قيمتها. إن أستمرت المشكلة لديك، فأرجو منك أن ترفق كود HTML كذلك.1 نقطة
-
الخطأ بسبب إستدعاء الدالة btnAction في نهاية الكود، حيث لم تقم بتمرير أي حدث إليها وبالتالي فإن المعامل e غير معرف undefined، وبالتالي يحدث خطأ عند محاولة الوصول إلى الخاصية target ضمن المعامل e كل ما عليك لحل المشكلة أن تقوم بحذف آخر إستدعاء للدالة btnAction من الكود: const btns = document.querySelectorAll("button") btns.forEach(btn =>{ btn.addEventListener('click', btnAction) }) function btnAction(e) { let description = e.target.getAttribute("data-cookie") console.log(description); } // هذا السطر هو سبب المشكلة // btnAction()1 نقطة
-
يمكنك التحكم في مدة عرض الإعلان من خلال إضافة خاصية جديد في كل عنصر video خاص بالإعلانات وليكن اسمها data-duration، بالشكل التالي: <video class="add1 one" id="add1" src="video/ad.mp4" data-duration="5"></video> <video class="add2 one" id="add2" src="video/ad2.mp4" data-duration="7"></video> <video class="add3 one" id="add3" src="video/ad3.mp4" data-duration="10"></video> ثم في كود JavaScript نقوم بتغير قيمة العداد بحسب القيمة الموجودة في الخاصية data-duration في الإعلان الذي تم إختياره عشوائيًا: let ads = document.querySelectorAll('.one'); let adsLength = ads.length; let randomAdIndex = Math.floor(Math.random() * adsLength) let randomAd = ads[randomAdIndex]; // نقوم بجلب القيمة الموجودة في العنصر video ونحولها إلى رقم // parseInt عبارة عن دالة تحول النص إلى رقم // "10" => 10 const adDuration = parseInt(randomAd.getAttribute('data-duration')); document.getElementById('counter1').innerHTML = adDuration ثم نستخدم قيمة الخاصية data-duration كذلك في حساب مدة عرض الإعلان وعرض العداد: if (mainTimer == 180) { counterTitle1.style.display = 'none'; counterTitle2.style.display = 'block'; counterTitle2.style.zIndex = '20'; counter1html.style.display = 'block'; counter1html.style.zIndex = '20'; counter1html.innerHTML = adDuration; // نغير قيمة العداد في كل ثانية mainVideo.pause(); randomAd.style.display = 'block'; randomAd.play(); } // إخفاء الإعلان عند إنتهاء المدة if (mainTimer == (180 - adDuration)) { randomAd.pause(); counterTitle2.style.display = 'none'; counter1html.style.display = 'none'; randomAd.style.display = 'none'; mainVideo.play(); } بهذا الشكل سوف يظهر في كل مرة إعلان عشوائي ونستطيع التحكم في مدة عرض كل إعلان من خلال تغير قيمة الخاصية data-duration1 نقطة
-
هناك عدة حزم مُعظم المُطورون يستخدمون إحداها لعمل هذه الجزئية في مشروعهم و من هذه الحزم أذكر: Laravel-permission التي تم تطويرها من طرف spatie و هم معروفين بتطوير عدة حزم مشهورة و مُستخدمة و يُطورون عليها بإستمرار. bouncer من تطوير Joseph Silber Laratrust هذه الحزم أكثر إستخداماً في هذا الموضوع و هي تُحدث بإستمرار حتى تدعم الإصدارات الجديدة من إطار laravel. إن كنت تريد إنجاز هذا الأمر فستتعب قليلاً و هذه الخطوات يُمكنك تطبيقها للوصول إلى ما تريد: إنشاء مودل لكل من Role و Permission و ملف تهجير لكل منهما: php artisan make:model Permission -m php artisan make:model Role -m كما تعلم فتمرير -m يعني أننا نريد إنشاء ملف تهجير أيضاً. تعديل ملفات التهجير: ملف تهجير الصلاحيات: <?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreatePermissionsTable extends Migration { public function up() { Schema::create('permissions', function (Blueprint $table) { $table->id(); $table->string('name'); // edit posts $table->string('slug'); //edit-posts $table->timestamps(); }); } public function down() { Schema::dropIfExists('permissions'); } } ملف تهجير الأدوار: <?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateRolesTable extends Migration { public function up() { Schema::create('roles', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('slug'); $table->timestamps(); }); } public function down() { Schema::dropIfExists('roles'); } } إنشاء ملفات تهجير الجداول الإضافية لربط الصلاحيات بالمستخدمين و ربط الصلاحيات بالأدوار و ربط الأدوار بالمُستخدمين: php artisan make:migration create_users_permissions_table --create=users_permissions php artisan make:migration create_users_roles_table --create=users_roles php artisan make:migration create_roles_permissions_table --create=roles_permissions و في ما يلي مُحتوى ملفات التهجير التي أنشأناها: جدول users_permissions: <?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateUsersPermissionsTable extends Migration { public function up() { Schema::create('users_permissions', function (Blueprint $table) { $table->unsignedBigInteger('user_id'); $table->unsignedBigInteger('permission_id'); //FOREIGN KEY CONSTRAINTS $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); $table->foreign('permission_id')->references('id')->on('permissions')->onDelete('cascade'); //SETTING THE PRIMARY KEYS $table->primary(['user_id','permission_id']); }); } public function down() { Schema::dropIfExists('users_permissions'); } } جدول users_roles: <?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateUsersRolesTable extends Migration { public function up() { Schema::create('users_roles', function (Blueprint $table) { $table->unsignedBigInteger('user_id'); $table->unsignedBigInteger('role_id'); //FOREIGN KEY CONSTRAINTS $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade'); //SETTING THE PRIMARY KEYS $table->primary(['user_id','role_id']); }); } public function down() { Schema::dropIfExists('users_roles'); } } جدول roles_permissions: <?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateRolesPermissionsTable extends Migration { public function up() { Schema::create('roles_permissions', function (Blueprint $table) { $table->unsignedBigInteger('role_id'); $table->unsignedBigInteger('permission_id'); //FOREIGN KEY CONSTRAINTS $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade'); $table->foreign('permission_id')->references('id')->on('permissions')->onDelete('cascade'); //SETTING THE PRIMARY KEYS $table->primary(['role_id','permission_id']); }); } public function down() { Schema::dropIfExists('roles_permissions'); } } نقوم بعملية التهجير: php artisan migrate إنشاء العلاقات بين النماذج علاقات النموذج Role: public function permissions() { return $this->belongsToMany(Permission::class,'roles_permissions'); } public function users() { return $this->belongsToMany(User::class,'users_roles'); } علاقات النموذج Permission: public function roles() { return $this->belongsToMany(Role::class,'roles_permissions'); } public function users() { return $this->belongsToMany(User::class,'users_permissions'); } إنشاء Trait لإستخدامه في النموذج User، في مٌجلد app نقوم بإنشاء مُجلد Permissions و نضع بداخله ملف HasPermissionsTrait.php ثم نقوم بتضمينه داخل النموذج User: <?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use App\Permissions\HasPermissionsTrait; class User extends Authenticatable { use HasFactory, Notifiable, HasPermissionsTrait; } يكون مُحتوى الملف HasPermissionsTrait بالشكل التالي: <?php namespace App\Permissions; use App\Models\Permission; use App\Models\Role; trait HasPermissionsTrait { public function givePermissionsTo(... $permissions) { $permissions = $this->getAllPermissions($permissions); if($permissions === null) { return $this; } $this->permissions()->saveMany($permissions); return $this; } public function withdrawPermissionsTo( ... $permissions ) { $permissions = $this->getAllPermissions($permissions); $this->permissions()->detach($permissions); return $this; } public function refreshPermissions( ... $permissions ) { $this->permissions()->detach(); return $this->givePermissionsTo($permissions); } public function hasPermissionTo($permission) { return $this->hasPermissionThroughRole($permission) || $this->hasPermission($permission); } public function hasPermissionThroughRole($permission) { foreach ($permission->roles as $role){ if($this->roles->contains($role)) { return true; } } return false; } public function hasRole( ... $roles ) { foreach ($roles as $role) { if ($this->roles->contains('slug', $role)) { return true; } } return false; } public function roles() { return $this->belongsToMany(Role::class,'users_roles'); } public function permissions() { return $this->belongsToMany(Permission::class,'users_permissions'); } protected function hasPermission($permission) { return (bool) $this->permissions->where('slug', $permission->slug)->count(); } protected function getAllPermissions(array $permissions) { return Permission::whereIn('slug',$permissions)->get(); } } إنشاء مُزود خدمة PermissionsServiceProvider: php artisan make:provider PermissionsServiceProvider نقوم بإضافة blade directive فيه و تعريف بوابة Gate من أجل كل صلاحية في الدالة boot: <?php namespace App\Providers; use App\Models\Permission; use Illuminate\Support\Facades\Blade; use Illuminate\Support\Facades\Gate; use Illuminate\Support\ServiceProvider; class PermissionsServiceProvider extends ServiceProvider { public function register() { // } public function boot() { try { Permission::get()->map(function ($permission) { Gate::define($permission->slug, function ($user) use ($permission) { return $user->hasPermissionTo($permission); }); }); } catch (\Exception $e) { report($e); return false; } //Blade directives Blade::directive('role', function ($role) { return "if(auth()->check() && auth()->user()->hasRole({$role})) :"; //return this if statement inside php tag }); Blade::directive('endrole', function ($role) { return "endif;"; //return this endif statement inside php tag }); } } بعد ذلك نقوم بتسجيل مُزود الخدمة في مصفوفة providers في الملف config\app.php: 'providers' => [ App\Providers\PermissionsServiceProvider::class, ], الآن تحتاج إلا إضافة بعض البيانات الإختبارية ملف بذر لكل من الصلاحيات و الأدوار و تضع فيه كل صلاحيات الموقع و بعض الأدوار التي تريد أن تكون ضمن تطبيقك و تربط الصلاحيات بالأدوار ثم تربط الأدوار بالمُستخدمين. <?php $admin_permission = Permission::where('slug','create-users')->first(); $manager_permission = Permission::where('slug', 'edit-users')->first(); //RoleTableSeeder.php $admin_role = new Role(); $admin_role->slug = 'admin'; $admin_role->name = 'Admin Role'; $admin_role->save(); $admin_role->permissions()->attach($admin_permission); $manager_role = new Role(); $manager_role->slug = 'manager'; $manager_role->name = 'Assistant Manager'; $manager_role->save(); $manager_role->permissions()->attach($manager_permission); $admin_role = Role::where('slug','admin')->first(); $manager_role = Role::where('slug', 'manager')->first(); $createUsers = new Permission(); $createUsers->slug = 'create-users'; $createUsers->name = 'Create Users'; $createUsers->save(); $createUsers->roles()->attach($admin_role); $editUsers = new Permission(); $editUsers->slug = 'edit-users'; $editUsers->name = 'Edit Users'; $editUsers->save(); $editUsers->roles()->attach($manager_role); $admin_role = Role::where('slug','admin')->first(); $manager_role = Role::where('slug', 'manager')->first(); $admin_perm = Permission::where('slug','create-users')->first(); $manager_perm = Permission::where('slug','edit-users')->first(); $admin = new User(); $admin->name = 'Samir Abboud'; $admin->email = 'samir@gmail.com'; $admin->password = bcrypt('password'); $admin->save(); $admin->roles()->attach($admin_role); $admin->permissions()->attach($admin_perm); $manager = new User(); $manager->name = 'Kamel Mahmoudi'; $manager->email = 'kamel@gmail.com'; $manager->password = bcrypt('password'); $manager->save(); $manager->roles()->attach($manager_role); $manager->permissions()->attach($manager_perm); يُمكنك إستخدام tinker لعمل test: $admin = User::where('email', 'samir@gmail.com')->first(); $admin->hasRole('admin'); // لفحص إن كان المُستخدم يملك الدور مدير $admin->givePermissionsTo('edit-users') // إعطاء المُستخدم صلاحية تعديل مُستخدمين $admin->can('create-users') // فحص المُستخدم إذا كان لديه صلاحية إنشاء مُستخدم في صفحات العرض يُمكن إستخدام التوجيه الذي أنشأناه: @role('admin') مرحبا مدير @endrole الخطوة الأخيرة هي إنشاء middleware لعدم السماح للمُستخدم الوصول إلى مسار مُحدد إذا لم يكن يملك الصلاحية: php artisan make:middleware RoleMiddleware php artisan make:middleware PermissionMiddleware <?php namespace App\Http\Middleware; use Closure; class RoleMiddleware { public function handle($request, Closure $next, $role) { if (!auth()->check()) { return redirect()->route('login'); } if(!auth()->user()->hasRole($role)) { abort(403); } return $next($request); } } <?php namespace App\Http\Middleware; use Closure; class PermissionMiddleware { public function handle($request, Closure $next, $permission) { if (!auth()->check()) { return redirect()->route('login'); } if(!auth()->user()->can($permission)) { abort(403); } return $next($request); } } بعد ذلك تقوم بتسجيل هاتين الmiddleware ضمن App\Http\Kernel.php في مصفوفة routeMiddleware: <?php protected $routeMiddleware = [ . . 'role' => \App\Http\Middleware\RoleMiddleware::class, 'permission' => \App\Http\Middleware\PermissionMiddleware::class, ]; الآن يتبقى فقط الإستخدام في ملف المسارات: <?php Route::group(['middleware' => 'role:admin'], function() { // مسارات المُستخدم الذي يملك الدور مدير }); أو من خلال باني المُتحكم: public function __construct() { $this->middleware('permission:create-users')->only(['create', 'store']); } إن كنت ستستخدم حزمة جاهزة فستجد كل هذه الخصائص موجودة فيها و ستجدها قد تم إختبارها بإستعمال الإختبارات الأحادية أيضاً.1 نقطة