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

سمير عبود

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

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

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

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

    34

أجوبة بواسطة سمير عبود

  1. نتأسف على التأخر في الرد، لكن يبدو من خلال الصور التي أرفقتها أنه لا يوجد أخطاء في الكود، يبدو فقط أنك تكتب في ملف database آخر إسمه power بدون لاحقة و تفتح ملف power.db حاول فقط تعديل السطر 3 إلى:

    let db = new sqlite3.Database('power.db', function(err) {

    ثم أغلق برنامج DB Browser، ثم أعد تنفيذ الملف:

    node powerjs.js

    بعد ذلك أعد تشغيل برنامج DB Browser ثم فتح ملف قاعدة البيانات power.db يُفترض أن تجد الجداول التي أنشأتها.

    • أعجبني 1
  2. بتاريخ 6 دقائق مضت قال Abdullah Baaqail:

    شكرا الحل ضبط ولكن بعد عمل إنشاء لحساب جديد يظهر هذا الخطأ 

    المشكلة هنا بسبب أنك لم تضبط إعدادات البريد الإلكتروني، فعند تسجيل الدخول نستخدم ميزة التحقق من امتلاك الشخص الذي أنشأ الحساب لعنوان البريد الإلكتروني الذي أدخله، يمكنك تعطيل الميزة أو التعديل على ملف env بوضع إعدادات صحيحة.

    • يُمكنك مثلاً إستخدام log:
    MAIL_MAILER=log

    وتعطيل باقي إعدادات البريد، في هذه الحالة عند إنشاء حساب سيتم إرسال رسالة التحقق إلى ملف laravel.log الموجود في المسار:

    storage\logs\laravel.log

    بعدها نسخ الرابط المُرسل هناك وفتحه على المتصفح ليتم تفعيل الحساب.

    • بإمكانك أيضاً إستخدام أحد الخدمات مثل mailtrap بعد إنشاء حساب يمكنك ربط صندوق البريد الخاص بالحساب الذي أنشأته بالتطبيق الخاص بك عبر الإعدادات المتاحة في الحساب و الخدمة تتكامل مع عدة تقنيات ليس لارافيل فحسب.
    • أعجبني 1
  3. المشروع يستعمل في ملف AuthServiceProvider.php الجدول permissions لإنشاء بعض البوابات (Gates) لتعريف التصريح لبعض العمليات ('edit-post', 'delete-post', 'add-post') لذلك ستحتاج مبدئياً إلى فتح الملف و تعطيل الأسطر:

    Permission::whereIn('name', ['edit-post', 'delete-post', 'add-post'])->get()->map(function($per) {
      Gate::define($per->name, function($user, $post) use ($per) {
        return $user->hasAllow($per->name) && ($user->id == $post->user_id || $user->isAdmin());
      });
    });
    
    Permission::whereIn('name', ['edit-user', 'delete-user', 'add-user'])->get()->map(function($per) {
      Gate::define($per->name, function($user) use ($per) {
        return $user->hasAllow($per->name) && $user->isAdmin();
      });
    });

    أي تعليقها:

    /*
    Permission::whereIn('name', ['edit-post', 'delete-post', 'add-post'])->get()->map(function($per) {
      Gate::define($per->name, function($user, $post) use ($per) {
        return $user->hasAllow($per->name) && ($user->id == $post->user_id || $user->isAdmin());
      });
    });
    
    Permission::whereIn('name', ['edit-user', 'delete-user', 'add-user'])->get()->map(function($per) {
      Gate::define($per->name, function($user) use ($per) {
        return $user->hasAllow($per->name) && $user->isAdmin();
      });
    });
    
    */

    ثم إكمال عملية تهيئة المشروع:

    php artisan key:generate

    إنشاء قاعدة بيانات ثم ربط معلومات الإتصال بها في الملف env.

    بعد ذلك تنفيذ أمر التهجير و البذر:

    php artisan migrate:fresh --seed

    يمكنك بعد ذلك الرجوع إلى الملف السابق وإزالة التعليق من الأسطر السابقة.

    و أخيراً تشغيل المشروع

  4. إن كان المشروع قيد الإطلاق، يٌفضل أخذ نُسخ إحتياطية لقاعدة البيانات بشكل دوري، حتى يتم الرجوع لها عند الحاجة أو في حالة حدوث مشكلة ما. يمكنك الإستفادةمن هذه المساهمة لتحقيق ذلك:

    أيضاً إن كان المشروع قيد الإطلاق يُفضل العمل على نُسخة تجريبية بعيداً عن النُسخة الأساسية للمشروع، وعدم إيداع التعديلات الجديدة إلا عند التأكد من عملها بشكل سليم.

    لإضافة حقل جديد في جدول به بيانات يُمكنك إضافة الحقل بشكل يدوي من خلال البرنامج التفاعلي لإدارة قواعد البيانات الذي يتم إستخدامه أو عبر سطر الأوامر، أو يمكنك ذلك من خلال إضافة ملف تهجير جديد يقوم بهذه العملية ثم تنفيذ عملية التهجير و الشرح موجود في هذه المساهمة:

  5. الخطأ بسيط ورسالة الخطأ توضح أنك قمت بفتح قوس معقوف { في السطر 72 أي:

    if(isset($_POST['login'])){

    لكنك لم تقم بإغلاقه بعدها، فمفسر اللغة لم يجد قوس الإغلاق فأعطى الخطأ.

    يُفترض منك إضافة القوس في الأخير:

    if(isset($_POST['login'])){
    
    
    }

    حاول دائما إحترام المسافة البادئة في الكتل البرمجية قبل سطر الكود لتجنب الوقوع في هذه المشاكل كما هو موضح في الصورة:

    php_code.thumb.PNG.583dbea2ebd0b1fb67789c55ed02598f.PNG

  6. بإمكانك إستخدام نظام الصفحات (pagination) المتاح في Laravel مع Intersection Observer API لتحقيق ذلك.

    سنقوم بإنشاء خاصية page للدلالة على الصفحة الحالية ترتفع قيمتها بـ 1 مع كل جلب لمجموعة بيانات جديدة

    سنقوم بإنشاء خاصية حاوية (كما شرح المدرب محمد في الأعلى) الهدف منها تخزين السجلات

    use Illuminate\Support\Collection;
    
    public int $page = 1;
    public Collection $posts;

    سنقوم بإنشاء خاصية من النوع computed في Livewire لإنشاء paginator يقوم بجلب مجموعة السجلات الخاصة بالصفحة الحالية:

    use Livewire\Attributes\Computed;
    
    #[Computed]
    public function paginator()
    {
      $ids = auth()->user()->following()->wherePivot('confirmed', true)->get()->pluck('id');
      return Post::whereIn('user_id', $ids)
        ->latest()
        ->paginate(10, ['*'], 'page', $this->page);
    }

    أعلاه يتم جلب 10 سجلات في كل مرة، يمكنك التحكم في ذلك من خلال الوسيط الأول للتابع paginate

    سنُنشئ تابع مسؤول عن تحميل المزيد لإضافة سجلات الصفحة الحالية إلى الحاوية الأساسية ورفع قيمة page:

    public function loadMore(): void
    {
      $this->posts->push(
        ...$this->paginator->getCollection()
      );
    
      $this->page = $this->page + 1;
    }

    ثم في التابع mount نقوم بتهيئة الحاوية وإستدعاء التابع loadMore لجلب سجلات أول صفحة:

    public function mount(): void
    {
      $this->posts = collect();
      $this->loadMore();
    }

    ليُصبح المكون ككل بالشكل التالي:

    <?php
    
    namespace App\Livewire;
    
    use Livewire\Component;
    use App\Models\Post;
    use Illuminate\Support\Collection;
    use Livewire\Attributes\Computed;
    
    class PostsList extends Component
    {
      protected $listeners = ['toggleFollow' => '$refresh'];
    
      public int $page = 1;
      public Collection $posts;
    
      public function mount(): void
      {
        $this->posts = collect();
        $this->loadMore();
      }
    
      public function loadMore(): void
      {
        $this->posts->push(
          ...$this->paginator->getCollection()
        );
    
        $this->page = $this->page + 1;
      }
    
      #[Computed]
      public function paginator()
      {
        $ids = auth()->user()->following()->wherePivot('confirmed', true)->get()->pluck('id');
        return Post::whereIn('user_id', $ids)
          ->latest()
          ->paginate(10, ['*'], 'page', $this->page);
      }
    
      public function render()
      {
        return view('livewire.posts-list');
      }
    }

    الآن ستحتاج فقط إلى إستخدام الموجه x-intersect المتاح في إطار العمل alpine.js لإستدعاء التابع loadMore من المكون، لست بحاجة إلى تثبيت الإطار فـ Livewire الإصدار الثالث يتيح إستعمال alpine.js دون حاجة لتثبيته:

    @if ($this->paginator->hasMorePages())
      <div x-intersect="$wire.loadMore" class="h-12 -translate-y-44"></div>
    @endif

    المتصفحات القديمة لا تدعم  Intersection Observer API يمكنك إضافة زر لتحميل المزيد يظهر في هذه الحالة:

    @if ($this->paginator->hasMorePages())
      <button wire:click="loadMore">Load more</button>
    @endif

    ملف العرض سيكون بالشكل التالي:

    <div class="w-[30rem] mx-auto lg:w-[95rem]">
        @if($posts->count() > 0)
            @foreach($posts as $post)
                <livewire:post :post="$post" :wire:key="'post_'.$post->id"/>
            @endforeach
    
            @if ($this->paginator->hasMorePages())
                <div x-intersect="$wire.loadMore" class="h-12 -translate-y-44"></div>
            @endif
    
            @if ($this->paginator->hasMorePages())
                <button wire:click="loadMore">Load more</button>
            @endif
        @else
            <div class="max-w-2xl gap-8 mx-auto dark:text-gray-100">
                {{__('Start Following Your Friends and Enjoy.')}}
            </div>
        @endif
    </div>
    • شكرًا 1
  7. أهلا يحيى،

    يبدو أن المشكلة في إستخدامك لعلامات التنصيص ' ' بالإستعلام جرب كتابة إسم الجدول بدون علامات التنصيص بهذا الشكل:

    SELECT * FROM tasks;

    أو إستخدم علامات التنصيص المائلة `` بالشكل التالي:

    SELECT * FROM `tasks`;

    إذا واجهت مشكلة في أحد دروس الدورة مستقبلاً يرجى طرح سؤالك أسفل الدرس، هناك يوجد قسم لأسئلة الطلاب، و هذا للقسم للأسئلة العامة.

  8. أعتقد أنك تقصد دورات الأكاديمية و تقدمك في الدورة، يبدو أنه لا توجد طريقة واضحة و بسيطة لذلك و لا أعتقد أنه يمكن إستخلاص ذلك من خلال الملف الشخصي على أقل تقدير في الوقت الحالي، إن كان الأمر مهم بالنسبة لك يوجد في صفحة الدورة الرئيسية قسم تحت مسمى مسارات الدورة فيه تفصيل و تقسيم للدروس على مسارات و عدد الدروس في كل مسار بالإضافة للكم الساعي لكل درس و كل مسار. يمكنك إستخلاص المعلومة التي تريدها من هناك.

    course_mo.thumb.png.def9e6cf88b133bb46ef33fa6e858b7d.png

  9. التصميم جيد نوعاً ما لكن إليك بعض التحسينات التي يمكنك إضافتها:

    • إضفاء بعض الحركية و التأثيرات للبطاقة نفسها هناك الكثير من التأثيرات كـ قلب البطاقة (flip) أو (zoom in) و غيرها، تستطيع الإقتباس من تصميمات موجودة على الإنترنت فقط أكتب في حقل البحث بالشكل التالي:
    zoom in card css example codepen

    يمكنك تغيير نوع التأثير الذي تريد إضافته.

    • تنعيم الحواف بإضافة border-radius مناسب.
    • تعويم البطاقة بإضافة ظل لها عبر خاصية box-shadow المتاحة في CSS، يمكنك الإقتباس من خلال الرابط التالي: إضغط هنا
    • إستخدام خطوط ملائمة، تستطيع إستخدام خطوط Google.
    • شكرًا 1
  10. البرمجة مجال واسع و يندرج تحتها عدة تفرعات لذلك من الصعب جداً إحتراف كل المجالات، دورة علوم الحاسوب هي دورة عامة تُعرفك على المجال ككل و تعطيك نبذة عن التفرعات الموجودة لتُسهل عليك الإختيار و أي طريق هو الأفضل و المناسب لك، إذا كنت تشعر بفقدان الشغف في تعلم البرمجة، فإليك بعض النصائح التي قد تساعدك في استعادة الحماس والاستمتاع بتعلم هذه المهارة:

    • حدد أهدافًا صغيرة وقابلة للقياس يمكنك تحقيقها بسهولة. ذلك سيمنحك شعورًا بالتقدم والإنجاز.

    • بدلاً من التركيز فقط على الدراسة النظرية، جرب بناء مشاريع عملية. هذا يجعل تعلم البرمجة أكثر إثارة.

    • انضم إلى منتديات البرمجة أو المجتمعات عبر الإنترنت، وشارك في المحادثات واطلب المساعدة. قد يكون التواصل مع المبرمجين الآخرين ملهمًا ومفيدًا. (مجتمع حسوب IO أو هنا على موقع الأكاديمية يمكنك طرح ما شئت من إستفسارات و سيجيب عليك و يتفاعل معك المدربون و الطلاب)

    • قد تحتاج إلى استراحات من وقت لآخر. لا تتردد في أخذ استراحة قصيرة لتجديد طاقتك ومن ثم العودة بروح جديدة.

    • التواصل مع أشخاص ذوي إهتمامات مشتركة هذا يمكن أن يكون محفزاً لك.

    • تجربة مشاريع مختلفة و التفاعل مع آخر التطورات و التقنيات في المجال.

    أهم شيء هو تحديد هدفك من تعلم البرمجة و الدخول في هذا المجال وتذكر أن فقدان الشغف يحدث للجميع في أحيانٍ كثيرة.

    • أعجبني 2
  11. يُمكنك فصل القالبين عن بعض و تضع لكل قالب ملف مخطط خاص به، يعني إلى جانب القالب الأساسي لديك base.html تقوم بإنشاء ملف قالب آخر بإسم مغاير و ليكن إسم main.html أو أي إسم آخر ترغب به ثم عند إنشاء صفحات العروض التي تعتمد على هذا القالب تقوم بوراثة هذا الملف main بدل القالب الأساسي:

    {% extends "main.html" %}
    
    # ...

    و في الصفحات التي تعتمد على القالب الأساسي تقوم فيها بوراثة ملف القالب الأساسي base.

    يفضل الإعتماد على قالب واحد لنفس المشروع حتى لا تكثر الموارد لأن هذا يؤثر على الأداء.

  12. مبدئياً و بشكل عام لا يمكن الجزم في هذا الموضوع فهو راجع لطبيعة الشخص أو المتعلم، البعض يجد تلقي المعلومات من الكتب أسهل نظراً لأنه تعود على هذه الطريقة أو يحب القراءة بشكل أكثر و البعض الآخر يجد أن التعلم من الدورات أفضل.

    سأجيب عن الموضوع من منطلق شخصي، أرى أنه إن كان الهدف تعلم أساسيات لغة أو تقنية معينة خصوصاً التقنيات الحديثة يُفضل متابعة دورة مختصرة تشرح الأساسيات و بها أهم الأشياء التي تستهدفها تلك التقنية ثم التوسع من خلال التوثيق الرسمي أو المحتوى المكتوب كالمقالات هذا لأن هذه التقنيات تتحدث بإستمرار و من الصعب إيجاد كتاب شامل لكل شيء يخص تلك التقنية بكافة خصائصها و نظراً لأن مسألة إنتاج الكتاب نفسه تأخذ وقت و تلك التقنية تتحدث بإستمرار.

    أما إن كان الهدف تعلم مواضيع عامة أو فلسفات معينة في مجال علوم الحاسب أو هندسة البرمجيات فقراءة الكتب هنا قد تكون مهمة جداً، فيمكن المزج بين قراءة الكتب و متابعة المحتوى المرئي في هذه الحالة حيث يكون الكتاب هو الأساس الذي يقود عملية التعلم و التفرع لجزئية محددة من الكتاب نفسه عبر فيديو أو مقال على الإنترنت بهدف فهمها جيداً و التوسع حولها.

    كخلاصة يمكن القول أن التعلم سواء من الكتب او الدورات مفيد و مسألة تفضيل أحدهما على الآخر تعود لنا نحن و في كثير من الحالات قد نلجأ لخيار المزج لتحقيق هدف معين و تحصيل إستفادة أكبر.

    يمكنك الإطلاع على المساهمات التالية أيضاً:

  13. يمكنك الإطلاع على الصفحة التالية الامتحان والحصول على الشهادة بها كل شيء يتعلق بموضوع الشهادة و الإمتحان و الخطوات مقتبسة من الصفحة:

    خطوات الامتحان

    1. تواصل معنا

    أخبرنا برغبتك باجراء الامتحان مع تزويدنا بروابط مشاريعك التي طبقتها أثناء الدورة. يجب أن تكون قد طبقت المشاريع مع المدرب أثناء الدورة، ولا يمكن اجراء امتحان بمشاهدة المحتوى فقط.

    2. محادثة صوتية

    سنحدد لك موعد لاجراء محادثة صوتية لمدة 30 دقيقة يطرح المدرب فيها أسئلة متعلقة بالدورة ويناقش معك ما نفذته خلالها.

    3. مشروع التخرج

    سيحدد لك المدرب مشروعًا مرتبطًا بما تعلمته أثناء الدورة لتنفيذه خلال فترة محددة تتراوح بين أسبوع الى أسبوعين.

    4. مراجعة المشروع والتخرج

    سيراجع المدرب المشروع الذي أنجزته، وإن سارت جميع الخطوات السابقة بشكل صحيح، ستتخرج وتحصل على الشهادة أو يرشدك المدرّب لأماكن القصور ويطلب منك تداركها ثم التواصل معنا من جديد.

    الشروط التي يجب تحقيقها قبل التقدم للإمتحان: 

    يمكنك التقدم إلى امتحان الدورة، من خلال التواصل مع مركز مساعدة أكاديمية حسوب، مع مراعاة الشروط التالية:

    • إتمام أربعة مسارات تعليمية على الأقل
    • التطبيق العملي مع المدرب، والاحتفاظ بالمشاريع العملية الناتجة لإرسالها للمراجعة
    • رفع المشاريع على حسابك على GitHub أولًا بأول لمشاركتها معنا
  14. يبدو أن ما تُمرره من المتحكم SocialMediaController في التابع المسؤول عن عرض القائمة، عبارة عن قائمة فارغة، و هو ما يعيده التابع GetSocialMedias في الصنف SocialMediaDAO، بتطبيق الشرط:

    .Where(x => x.isDeleted == false)

    لا يوجد أي سجل في الجدول يحقق الشرط لأن السجلات تحمل NULL في العمود isDeleted. أعتقد أن المشكلة تتعلق بهذا الجزء، حاول تعديل الشرط بما يتناسب مع الحالة و انظر إن كان يحل المشكلة لديك.

    • أعجبني 1
  15. ستجد في صفحة قصص نجاح بعض من قصص النجاح عن طلاب تخرجوا من أكاديمية حسوب يروون تجربتهم في التعلم من دورات الأكاديمية و مسيرتهم بعد التخرج، يُمكنك الإطلاع على الصفحة و تلك التجارب. 

  16. و عليكم السلام،

    ستجد في المقال التالي شرح أو مدخل للأمن السيبراني:

    و من خلال موقع roadmap.sh ستجد خرائط طرق لعدة مسارات تعليمية و هذه خريطة الطريق لتعلم الأمن السيبراني و من بين الأشياء المهمة التي تحتاج تعلمها هي أنظمة التشغيل و الشبكات:

    في الأسفل مساهمات سابقة في نفس الموضوع أيضا:

  17. أهلا محمود،

    لا الإمتحان يتمحور حول ما درسته في الدورة فقط، لن تجد فيه أشياء لم تتطرق لها الدورة أو أشياء لم تُشرح فقط ما تم شرحه خلال المسارات. ستجد في صفحة الامتحان والحصول على الشهادة كل شيء يتعلق بهذا الموضوع.

    • شكرًا 1
  18. إليك بعض النصائح أثناء تعلمك من دورات أكاديمية حسوب:

    • تأكد من الفهم السليم للأساسيات (محتوى الدرس أو الموضوع الأساسي للدرس) 
    • لا تكتفي فقط بمشاهدة الدرس و الإستماع، و إنما عليك بالتطبيق و كتابة الكود بنفسك حتى تتعود، ستجد في البداية صعوبة لكن كلما تعودت على هذه الممارسة كلما تطورت أكثر.
    • يُمكنك تدوين المعلومات المهمة على شكل رؤوس أقلام او مخططات حتى تعود لها في حالة النسيان أو عند المراجعة لتذكر تلك المعلومات.
    • لديك عدد كبير من المقالات منشورة على أكاديمية حسوب في شتى المجالات و التقنيات ستساعدك كثيراً في زيادة معلوماتك التي خرجت بها من الدرس و للتوسع أكثر، إستخدم محرك البحث أو حقل البحث في موقع الأكاديمية.
    • لديك أيضاً موسوعة حسوب فهي تحتوي على توثيق لمعظم اللغات و التقنيات باللغة العربية يُمكنك الإستفادة منها سواء في المراجعة أو زيادة الفهم.
    • توفر أكاديمية حسوب عدد من المدربين المحترفين الذين يمكنهم مساعدتك في أي وقت، لذلك إن وجدت صعوبة في فهم درس ما أو جزء مُعين يُمكنك الإستفسار عنه و سيجيب عليك أحد المدربين و يوضح لك الجزء الذي تسأل عنه، الصفحة التالية توضح لك طريقة الإستفسار حتى تحصل على أجوبة أفضل كيف أتواصل مع المدرّبين

    ستجد بعض النصائح في هذا المقال:

    و هنا مساهمات مشابهة لما تسأل عنه:

    • شكرًا 2
  19. بإمكانك إضافة كلاس مشترك لكل حقول الإدخال التي تريد الضغط عليها، ثم تحديد العناصر عبر التابع querySelectorAll الذي يعيد كل العناصر ثم عبر حلقة forEach تضيف لكل عُنصر EventListener بالشكل التالي:

    document.addEventListener("DOMContentLoaded", () => {
    
      document.querySelectorAll('.myInput').forEach(input => {
        input.addEventListener("click", function () {
          this.parentElement.nextElementSibling.classList.toggle('active')
        })
      })
    
    });

    بعد ان تضع لحقول الإدخال الصنف myInput:

    <input type="text" class="myInput" placeholder="search">
                       ^^^^^^^^^^^^^^^

    أو تضع أي إسم المهم أن تستهدفه عبر querySelectorAll.

    بداخل المعالج (handler) تقوم بالتدرج من حقل الإدخال إلى عُنصر القائمة الذي تريد تبديل ظهوره و إخفائه. كما هو موضح:

    this.parentElement.nextElementSibling.classList.toggle('active')
    • أعجبني 1
  20. إضافة إلى ما ذكره عدنان، فـ Filament يحتوي على عدد من الحزم التي تتيح التعامل مع مكونات معينة فمثلاً حزمة Form Builder تتيح لك إنشاء إستمارات و التعامل معها، حزمة  Table Builder لإنشاء الجداول و التعامل معها و هكذا بالنسبة لبقية الحزم، هذه الحزم تُثبت تلقائياً عند تثبيت الحزمة الأساسية Panel Builder، لكن يمكن تثبيت حزمة بعينها في مشروعك دون الحاجة إلى الحزمة الأساسية أو الحزم الأخرى كلها بشرط أن يكون مشروعك مبني بـ TALL Stack أي (Tailwind, Alpine, Livewire و Laravel) فإطار العمل كله و مكوناته الفرعية مبنية بهذه التقنيات و تعتمد عليها. يمكن من خلال Filament أو الحزم التي توفرها إنشاء مكونات بالسلوك الإفتراضي و المظهر الإفتراضي، و يمكن أيضاً تخصيص تلك المكونات فهو قابل للتخصيص بشكل كبير.

×
×
  • أضف...