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

Adnane Kadri

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

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

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

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

    52

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

  1. لعل السؤال "من أين أبدأ" واحد من أكثر الأسئلة شيوعا و اﻷكثر طرحا في المجال و رغم أن السؤال يطرح وحده بالنسبة لكل جديد على المجال إلا أني أظن أنه لا يجب سؤالها ابدا لأن كل لغة لها تخصص معين ولها طريقة كتابة وسياق خاص بها و لربما لها طريقة خاصة بالتعلم ! و لذلك قبل طرح هذا السؤال يجب أولا : اختيار مجال معين من مثل : تطوير مواقع الويب , تطوير تطبيقات الأندرويد , تطوير الألعاب و غيرها من المجالات . البحث عن لغات هذا المجال الأكثر شيوعا و استعمالا وافهم وظيفة كل لغة تخص هذا المجال . يفضل تعلم مبادئ البرمجة و التفكير المنطقي قبل التوغل في أي مجال . أشياء من مثل هاته يمكن إكتسابها و تعلمها عن طريق تعلم الخوارزميات و بنية البيانات . يمكنك الان تعلم لغات هذا المجال عن طريق دورات أو معاهد تكوينية . يمكنك إلقاء نظرة على دورات الأكاديمية هنا . التطبيق العملي و الاختبار و التجربة و الكثير منه . يساعدك كل من المراحل السابقة على تحديد هدفك و توضيحه أكثر و أكثر , و هو ما ستحتاج إليه على طول مسيرتك في المجال . كما أن هذا سيولد لديك الكثير من الأسئلة التي ستوسع نظرتك للمجال و تطور من ثروتك النظرية مما سيدفعك أسرع و أسرع للتطبيق العملي و الإنتاج .
  2. لإستعمال خدمات zoom في تطبيق لارافيل يجدر بك فتح حساب مطور في zoom لإستعمال الواجهة البرمجية الخاصة بهم بشكل طبيعي . يمكنك قراءة توثيق الواجهة البرمجية كاملا هنا . كما يمكنك إستعمال الـ sdk الخاص بـ zoom للاستفادة من كامل المميزات و الخدمات التي توفرها . يمكنك قراءة التوثيق كاملا هنا . كما يمكنك إستعمال هاته الحزمة للإستفادة من بعض الخدمات بشكل أبسط . كما يمكنك الاستزادة بقراءة هاته المقالات حول نفس الموضوع : كيفية إضافة zoom API إلى تطبيق لارافيل كيفية تضمين الـ embeded code الخاص بأي ملتقى zoom (مقالة). كيفية تضمين الـ embeded code الخاص بأي ملتقى zoom (نقاش في منتديات zoom). إدارة ملتقيات زوم عن طريق تطبيق لارافيل .
  3. لتوسيط الصورة يمكنك تعديل محاذاة العنصر الحاوي لعنصر الصورة ليحمل قيمة المحاذاة إلى الوسط : .img-container{ text-align: center; } و لعمل عرض شرائح سنحتاج إنشاء حاوي لعناصر الشرائح و أزرار جانبية لكل من التالي و السابق و بعض عناصر التصفح تكون على شكل نقط و دوائر , ستكون بنية الـ html على نحو مشابه : <!-- حاوي عرض الشرائح --> <div class="slideshow-container"> <!-- الشرائح --> <div class="mySlides fade"> <img src="img1.jpg" style="width:100%"> </div> <div class="mySlides fade"> <img src="img2.jpg" style="width:100%"> </div> <div class="mySlides fade"> <img src="img3.jpg" style="width:100%"> </div> <!-- أزرار التالي و السسابق --> <a class="prev" onclick="plusSlides(-1)">❮</a> <a class="next" onclick="plusSlides(1)">❯</a> </div> <br> <!-- دوائر التصفح --> <div style="text-align:center"> <span class="dot" onclick="currentSlide(1)"></span> <span class="dot" onclick="currentSlide(2)"></span> <span class="dot" onclick="currentSlide(3)"></span> </div> سنحتاج لإضافة بعض الـتنسيقات : /* حاوي عرض الشرائح */ .slideshow-container { max-width: 1000px; position: relative; margin: auto; } /* نححتاج إخفاء الصور في الحالة الافتراضية */ .mySlides { display: none; } /* أزرار التالي و السابق */ .prev, .next { cursor: pointer; position: absolute; top: 50%; width: auto; margin-top: -22px; padding: 16px; color: white; font-weight: bold; font-size: 18px; transition: 0.6s ease; border-radius: 0 3px 3px 0; user-select: none; } /* تحديد زر التالي ليظهر بيمين الصفحة */ .next { right: 0; border-radius: 3px 0 0 3px; } /* المؤشرات */ .dot { cursor: pointer; height: 15px; width: 15px; margin: 0 2px; background-color: #bbb; border-radius: 50%; display: inline-block; transition: background-color 0.6s ease; } /* انيميشن */ .fade { -webkit-animation-name: fade; -webkit-animation-duration: 1.5s; animation-name: fade; animation-duration: 1.5s; } @-webkit-keyframes fade { from {opacity: .4} to {opacity: 1} } @keyframes fade { from {opacity: .4} to {opacity: 1} } الان لن يظهر أي شيء لأن كل الشرائح مخفية افتراضا , و لعمل التفاعلية سنحتاج تطبيق المنطق التالي وفق الجافاسكربت : عند الضغط عن زر التالي سنقوم بتحديد الشريحة الما بعد الشريحة الحالية و إظهارها . عند الضغط عن زر السابق سنقوم بتحديد الشريحة الما قبل الشريحة الحالية و إظهارها . و سنستعمل فيهما دالة plusSlide لنقوم بتمرير رقم 1 معبرا عن التالي , و 1- معبرا عن السابق . عند الضغط عن دائرة سنقوم بتحديد الشريحة المرافقة لها و إظهارها . و سنستعمل في هذا دالة currentSlide لنقوم بتمرير الرقم الترتيبي للشريحة المراد تفعيلها . و لإظهار الشريحة لن نحتاج إلا لـ : تحديد الرقم الترتيبي للشريحة المراد تفعيلها . إخفاء كامل الشرائح عن طريق إعطاءهم القيمة none في الخاصية display . إظهار الشريحة المفعلة عن طريق إعطاءها القيمة block في الخاصية display . فيكون كود الجافاسكربت كالتالي : var slideIndex = 1; // الشريحة الحالية showSlides(slideIndex); // إستدعاء الدالة المسؤولة عن عرض الشرائح // الدالة الخاصة بأزرار التالي و السابق function plusSlides(n) { showSlides(slideIndex += n); } // الدالة الخاصة برموز الاتجاهات function currentSlide(n) { showSlides(slideIndex = n); } // الدالة المسؤولة عن عرض الشرائح function showSlides(n) { var i; var slides = document.getElementsByClassName("mySlides"); // تحديد كامل الشرائح var dots = document.getElementsByClassName("dot"); // تحديد كامل الدوائر if (n > slides.length) {slideIndex = 1} // تحديد الشريحة الاولى كمفعلة if (n < 1) {slideIndex = slides.length} // تحديد الشريحة الأخيرة كمفعلة for (i = 0; i < slides.length; i++) { slides[i].style.display = "none"; // إخفاء كامل الشرائح } slides[slideIndex-1].style.display = "block"; // تعديل تنسيق الشريحة المفعلة } و بالطبع فإن هذا هو المنطق البسيط للعملية , يمكنك تخصيص بنية الـ html و تنسيقها و تفاعليتها بكل حرية .
  4. يمكنك إستعمال التابع where لتحديد شرط التساوي بين الرقم الوزاري للمستخدم الحالي و الموظفين من جدول الموظفين : $no_ministry = Auth::user()->no_ministry; $selectemployees = Employee::select('id' , 'id_no' , 'name' , 'no_ministry' , 'staff' , 'phone') ->where('no_ministry' ,$no_ministry) ->get();
  5. سنحتاج في هذا توليد token و تخزينه بقواعد البيانات و إخفاءه عن المستخدم . و إرساله مرة أخرى إلى البريد الالكتروني للشخص أو رقم هاتفه . إما كسلسلة نصية و التحقق من مطابقتها . أو إرسالها كرابط بمتغير و ليكن token يحمل token هذا المستخدم . و لارافيل تجعل العملية أبسط و أبسط عن طريق الخطوات التالية : تحضير النموذج User : لنتأكد أولا من أن النموذج ينفذ الصنف MustVerifyEmail : <?php namespace App; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; class User extends Authenticatable implements MustVerifyEmail { use Notifiable; // ... } سيقوم هذا بإرسال رابط تحقق لكل بريد إلكتروني يخص عضو يقوم بالتسجيل حديثا . إعتبار قواعد البيانات : نتأكد من إمتلاك جدول المستخدمين users على عمود email_verified_at . ثم تنفيذ أمر التهجير : php artisan migrate تحضير المسارات : يتضمن Laravel صنف VerificationController الذي يحتوي على المنطق الضروري لإرسال روابط التحقق والتحقق من رسائل البريد الإلكتروني . و لتسجيل المسارات الضرورية لهذا المتحكم ، تأكد أن تقوم بتمرير خيار التحقق إلى التعريف Auth :: route : Auth::routes(['verify' => true]); حماية المسارات : يمكن استخدام طبقات وسيطة Middlewares جاهزة و معدة مسبقا من قبل لارافل للمسارات للسماح للمستخدمين الذين تم التحقق منهم فقط بالوصول إلى مسار معين . و كل ما عليك فعله هو إرفاق الطبقة الوسيطة verified بتعريف المسار : Route::get('profile', function () { // هذا المسار قابل للوصول من قبل المستخدمين المتحقق من بريدهم فقط })->middleware('verified'); ملفات العرض : لإنشاء كل ملفات العرض الضرورية للتحقق من البريد الإلكتروني ، يمكنك استخدام حزمة laravel/ui : composer require laravel/ui php artisan ui vue --auth يقوم هذا بوضع كل ملفات العرض الخاصة بالتحقق من البريد الإلكتروني في : Resources / views / auth / verification.blade.php. بحيث يمكنك تخصيصها كما تشاء .
  6. هل يمكنك وصف المشكلة بشكل أكثر دقة ؟ كما أنه قد يكون من الجيد تضمين بعض الشيفرات البرمجية و الأكواد التي تظن أنها مسببة للمشكلة . يمكنك القراءة أكثر عن إرشادات الاستخدام .
  7. صحيح .خدمات Pusher مدفوعة لكنها تقدم في عرضها المجاني sandbox إمكانية تمرير 200 ألف رسالة بشكل يومي . و هو رقم جد مناسب في مثل حالتك .
  8. يمكن استعمال دريفر Pusher لتحقيق الغرض . لنقم بإتباع الخطوات التالية : 1. تثبيت حزمة خادم Pusher في تطبيق الللارافل : composer require pusher/pusher-php-server 2, إنشاء تطبيق 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 3. نقوم بإنشاء حدث معين : php artisan make:event NewTemperatureRecord سنلاحظ إضافة ملف NewTemperatureRecord.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 NewTemperatureRecord 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('temperature-channel'); } } إنشاء متحكم يختص بالعملية : php artisan make:controller TemperatureController ثم لنتأكد من وضع المحتوى التالي به : <?php namespace App\Http\Controllers; use Illuminate\Http\Request; class TemperatureController extends Controller { public function update(Request $request) { // تحضير مصفوفة بيانات لتمريرها $data['temp'] = $request->temp; // Notify إثارة الحدث event(new App\Events\NewTemperatureRecord($data)); } } و لتأكد من تعريف المسارات اللازمة , واحد لعرض الصفحة وواحد لإرسال طلبات التحديث : // web.php Route::post('temperature','TemperatureController@update'); Route::view('temperature', 'temperature'); ثم بملف ما بالواجهة الأمامية سيكون علينا فقط : الإشتراك في هاته القناة + الإستماع لأحداث هاته القناة : <!-- temperature.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('temperature-channel'); // Notify الاستماع للحدث channel.bind('App\\Events\\NewTemperatureRecord', function(data) { // إن تم اثارة الحدث قم بعرض البيانات document.querySelector('#temp').textContent = data.temp; }); </script> </head> <body> <div id="temp"> 35 </div> </body> بدون تحديث الصفحة سيكون علينا إرسال طلبات أجاكس إلى المسار temp/ بالفعل POST و سنلاحظ تحدث القيمة في صفحة العرض temp/ .
  9. يفضل فهم مبدأ عمل الالية و منطقها و إنشاء التطبيق على طريقتك الخاصة . ولنقل أنه يمكننا ذلك عن طريق الإستعانة بمفهوم الويب سوكيت web sockets . (يمكنك التعرف أكثر على هذا المفهوم هنا ) بحيث نقوم : - في الخادم (في الواجهة الخلفية للتطبيق) بإنشاء قناة أو قنوات بحدث أو أحداث معينة , ثم تمرير البيانات عبر هاته القنوات مستهدفين أحداثا معينة . - في المتصفح (في الواجهة الأمامية للتطبيق) بالإشتراك في هاته القنوات و الإستماع لهاته الأحداث و التصرف بناء عليها (كأن يتم عرض الرسائل بشكل ) . مثال عن الإستعمال : لما تكتب سارة رسالة بمربع نص و تضغط زر الإرسال إلى شيماء سيتم إرسال طلب HTTP إلى الخادم . سيقوم الخادم بمعالجة طلب سارة و تسجيل الرسالة بقواعد البيانات , و في نفس الوقت سيقوم بإثارة الحدث المرتبط بالعملية و ليكن NewMessageEvent ضمن القناة ShaimaaChannel . شيماء مشتركة في القناة ShaimaaChannel و تستمع لأية إثارة لأحداثها , ففي حالة إثارة أية حدث ستقوم بالتقاط البيانات التي تم تمريرها عبره دون تحديث الصفحة . لما يتم إثارة الحدث NewMessageEvent ضمن القناة ShaimaaChannel ستقوم الواجهة الأمامية لشيماء بالتصرف بناء على البيانات التي تلتقطها عبر هاته القناة في هذا الحدث . كأن تقوم بإظهار تنبيه نصي . و قد نحتاج إلى دريفر لمساعدتنا في تمرير البيانات و إنشاء القنوات من مثل 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 NewMessageEvent سنلاحظ إضافة ملف NewMessageEvent.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 NewMessageEvent 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('chaimaa-sara-channel'); } } إنشاء متحكم يختص بالعملية : php artisan make:controller MessagesController ثم لنتأكد من وضع المحتوى التالي به : <?php namespace App\Http\Controllers; use Illuminate\Http\Request; class MessagesController extends Controller { public function send(Request $request) { // تحضير مصفوفة بيانات لتمريرها $data['message'] = $request->message; // Notify إثارة الحدث event(new App\Events\NewMessageEvent($data)); } } سيكون علينا تعريف مسارين , مسار لإستهداف تابع المتحكم MessagesController و اخر لعرض الصفحة chat.blade.php : //web.php Route::post('chat','MessagesController@send'); Route::view('chat', 'chat'); ثم بملف ما بالواجهة الأمامية سيكون علينا فقط : الإشتراك في هاته القناة + الإستماع لأحداث هاته القناة : <!-- chat.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('sara-chaima-channel'); // Notify الاستماع للحدث channel.bind('App\\Events\\NewMessageEvent', function(data) { // إن تم اثارة الحدث قم بعرض البيانات alert(data.message); }); </script> </head> بدون تحديث الصفحة سيكون علينا إرسال طلبات أجاكس من نموذج سارة إلى المسار chat/ بالفعل POST و سنلاحظ ظهور الرسالة في مسار chat/ . المسار الأول يمثل الطلب الذي أرسلته سارة , و المسار الثاني يمثل صفحة عرض الرسائل بالنسبة لشيماء . و بالطبع فإن هذا هو الشكل الأبسط للعملية , يمكن تطوير العملية كأن نقوم بتخصيص طريقة العرض في قائمة رسائل منظمة بإنزلاق أفقي مع كل تحديث . قد نضيف أيضا إشعارا جانبيا في كل إثارة للحدث , كما يمكن تخصيص قنوات خاصة بكل مستخدم منفرد أو نقوم بتمرير بيانات أخرى و تطبيق العديد و العديد من الأفكار عليها .
  10. يحدث هذا لأنك تعطي عنصري الفقرتين عرضا أكبر من عرض الشاشة المتبقي : 600 بكسل . و هذا في ملف style.css , لاحظ : section.phara .container .row p.aa { font-size: 18px; font-weight: 300; line-height: 35px; padding-bottom: 50px; border-bottom: 1px solid #fff; width: auto; /*هنا*/ } section.phara .container .row p.bb { font-size: 18px; font-weight: 300; line-height: 35px; padding-top: 50px; width: auto; /*هنا*/ } للعنصرين : <section class="phara"> <div class="container"> <div class="row "> <div class="col-md-12 ml-auto"> <h5> Diagoona HTML Template </h5> <p class="aa"> ... </p> <p class="bb"> ... </p> <button type="button" name="button"> Continue... </button> </div> </div> </div> </section> و لإصلاح ذلك لن نحتاج إلا لإسناد قيمتين مناسبتين أكثر أو يفضل عرضا افتراضيا للخاصية width : width: auto; أما عن إضافة الطبقة السوداء فيمكنك إنشاء عنصر بالصف overlay يوضع أسفل عنصر الـ footer : <footer> <div class="copyright"> <p>Copyright 2020 Diagoona Co. | Design: TemplateMo</p> </div> </footer> <div class="overlay"></div> و ليحمل التنسيقات التالية : /* إضافة طبقة سوداء شفافة ثابتة و مربعة ذات طول كامل و نصف عرض*/ .overlay{ position: fixed; height: 100vh; width: 57vw; background-color: rgba(0,0,0,0.16); top: 0px; right:0px; z-index: -99; /* لضمان بقاء باقي العناصر قابلة للوصول */ } /* إضافة مثلث جانبي بنفس طول مربع الطبقة السابقة وبنفس درجة الشفافية */ .overlay::before{ content: ''; position: absolute; top: 0px; left: -150px; height: 100%; border-bottom: 100vh solid rgba(0,0,0,0.16); border-left: 150px solid transparent; } و لتوضيح منطق العملية لاحظ كيفية تداخل التركيبتين : ------------- - | | |\ | المربع | + | \ | | | م\ | | | ثلث\ ------------- ------
  11. لن يمكنك فعل ذلك بإستعمال التابع load , لأن هذا التابع يسمح بتحميل HTML أو محتوى نصي من الخادم ثم إضافته إلى عنصر DOM . أما لتحقيق غرضك فلن نحتاج إلا لتحديد العنصر الحاوي للمحتوى ثم إضافته إلى العنصر div . سيمكن إستعمال التابع append لهذا . رغم أن فكرة تحميل محتوى موجود داخل الـ div و إعادة تضمينه في نفس العنصر غير منطقية إلا أن الشيفرة ستكون مشابه للتالي : <div id="load_posts"></div> <script> setInterval(function(){ var content = $('#load_posts').html(); // $('#load_posts').html(''); لحذف المحتوى و إعادة تحميله $('#load_posts').append(content); }, 1000); </script>
  12. أظن أنه ينبغي عليك أولا معرفة المميزات التي قد تستفيد منها في تعلمك لسكراتش , ثم سيمكنك الحكم إن كان تعلم ذلك واجبا أم لا بالنسبة لك , رغم أن تعلمه يقترح و يفضل . لنقل أن من بعض مميزاته الاتي : هدفه : حيث أن تعلم سكراتش سيقوم بتبسيط تعاملك مع منطق لغات البرمجة و يجعل ذلك مألوفا بشكل كبير . تعلمه : تعلم سكراتش سهل و ممتع نوعا ما , أي أن طريق تعلمه لن يكون مملا بعض الشيء. يطور مهاراتك : واحدة من أهم أهداف سكراتش هي في تطوير مهاراتك في إدارة المشاريع و تسييرها . يطور منطقك : كما أنه سيساعدك بشكل كبير في تطوير المهارات التحليلية و المنطقية لديك . ممتع و تفاعلي : إستعماله مجاني و ذو واجهة تفاعلية .
  13. يمكنك تحريك الشريط الجانبي للأسفل تماما مباشرة بعد نجاح عملية تحميل أية رسائل جديدة و إضافتها إلى الوثيقة . أي إلى الدالة appendMessage . قد لا نحتاج الدالة getMessages في هاته العملية . أي أننا لا يجب أن نرغم المستخدم أن يكون الشريط الجانبي في أسفله تماما و دوما , و إنما أن يتم عمل التحريك التلقائي للشريط الجانبي بعد كل تضمين لعنصر رسالة جديد , و ذلك لعرضها . أي أن الشيفرة الخاصة بالعملية ستتبع المنطق التالي : const messages = document.getElementById('div_show_message'); function appendMessage() { const message = document.getElementsByClassName('message')[0]; const newMessage = message.cloneNode(true); messages.appendChild(newMessage); scrollToBottom(); } function scrollToBottom() { messages.scrollTop = messages.scrollHeight; } scrollToBottom();
  14. كون الدالتين تستعملان نفس الحدث فلن نحتاج إلا لوضعهما بالمكان الصحيح بدل تكرار الكود : أي بعد نجاح طلب الأجاكس , و المقصود هنا هو التابع success . نقوم في الكود الأول بإرسال طلب أجاكس لتخزين بيانات الرسالة بعد تقديم النموذج , لاحظ : $j('#messages_form') .on('submit', function(event) { event.preventDefault(); if ($j('#username') .val() != '' && $j('#message') .val() != '') { var form_data = $j(this) .serialize(); $j.ajax({ url: "send_messages_form.php", method: "POST", data: form_data, success: function(data) { $j('#messages_form')[0].reset(); load_unseen_notification(); } }); } else { alert(" رسالة فارغة رجاءا اكتب شىء "); } }); في حين أننا نقوم بعرض رسالة في قسم الرسائل في النجاح في الكود الثاني , لاحظ : success: function(response) { $j("#norec") .hide(); $j("#div_show_message") .append(response); $j('#messages_form') .trigger('reset'); }, error: function(xhr, ajaxOptions, thrownError) { alert(thrownError); } أي أن دمج الكودين لن يكون إلا في ما بعد نجاح طلب الأجاكس , و بالتالي : $j('#messages_form') .on('submit', function(event) { event.preventDefault(); if ($j('#username') .val() != '' && $j('#message') .val() != '') { var form_data = $j(this) .serialize(); $j.ajax({ url: "send_messages_form.php", method: "POST", data: form_data, success: function(data) { $j('#messages_form')[0].reset(); load_unseen_notification(); // عرض الرسالة $j("#norec") .hide(); $j("#div_show_message") .append(data); $j('#messages_form') .trigger('reset'); }, // إضافة حالة فشل الطلب error: function(xhr, ajaxOptions, thrownError) { alert(thrownError); } }); } else { alert(" رسالة فارغة رجاءا اكتب شىء "); } }); ثم كخطوة أخيرة لن تحتاج إلا تحريك الشريط الجانبي للأسفل , و بالطبع سيكون ذلك بعد نجاح طلب الأجاكس , أي أن العملية ستتبع منطقا واحد . وهو نفس المنطق المتبع في الكود المرفق . يمكنك المحاولة بقيام ذلك ثم سيمكن مساعدتك في حالة الاستعصاء .
  15. من الطبيعي جدا أن تجد بعض الصعوبة في عمل أي تطبيق عملي , ولكنه سيجب عليك تخطي هاته الصعوبة بالمحاولة و التكرار . و لذلك فإنه لن يكون لتقديم الكود أي منفعة . عوضا عن ذلك يمكنك الإنطلاق بالفعل في صياغة الكود الخاص بك , و سنساعدك في ذلك .
  16. لما لا تقوم فقط بإستعمال واحدة من الحزم التي تستعمل طريقة omnipay لتوحيد عمل بوابات الدفع لإضافة بوابة دفع بايسيرا كونك تطبيقك لارافيل ؟ يقترح : semyonchetvertnyh/omnipay-paysera . povils/omnipay-paysera . و لن يكون ذلك مشكلة إن قمت بالتعامل مع أي من حزمها من قبل . كما يمكنك أيضا إستعمال حزمة adumskis/laravel-paysera (لا تنتمي لمجموعة حزم omnipay) و عموما ستكون ملزما بإتباع الخطوات : فتح حساب بايسيرا , خاص أو تجاري (سيكون هذا ضروريا في عمليات توثيق التعاملات). ستحتاج طلب خدمة بوابة الدفع : يمكنك القيام بذلك مجانًا عن طريق تسجيل الدخول إلى حسابك والانتقال إلى الإعدادات > إعدادات الملف الشخصي > إدارة الخدمة . قم بإنشاء مشروع , يمكنك اتباع الخطوات الموضحة في الفيديو التالي . قم بربط بوابة الدفع , إما عن طريق الإضافة التي توفرها بايسيرا , أو عن طريق الواجهة البرمجية . يمكن الإستعانة بواحدة من الحزم السابقة أو إستعمال الواجهة بشكل مباشر .
  17. الكود خاصتك غير منظم جيدا و لذلك هو غير واضح أو غير قابل للقراءة بشكل عادي . و لكن لتنفيذ الفكرة التي تصفها يمكنك عمل تحديث للصفحة و التحريك التلقائي لشريط التمرير بعد نجاح اظهار الرسائل . و لنتأكد من إتباع مبدأ فصل الاهتمامات لتنظيم العملية أكثر , سيتبع الكود المنطق الموصوف سابقا على نحو مشابه : function adjustScroll() {} function loadUnseenNotifications() { // بعد ارسال طلب الاجاكس لتحميل اشعار بالرسائل الغير مقروءة if (data.unseen_notification > 0) { $j('.count').html(data.unseen_notification); // تحميل الرسائل و عرضها ضمن الشاشة ان كانت الرسائل أكثر من 1 loadMessages(); } } function loadMessages() { // بعد تحميل الرسائل نحتاج تحديث الصفحة و عمل الاسكرول التلقايئ adjustScroll(); } setInterval(function() { loadUnseenNotifications(); }, 1000); أي : يتم التحقق كل ثانية إن كان هنالك إشعارات رسائل غير مقروءة . ان كان نعم سيتم تحديث عد الاشعارات غير المقروءة + تحميل رسائل جديدة . سيقوم تحميل رسائل جديدة تلقائيا بعد انتهاء طلب الأجاكس بتحديث الصفحة و عمل اسكرول تلقائي للأسفل لاخر رسالة تم تحميلها . و رغم أن تطبيقات الدردشة تستعمل تقنيات أحدث إلا أنه يعتبر تطبيقا عمليا جيدا . بالطبع فإن العملية وصفية , لكن يمكنك صياغة الكود الخاص بك وفق الخطوات السابقة .
  18. قد يختلف الأمر قليلا خصوصا لو كنت قادم من نظام تشغيل ويندوز , فلن تجد واجهة تفاعلية تخبرك بما عليك فعله . و سيتم كل ذلك عن طريق التارمنل . عن طريق ما يعرف بمدراء الحزم . و بالطبع فإن الأمر ليس دستورا ثابتا , فهو يختلف من توزيعة لينكس إلى أخرى , و من مدير حزم إلى مدير اخر . و لنأخذ على سبيل المثال توزيعة ubuntu الغنية عن التعريف . في ubuntu يمكننا تثبيت البرنامج بـ 3 طرق مختلفة : عن طريق مركز برمجيات أوبونتو أو Ubuntu Software Center : وهو عبارة عن برنامج يوفر واجهة تفاعلية يسهل من عليها استعراض البرامج المتوفرة و تثبيتها عن طريق ضغطة زر . قد توفر توزيعات أخرى نفس الفكرة . عن طريق snap : وهو مدير حزم يقوم بتحميل الحزم و تحميلها من متجر snap , يتوفر snap في عديد من توزيعات لينكس من مثل فيدوار و لينكس مينت . و سنحتاج للتارمنل في التعامل معه لأن snap لا يوفر واجهة تفاعلية . يتم تثبيت البرامج عن طريقه بأوامر مشابهة : sudo snap install <app-name> عن طريق مدير الحزم apt : sudo apt install <app-name> و كوننا قد قمنا بثتبيت البرنامج لن يجعل من المنطقي ان نقوم بتثبيته كل مرة غرض تشغيله , و بالتالي فإنك لن تحتاج ذلك و يكفي تثبيته مرة واحدة . و لتشغيل البرنامج نقوم إما بطباعة اسمه في التارمنل أو بالتصفح إليه في قائمة البرامج . كما يمكنك إنشاء أيقونة سطح المكتب للوصول السهل إليها .
  19. يحاول الخطأ إخبارك أن المشروع الذي تحاول تطبيق الأمر فيه ليس مستودع git , و لذلك سنحتاج تحويله لذلك قبل عمل أي أوامر git عليه . يمكنك ذلك عن طريق الأمر : git init قد تحتاج أيضا ربط ملفات مشروعك مع مستودعك البعيد عن طريق الأمرين : git remote add origin https://your_gitrepo/some_repo ثم : git branch -M main بعد ذلك يمكنك تطبيق الأوامر : git add -A git commit -m "init commit" git push -u origin main
  20. هلا قمت بطباعة الأمور التالية على التوالي : git checkout -b myBranch git checkout master git merge myBranch git branch -d myBranch سيقوم هذا بتبديل الفروع أولا ثم استعادة ملفات المستودع الحالي و دمجها مع ملفات مشروعك , ثم إنشاء فرع جديد للدفع إليه . يمكنك بعد هذا إنشاء commit بطريقة عادية : git commit -m "my commit" ثم الدفع إلى الفرع الجديد في مستودعك : git push -u origin myBranch
  21. ينغبي الفهم أولا أن قاعدة البيانات ، ليست هي إلا مجموعة بيانات أو معلومات يتم تنظيمها لتسهيل تخزينها , استرجاعها , تعديلها وحذفها بالتزامن مع عمليات معالجة البيانات المختلفة . عادة ما يتم ذلك عن طريق نظم إدارة قواعد البيانات , و يشار إلى النظام نفسه مع البيانات بقواعد البيانات . أي أن الهدف واحد و السبل تختلف . عادةً ما يتم نمذجة هاته البيانات الموجودة ضمن الأنواع الأكثر شيوعًا من قواعد البيانات الشغالة اليوم في : صفوف وأعمدة في سلسلة من الجداول لجعل المعالجة والاستعلام عن البيانات فعالا و أبعد قليلا عن التجريد . بحيث يمكن بعد ذلك الوصول إلى البيانات وإدارتها وتعديلها وتحديثها والتحكم فيها وتنظيمها بسهولة . تستخدم معظم قواعد البيانات لغة الاستعلام المهيكلة (SQL) لكتابة البيانات والاستعلام عنها أو إدارتها . يوجد العديد من أنواع قواعد البيانات المختلفة التي يمكن لمؤسسة أو برنامج ما إتباعها نذكر منها : قواعد بيانات علائقية Relational databases : يمكن اعتبارها الأكثر شيوعا الان . بحيث يتم تنظيم العناصر الموجودة في قاعدة البيانات العلائقية كمجموعة من الجداول ذات الأعمدة والصفوف التي يمكن لها أن تحمل علاقات فيما بينها . قواعد بيانات كائنية التوجه Object-oriented databases : بحيث يتم تنظيم البيانات بشكل كائنات يسهل التعامل معها بمنطق مشابه لمنطق البرمجة الكائنية . قواعد بيانات موزعة Distributed databases : يتم تنظيم البيانات بشكل ملفات تكون موزعة على مكانين أو أكثر . قواعد بيانات غير علائقية NoSql: تعتبر الأفضل من ناحية تخزين البيانات غير المهيكلة unstructured و شبه المنظمة semistructured . واحدة من الأكثر شيوعا الان . طبعا ليست هاته الأنواع الوحيدة فقط بل يوجد الكثير غيرها .. كل منها ينفرد بمنطقه و طريقة معالجته للبيانات و تخزينها . و مثلما تم الإشارة فإنه يتم إدارتها عن طريق نظم إدارة قواعد البيانات (database management system) اختصارا : DBMS .بحيث يعمل كواجهة بين قاعدة البيانات والمستخدمين النهائيين أو البرامج ، مما يسمح للمستخدمين باسترداد وتحديث وإدارة كيفية تنظيم المعلومات وتحسينها . و أيضا الإشراف والتحكم في قواعد البيانات ، يوفر هذا مجموعة متنوعة من العمليات الإدارية مثل مراقبة الأداء والضبط والنسخ الاحتياطي والاسترداد و غيرها . و لنأخذ MySql كمثال : MySQL هو نظام إدارة قواعد بيانات علائقية مفتوح المصدر يعتمد على SQL . تم تصميمه وتحسينه لتطبيقات الويب . كانت وراء بعض أفضل مواقع الويب و تطبيقات الويب في العالم ، أمثلة : Airbnb و Uber , LinkedIn , Facebook , Twitter , YouTube . و رغم أنها بالفعل خسرت بعض شعبيتها في الأعوام الأخيرة إلا أنه لا بأس في تعلمها و التعرف عليها و العمل بها , خصوصا في سوقنا العربي فهي : سهلة التعلم. ما تزال شائعة ومهيمنة نوعا ما . توثيقها السهل و وفرة المعلومات حولها . متوفرة بشكل افتراضي في أغلب الاستضافات . مجانية . يمكنك القراءة عن Mysql أكثر هنا . يمكنك أيضا التعرف أكثر على قواعد البيانات على بعض من نظم إدارة قواعد البيانات هنا . كما يمكنك الاستزادة بقراءة بعض من مقالات الأكاديمية بهذا الشأن : الأنواع السبعة لروابط الجداول في SQL مقارنة بين أنظمة إدارة قواعد البيانات العلاقية: SQLite مع MySQL مع PostgreSQL شرح الفروقات بين قواعد بيانات SQL ونظيراتها NoSQL
  22. يمكنك إضافة الخاصيتين data-toggle و data-target لوسم الصورة أو العمود : data-toggle="modal" data-target="#mymodal" سيقوم هذا بفتح المودل بعد الصغط على الصورة أو العمود .
  23. تأكد أن تقوم بحذف ملف index.lock داخل مجلد git. , يمكنك ذلك عن طريق الأمر : rm -f .git/index.lock و في حال ظهر معك خطأ على هذا النحو : 'rm' is not recognized as an internal or external command يمكنك طباعة الأمر : del -f .git/index.lock .. قد نتسبب في هذا المشكل عندما نحاول تطبيق أمري أو عمليتي git في نفس الوقت , و في الغالب تكون واحد عن طريق المحرر vsCode و الاخر عن طريق موجه الأوامر أو التارمنل . و حذف ملف index.lock سيقوم بإلغاء أي عمليات أخرى معدا الحالية و بالتالي حل المشكل.
  24. يمكنك معاملة الصور و أيقونات كزر فتح المودل , سيتبع الكود منطقا مشابها : <button type="button" class="btn" data-toggle="modal" data-target="#mymodal"> <img src="img1.png" /> </button> <button type="button" class="btn" data-toggle="modal" data-target="#mymodal"> <img src="img2.png" /> </button> <button type="button" class="btn" data-toggle="modal" data-target="#mymodal"> <img src="img3.png" /> </button> <button type="button" class="btn" data-toggle="modal" data-target="#mymodal"> <img src="img4.png" /> </button> <!-- المودل يبدأ هنا --> و بالطبع ستحتاج إرسال طلب الأجاكس بشكل منفصل . سنحتاج أولا تعريف النموذج و إضافة حدث عن طريق الجافاسكربت : var myForm = document.querySelector('#myform'); myForm.addEventListener('submit' ,function(e){ e.preventDefault(); // منع تحديث الصفحة sendAjaxRequest(); }); function sendAjaxRequest() { // سيتم إرسال طلب الاجاكس هنا } حيث أن الدالة sendAjaxRequest ستكون المسؤولة عن إرسال هذا الطلب . function sendAjaxRequest() { // XMLHttpRequest تعريف نموذج عن الكائن var xhttp = new XMLHttpRequest(); // جلب البيانات من النموذج var formData = new FormData(document.querySelector('#myForm')) xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { alert('تم إرسال الطلب'); } }; xhttp.open("POST", "http://path.to/endPoint/example", true); // فتح طلب xhttp.send(formData); // إرسال طلب }
×
×
  • أضف...