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

لوحة المتصدرين

  1. سمير عبود

    سمير عبود

    الأعضاء


    • نقاط

      4

    • المساهمات

      3496


  2. احمد صوالحة

    احمد صوالحة

    الأعضاء


    • نقاط

      4

    • المساهمات

      29


  3. Abdulraheem Barghouthi

    Abdulraheem Barghouthi

    الأعضاء


    • نقاط

      3

    • المساهمات

      182


  4. Sam Ahw

    Sam Ahw

    الأعضاء


    • نقاط

      3

    • المساهمات

      1388


المحتوى الأكثر حصولًا على سمعة جيدة

المحتوى الأعلى تقييمًا في 02/16/21 in أجوبة

  1. يوجد طريقتان لتنفيذ الـthreads وهما: عمل implement للواجهة Runnable عمل extend للصنف Thread ما الفرق بينهما وما هي الطريقة الأفضل ؟
    2 نقاط
  2. لفهم سبب إستخدام Char Array بدلاً من String يجب علينا أولاً فهم الفرق بينهم: String: هو عبارة عن نوع بيانات غير قابل للتغير أي أن مجرد تعريفك لبيانات ستبقى موجودة في الذاكرة لحين مسحها من قبل الـGarbage Collection المسؤولة عن إدارة الذاكرة. عند قيامك بتعريف متغير من نوع String بحيث يحتوي على القيمة النصية "hello" سيتم حفظه في String constant pool، في حال قمت بتغيير قيمة المتغير إلى " hello 2 " سيتم أنشاء String جديد وإضافته للـ String constant pool، أي عند تغيير قيمة المتغير يتم إنشاء كائن جديد من نوع String ولا يتم تعديل نفس الكائن. الخلاصة: لا يمكن مسح البيانات من String بعد تعريفها بل ستبقى في الذاكرة لحين مسحها من قبل الـGarbage Collection. Char Array: هي عبارة عن نوع بيانات قابل للتغير عكس الـString، أي عند تغيير قيم مصفوفة ما فإن القيم السابقة سيتم مسحها ولا يمكن إرجاعها. إذاً ما المغزى من إستخدام Char Array ؟ يجب أخذ التدابير الأمنية عند التعامل مع كلمات المرور والحسابات البنكية وغيرها من الأمور الحساسة الأخرى، لو إستخدمنا String في التعامل مع هكذا معلومات فيستطيع المهاجم الذي وصل إلى الذاكرة الخاصة بالـJVM أن يستخرج هذه المعلومات الحساسة بينما لو تم إستخدام Char Array فالمهمة ستكون أصعب كثيراً لأننا سنقوم بتعديل قيمة عناصر الـArray إلى قيم وهمية بعد إنتهائنا منها وبالتالي سيحصل على كلمة مرور خاطئة.
    2 نقاط
  3. متى سوف تبدأ الدوره وكيف الطريقه؟؟
    2 نقاط
  4. عملت كود مبدئي ولسبب ما اضطررت الى نسخ الكود في برنامج one note وعندما ارت استعادت الكود لم يعمل بشكل صحيح ما الحل واين يمكنني نسخ الاكواد واسترجاعها بشكل سليم وصحيح
    1 نقطة
  5. أنا مبتدئ فى مجال البرمجة محتاج جهاز إمكانياته إيه علشان ابداء
    1 نقطة
  6. لدي جدول بيانات به مجموعة من السجلات و أريد إضافة عمود جديد لهذا الجدول بدون فقدان البيانات الحالية كيف استطيع عمل ذلك في laravel
    1 نقطة
  7. سأضيف معلومة مهمة جداً: عند إنشاء Thread بإستخدام Runnable فإنه يمكن تشارك الـObject لكل الـthreads، عكس الطريقة الثانية التي تنشئ Object منفصل لكل thread. سأترك لك مثال موضح بالتعليقات لتفهم الأمر بشكل أفضل: class MyImplementedThread implements Runnable{ // الطريقة الأولى public int counter = 0; @Override public void run(){ counter++; // يتم زيادة العداد في كل مرة يتم تشغيل //thread System.out.println("implemented: "+counter); } } class MyThread extends Thread{ // الطريقة الثانية public int counter = 0; @Override public void run(){ counter++; System.out.println("MyTheread: "+counter); } } public class Main{ public static void main(String []args){ //الطريقة الأولى MyImplementedThread myImplementedThread = new MyImplementedThread(); /* ننشئ الكائن الذي ستشترك به كل الـ threads التي ستتبع الطريقة الأولى */ Thread implemented1 = new Thread(myImplementedThread); /* نعرف thread جديدة مع ارفاق الكائن الخاص بالطريقة الأولى */ implemented1.start(); // نبدأ عمل الـ //thread try{ Thread.sleep(1000); /* نقوم بإيقاف تشغيل مؤقت لمدة ثانية واحدة قبل متابعة إنشاءالـ threads الأخرى */ } catch(Exception e){ System.out.println(e.getMessage()); } Thread implemented2 = new Thread(myImplementedThread); implemented2.start(); try{ Thread.sleep(1000); } catch(Exception e){ System.out.println(e.getMessage()); } Thread implemented3 = new Thread(myImplementedThread); implemented3.start(); try{ Thread.sleep(1000); } catch(Exception e){ System.out.println(e.getMessage()); } //---------------------- //الطريقة الثانية MyThread myThread1 = new MyThread(); myThread1.start(); /* ننشئ thread منفصلة في كل مرة */ try{ Thread.sleep(1000); } catch(Exception e){ System.out.println(e.getMessage()); } MyThread myThread2 = new MyThread(); myThread2.start(); try{ Thread.sleep(1000); } catch(Exception e){ System.out.println(e.getMessage()); } MyThread myThread3 = new MyThread(); myThread3.start(); try{ Thread.sleep(1000); } catch(Exception e){ System.out.println(e.getMessage()); } } } لاحظ ناتج تنفيذ البرنامج: وهذا يدل على التشارك في الـObject في الطريقة الأولى حيث تم زيادة الـcounter بواحد من قبل كل thread بينما في الطريقة الثانية كل thread كان لها object خاص بها وبالتالي ظهر الرقم واحد بدون أي زيادة.
    1 نقطة
  8. يظهر لدي الخطأ التالي عند محاولة تشغيل برنامج بلغة java : java.lang.NullPointerException ما هو سبب ظهوره ؟ وكيف أعالج هذه المشكلة؟
    1 نقطة
  9. إن الفرق بين الطريقتين هو كالتالي: أولاً: عن طريق تطبيق الواجهة Runnable Interface: public class DemoRunnable implements Runnable { public void run() { //نضع هنا الكود الخاص بالعملية } } ثانياً: عن طريق استخدام الصف Thread: public class DemoThread extends Thread { public DemoThread() { super("DemoThread"); } public void run() { //نضع هنا الكود الخاص بالعملية } } وإن كلا الطريقتين متشابهتين ولا يوجد طريقة جيدة وأخرى سيئة، وأيضاً يوجد العديد من النقاشات حول استخدامات كل منها، ولكن من أهم الفروقات أو النقاط التي يجب عليك الانتباه لها لاختيار الطريقة المناسبة هي: 1- في استخدام Runnable أنت لا تخصص حقًا سلوك المسالك أو تعدلها. أنت فقط تعطي المسلك شيئًا لتشغيله. هذا يعني أن الترتيب في الكود سيكون أفضل. 2- لغة جافا تدعم فقط الوراثة وحيدة الدرجة، لذلك لا يمكنك إنشاء extend لأكثر من صف. 3- إن إنشاء واجهة تعطي interface تسمح لك بفصل المكونات عن بعضها ضمن الكود، وبذلك يصبح الكود الخاص بك أكثر مرونة ويمكنك ذلك من فصله عن العمليات المستخدمة ضمن المسلك thread. 4- في استخدام Runnable تجعل الصف الذي يقوم باستدعائها أكثر مرونة، أما إذا استخدمت Thread فإن الحدث الذي سيقوم به سيبقى دوماً ضمن الـ thread، أما في الحالة الأخرى أي Runnable فليس من الضرورة أن يبقى ضمن المسلك thread حيث يمكنك أيضاً تمرير البيانات إلى خدمات وصفوف أخرى. 5- وأخيراً، في حال قررت استخدام Thread فيجب عليك الانتباه إلى وجود خطأ بسيط Bug في نسخ JDK 4 أو الأقدم يتعلّق بالتوقيت بين بناء المسلك contruction و بدء عمله start، حيث قامت شركة Sun بإصلاح الخطأ بدءً من نسخ Java 1.5 ولذلك يجب عليك الانتباه للنسخة التي تقوم باستخدامها من جافا. وإذا نظرنا إلى جميع النقاط السابقة يمكن أن نلاحظ أن استخدام runnable مناسب أكثر لمعظم الحالات. ولكن هذا لا يعني عدم استخدام الصف Thread فكل مبرمج يفضّل الطريقة التي تناسب عمله ويرتاح بالعمل فيها.
    1 نقطة
  10. ليس هنالك فرق واضح بين الطريقتين ولكن الطريقة الاولى تعتبر اسهل نسبياً من الطريقة الثانية.
    1 نقطة
  11. java.lang.NullPointerException تعني أن الكائن عبارة عن null وتحاول ان تستدعي دالة بداخله ويمكنك معالجة الامر باستخدام try catch ولكن لايوصى بذلك وعوضاً عن ذلك يمكنك استخدام هذه الطريقة: if(someVariable != null){ someVariable.doSomething();//في حالة أن المتغير ليس null }else{ // الكود في حالة أن المتغير null }
    1 نقطة
  12. عند التعامل مع الـPassword Field في Java Swing نلاحظ أن getPassword() تعيد لنا char array بينما عند التعامل مع الحقول الأخرى نستخدم getText() فتعيد لنا String. لماذا تم إستخدام char array بدلا من String ؟
    1 نقطة
  13. أريد إنشاء برنامج دردشة / شات باستخدام ما تعملته من أساسيات لغة php، فما مبدأ عمل برنامج الدردشة؟ وكيف يمكنني إنشاء واحد؟
    1 نقطة
  14. يمكنك أن تبدأ في أي دورة من الدورات الحالية الموجودة في أكاديمية حسوب في أي وقت من هنا، ولا يوجد وقت محدد لبدء أي دورة منهم. الأمر متوقف عليك ومتى تريد أن تبدأ.
    1 نقطة
  15. السلام عليكم ورحمة الله حياكم الله ,,, ب أرشيف المسارات الأقدم كان في دوره لاساسيات تطوير الويب ... لاستاذ ثاني غير الموجود حاليا بالخيار الاول ... كيف بصل للقديم ممكن جواب
    1 نقطة
  16. يوجد لديك خطأ في إستعمال الدالة fputs هذه الدالة تستقبل سلسلة نصية على شكل مصفوفة محارف كمُعامل أول و مؤشر على File كمُعامل ثاني بهذا الشكل مثلاً: #include <stdio.h> int main () { FILE *fp; fp = fopen("file.txt", "w+"); fputs("This is c programming.", fp); fclose(fp); return(0); } أنت لم تقرأ شيء من الملف الذي تريد نقل مُحتواه فللكتابة في الملف الثاني يجب قراءة مُحتوى الملف الأول ثم نقله للملف الثاني بهذا الشكل مثلاً: #include <iostream> #include <stdio.h> using namespace std; int main() { FILE* pFile; // المصدر FILE* pofg; // الخرج char ch; // مُتغير سنستخدمه للقراءة pFile = fopen("a.txt", "r"); // فتح المصدر للقراءة pofg = fopen("abc.txt", "w"); // فتح الخرج للكتابة if (pFile != NULL) // إذا كان المصدر لا يُساوي null { ch = fgetc(pFile); // قراءة المحرف الأول من المصدر while(ch != EOF) // بما اننا لم نصل إلى نهاية الملف { fputc(ch, pofg); // أكتب في الخرج ما قمت بقرائته ch = fgetc(pFile); // واصل القراءة } cout<<"\nFile copied successfully."; // تم نقل المحتوى fclose(pFile); // غلق المصدر fclose(pofg); // غلق الخرج } return 0; }
    1 نقطة
  17. لنفترض أنه لديك حقل username في جدول المُستخدمين بهذا الشكل: $table->string('username')->unique(); الآن يجب أن تُعدل على نموذج تسجيل الدخول و بالضبط في حقل البريد ليُصبح بهذا الشكل: <div class="form-group row"> <label for="login" class="col-md-4 col-form-label text-md-right">{{ __('Username or Email') }}</label> <div class="col-md-6"> <input id="login" type="text" class="form-control{{ $errors->has('username') || $errors->has('email') ? ' is-invalid' : '' }}" name="login" value="{{ old('username') ?: old('email') }}" required autofocus> @if ($errors->has('username') || $errors->has('email')) <span class="invalid-feedback"> <strong>{{ $errors->first('username') ?: $errors->first('email') }}</strong> </span> @endif </div> </div> في ملف login.blade.php، و هذا حتى يقبل الحقل إدخال نص و عرض رسائل الخطأ. الآن يجب التعديل على المُتحكم LoginController سنُجري عليه بعض التعديلات حتى يُلائم الوضعية: نضيف الخاصية التالية للمُتحكم: protected $username; ثم من خلال الباني نقوم بتهيئة هذه الخاصية: public function __construct() { $this->middleware('guest')->except('logout'); $this->username = $this->findUsername(); } لاحظ أنها تأخذ قيمتها من خلال ما يُرجعه التابع findUsername لذلك نقوم بإنشائه في المتحكم أيضاً: <?php public function findUsername() { $login = request()->input('login'); // جلب قيمة النص الذي أدخله المُستخدم في الحقل $fieldType = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; // بإستخدام القيمة يُمكننا معرفة إن كان المُدخل بريد او نص و على اساسها نضع نوع الحقل request()->merge([$fieldType => $login]); // وضع حقل جديد في الطلب return $fieldType; // email or username } كل ما يفعله التابع أنه يجلب لنا email او username على حسب القيمة المُدخلة و يضيف ذلك لمصفوفة الطلب: إذا كان المُدخل بريداً: 'email' => 'قيمة الحقل' إذا لم يكن بريد إلكتروني: 'username' => 'قيمة الحقل' الآن نقوم بإعادة تعريف كل من التابع username و التابع login اللذان يستخدمها المُتحكم LoginController إعتمادًا على الTrait AuthenticatesUsers لن نُغير على التابع login كثيراً سنأخذه كما هو و نضيف بعض الأشياء فقط: التابع username: <?php public function username() { return $this->username; } التابع login: <?php public function login(Request $request) { //نُغير التحقق $this->validate($request, [ 'login' => 'required|string', 'password' => 'required|string', ]); // نجلب نوع التسجيل $login_type = filter_var($request->input('login'), FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; // نضيفه لمصفوفة الطلب $request->merge([ $login_type => $request->input('login') ]); // بقية الأشياء موجودة من الإطار نفسه و لن نغير فيها // If the class is using the ThrottlesLogins trait, we can automatically throttle // the login attempts for this application. We'll key this by the username and // the IP address of the client making these requests into this application. if (method_exists($this, 'hasTooManyLoginAttempts') && $this->hasTooManyLoginAttempts($request)) { $this->fireLockoutEvent($request); return $this->sendLockoutResponse($request); } if ($this->attemptLogin($request)) { return $this->sendLoginResponse($request); } // If the login attempt was unsuccessful we will increment the number of attempts // to login and redirect the user back to the login form. Of course, when this // user surpasses their maximum number of attempts they will get locked out. $this->incrementLoginAttempts($request); return $this->sendFailedLoginResponse($request); } لا تنسى إستدعاء الكلاسات المُستخدم في المُتحكم. هذا مُحتوى المُتحكم LoginController بعد التعديلات المُضافة: <?php namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use App\Providers\RouteServiceProvider; use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Http\Request; class LoginController extends Controller { /* |-------------------------------------------------------------------------- | Login Controller |-------------------------------------------------------------------------- | | This controller handles authenticating users for the application and | redirecting them to your home screen. The controller uses a trait | to conveniently provide its functionality to your applications. | */ use AuthenticatesUsers; /** * Where to redirect users after login. * * @var string */ protected $redirectTo = RouteServiceProvider::HOME; protected $username; /** * Create a new controller instance. * * @return void */ public function __construct() { $this->middleware('guest')->except('logout'); $this->username = $this->findUsername(); } public function findUsername() { $login = request()->input('login'); $fieldType = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; request()->merge([$fieldType => $login]); return $fieldType; } public function username() { return $this->username; } public function login(Request $request) { $this->validate($request, [ 'login' => 'required|string', 'password' => 'required|string', ]); $login_type = filter_var($request->input('login'), FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; $request->merge([ $login_type => $request->input('login') ]); // If the class is using the ThrottlesLogins trait, we can automatically throttle // the login attempts for this application. We'll key this by the username and // the IP address of the client making these requests into this application. if (method_exists($this, 'hasTooManyLoginAttempts') && $this->hasTooManyLoginAttempts($request)) { $this->fireLockoutEvent($request); return $this->sendLockoutResponse($request); } if ($this->attemptLogin($request)) { return $this->sendLoginResponse($request); } // If the login attempt was unsuccessful we will increment the number of attempts // to login and redirect the user back to the login form. Of course, when this // user surpasses their maximum number of attempts they will get locked out. $this->incrementLoginAttempts($request); return $this->sendFailedLoginResponse($request); } } ملاحظة: هذه الطريقة مُستخدمة على إصدار 8 من لارافيل، بإستعمال الحزمة Laravel/ui
    1 نقطة
  18. مرحباً، يمكنك تسجيل الدخول عن طريق أحد الحلقين المذكورين ( البريد الالكتروني او اسم المستخدم) من خلال تنفيذ الخطوات التالية: بالبداية بكل تأكيد يجب أن تكون قد أنشأت ملفات المصادقة auth scaffolding ، من خلال عدة خيارات متاحة أثناء بناء تطبيقك، مثلاً: php artisan ui bootstrap --auth بعدها تأكد من اضافة حقل username في جدول المستخدمين الخاص بك لتكون كالتالي: <?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('users', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('name'); $table->string('email'); $table->string('username')->nullable(); $table->timestamp('email_verified_at')->nullable(); $table->boolean('is_admin')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('users'); } } ولا تنسى القيام بـ migrate في حال قمت بالتعديل على الملف السابق ليتم بناء قاعدة البيانات من جديد في ملف واجهة تسجيل الدخول login blade قم بحذف حقل البريد الالكتروني email و إضافة حقل اسم المستخدم username كي يكون بديلا عنه (سنقوم بجعله يقبل الاثنين في الخطوة القادمة) عبر الكود التالي: <div class="form-group row"> <label for="username" class="col-md-4 col-form-label text-md-right">Username Or Email</label> <div class="col-md-6"> <input id="username" type="username" class="form-control @error('username') is-invalid @enderror" name="username" value="{{ old('username') }}" required autofocus> @error('username') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror </div> </div> الان سنقوم بتعديل تابع تسجيل الدخول login في ملف LoginController كي يحقق الوظيفة المطلوبة كالتالي: <?php namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Http\Request; class LoginController extends Controller { use AuthenticatesUsers; protected $redirectTo = '/home'; /** * Create a new controller instance. * * @return void */ public function __construct() { $this->middleware('guest')->except('logout'); } /** * Create a new controller instance. * * @return void */ public function login(Request $request) { $input = $request->all(); $this->validate($request, [ 'username' => 'required', 'password' => 'required', ]); $fieldType = filter_var($request->username, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; if(auth()->attempt(array($fieldType => $input['username'], 'password' => $input['password']))) { return redirect()->route('home'); }else{ return redirect()->route('login') ->with('error','Email-Address And Password Are Wrong.'); } } } يقوم التعديل السابق بفحص البيانات المدخلة في حقل username فإذا كانت بصيغة email فإنه سيقوم بمقارنتها بعمود البريد الالكتروني في قاعدة البيانات و الا فإنها اسم مستخدم و سيقارنها بحقل username بقاعدة البيانات.
    1 نقطة
  19. هناك عدة حزم مُعظم المُطورون يستخدمون إحداها لعمل هذه الجزئية في مشروعهم و من هذه الحزم أذكر: 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 نقطة
  20. في البداية يجب عليك تجهيز بعض الجداول للقيام بذلك, فستحتاج على الأقل إلى جدول للأدوار وجدول للصلاحيات وجدول صلاحيات الدور. كل واحد منها يحمل الاسم الذي سيتعامل معه النظام, كالتالي: Schema::create('permissions', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('name'); $table->timestamps(); }); هذا للصلاحيات وكذلك للأدوار كالتالي: Schema::create('roles', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('name'); $table->timestamps(); }); أما لجدول صلاحيات الدور فسيحتوي على id لكل دور يقابله الصلاحيات المعطاه له كالتالي: Schema::create('role-permissions', function (Blueprint $table) { $table->bigIncrements('id'); $table->unsignedBigInteger('role_id'); $table->unsignedBigInteger('permission_id'); $table->timestamps(); $table->foreign('role_id')->references('id')->on('roles'); $table->foreign('permission_id')->references('id')->on('permissions'); }); حيث أن هذا الجدول مخصص للعلاقة وربط بين الجدولين. بالطبع سنحتاج إلى Models لل Role و Permission حتى نستطيع التعامل مع الجداول سأفترض معرفتك بهذا الأمر ولكن سأوضح العلاقة الموجودة والتي هي واحد لمجموعة 1:m وممثلة كالتالي في Permission model: public function role(): { return $this->belongsTo(Role::class); } وفي Role model: public function permission(): { return $this->hasMany(Permission::class); } هكذا تكونت العلاقات لدينا, الأن نريد أن نضيف عمود جديد في جدول users باسم role حتى نستطيع إعطاءه الدور الخاص به. وهذا يعني أننا نريد أن ننشئ الصلاحيات ومن ثم تحديد هذه الصلاحيات حسب دور محدد ومن ثم نعطي هذا الدور للمستخدم وبهذا الشكل سيمتلك المستخدم الصلاحيات. ولكن نريد تطبيق ذلك في المشروع لدينا وهذا يتم عبر ال Middlewate غالباً لكن يمكن فحصه في controller بداخل ال constructor الخاص بهذا ال controller ولكن دعنا نقول أننا نريد التعامل باستخدام Middleware فما علينا فعله هو أن نتأكد بداخله إن كان هذا المستخدم لديه الصلاحيات لدخول إلى صفحة معينة أو القيام بأمر معين. وعلى المستوي الشخصي أستخدم مكتبة جاهزة توفر الوقت علي بهذا الأمر وتقوم به بطريقة ممتازة واسم هذه المكتبة Laravel-permission فكل ما عليك فعله هو تتبع خطوات التنزيل الموضحة ومن ثم تعلم استخدام المكتبة.
    1 نقطة
  21. اللارافيل تسهل القيام بذلك من خلال امرين: البوابات او الgates : وهي عبارة عن بوابة تعطي المرور للمستخدمين المصرح لهم القيام بالواجبات المعينة. ويتم تعريف البوابات بداخل الدالة boot use App\Models\Post; use App\Models\User; use Illuminate\Support\Facades\Gate; /** * Register any authentication / authorization services. * * @return void */ public function boot() { $this->registerPolicies(); Gate::define('update-post', function (User $user, Post $post) { return $user->id === $post->user_id; }); } في الكود الموجود بالأعلى يتم إنشاء بوابة تقوم بتحديد عملية تحديث الpost للشخص الذي قام بانشائه فقط وذلك من خلال مقارنة الid الخاص بالمستخدم الحالي مع الid الخاص بالمستخدم الذي قام بإنشاء الpost. <?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use App\Models\Post; use Illuminate\Http\Request; use Illuminate\Support\Facades\Gate; class PostController extends Controller { /** * Update the given post. * * @param \Illuminate\Http\Request $request * @param \App\Models\Post $post * @return \Illuminate\Http\Response */ public function update(Request $request, Post $post) { if (! Gate::allows('update-post', $post)) {//هنا يتم التأكد باستخدام البوابة update-post من أن المستخدم مصرح له تحديث ال post abort(403);//يتم اجهاض العملية مع الخطأ 403 اي أن المستخدم غير مصرح للقيام بالعملية } // متابعة الكود وتحديث المنشور } } بعد عملية إنشاء الgate يأتي الدور على ربط البوابة مع الcontroller حيث تم وضع شرط لمواصلة تنفيذ التحديث على البوست وهو ان تكون قيمة البوابة قيمة ايجابية اي ان المستخدم مصرح له القيام بالامر. : او السياسات policies من خلال ال php artisan make:policy PostPolicy --model=Post خاصة بالموديل بوست حتكون موجودة في المسار policy الامر ده من خلاله سيتم إنشاء app/Policies بعدها ستقوم بتسجيل السياسة التي قمت بعملها في المسار App\Providers\AuthServiceProvider والتسجيل بمثابة اخبار للارافيل بالسياسات التي ستستخدمها في البرنامج. <?php namespace App\Policies; use App\Models\Post; use App\Models\User; class PostPolicy { /** * Determine if the given post can be updated by the user. * * @param \App\Models\User $user * @param \App\Models\Post $post * @return bool */ public function update(User $user, Post $post) { return $user->id === $post->user_id; } } في الكود السابق يتم التحقق من أن المستخدم مصرح له أن يقوم بعملية التحديث. وتقدر تستخدم الpolicy بواحدة من طريقتين: اما عن طريق الblade : @can('update', $post) <!-- ...بتقوم بعرض جزئيات من التصميم للمستخدم في حال انه كان يمكنه عمل تحديث للبوست --> @elsecan('create', App\Models\Post::class) <!-- ...بتقوم بعرض جزئيات من التصميم للمستخدم في حال انه كان يمكنه عمل انشاء لبوست جديد--> @endcan @cannot('update', $post) <!-- ...تقوم بعرض جزئيات من التصميم للمستخدم في حال انه كان لا يمكنه عمل تحديث للبوست --> @elsecannot('create', App\Models\Post::class) <!-- ...بتقوم بعرض جزئيات من التصميم للمستخدم في حال انه كان لا يمكنه عمل انشاء لبوست جديد--> @endcannot عن طريق الربط مع الcontroller: <?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use App\Models\Post; use Illuminate\Http\Request; class PostController extends Controller { /** * Update the given post. * * @param \Illuminate\Http\Request $request * @param \App\Models\Post $post * @return \Illuminate\Http\Response */ public function update(Request $request, Post $post) { if ($request->user()->cannot('update', $post)) { abort(403); } // Update the post... } }
    1 نقطة
  22. تعد المصادقة المتعددة مهمة جدًا إذا كنت تعمل على تطبيق ويب كبير الحجم، فتمكنك من استخدام صلاحيات مختلفة تابعة لجداول مختلفة للمستخدمين مثل جدول "المستخدمين" لتسجيل مستخدم الموقع وجدول "المشرفين" للمستخدم المسؤول أو للدخول إلى لوحة التحكم على سبيل المثال. وبهذه الطريقة توفر أمانًا وقوةً حيث يمكنك الفصل بين المستخدمين وإعطاء صلاحيات وصول مختلفة لكل نوع. مثال عن تطبيقها: أولاً نقوم بإنشاء مصادقة في حال لم تكن موجودة كالتالي: php artisan make:auth نقوم بإنشاء مودل للمدراء كالتالي، ونقوم بملء الحقول اللازمة ضمنه: php artisan make:model Admin ثم نقوم بإنشاء المتحكم الخاص بالمدراء: php artisan make:controller AdminController class AdminController extends Controller { public function __construct() { $this->middleware('auth:admin'); } public function index() { return view('admin'); } } ونلاحظ هنا أنه تم استخدام middleware وهو admin، ولكن لمستخدمي الموقع يجب أن نستخدم مصادقة أخرى، حيث لا يجب على المستخدمين العاديين الدخول إلى لوحة التحكم للموقع، فنقوم أولاً بمعالجة عملية المصادقة وتسجيل الدخول للمدراء عن طريق إنشاء متحكّم خاص بذلك كالتالي: php artisan make:controller Auth/AdminLoginController أما للمستخدمين العاديين فسيتم التحقق والمصادقة بشكل منفصل كالتالي: public function showLoginForm() { return view('auth.login'); } وأخيراً لا ننسى تعديل ملف config/auth.php وإضافة الجزئية الخاصة بمصادقة المدراء كالتالي: //المصادقة الافتراضية 'defaults' => [ 'guard' => 'web', 'passwords' => 'users', ], //مصادقة المدراء أو المشرفين التي قمنا بإنشائها 'admins' => [ 'driver' => 'eloquent', 'model' => App\Admin::class, ], // // 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'admin' => [ 'driver' => 'session', 'provider' => 'admins', ], ], // // 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\User::class, ], 'admins' => [ 'driver' => 'eloquent', 'model' => App\Admin::class, ], ], // وهنا يمكننا ملاحظة أنه تمكّنا من فصل كيان المستخدم المدير عن كيان المستخدم العادي، عن طريق استخدام جدولين مختلفين في قاعدة البيانات واستخدام guard مختلف وجلسات مختلفة لكل منهما. وبنفس الطريقة يمكن إضافة نوع جديد آخر ينتمى أيضاً لجدول آخر في قاعدة البيانات وله صلاحيات وصول مختلفة.
    1 نقطة
  23. الحذف الناعم أو soft delete هي نوع من أنواع حذف البيانات ولكن بدل من التخلص من البيانات بشكل تام يتم إخفائه والاحتفاظ بالبيانات في الجداول لديك. ويتم ذلك عن طريق إضافة عمود جديد في الجدول باسم deleted_at أو أي اسم تريده ولكن هذا هو المتعارف عليه, حيث يكون فارغاً أو null بالوضع الطبيعي ولكن عن تطبيق ال soft delete على أحد العناصر يتم إضافة تاريخ الحذف في deleted_at. ويمكن تفعيل هذه الميزة عن طريق إضافة Trate use SoftDeletes; بداخل ال Model المراد تطبيق هذه الخاصية عليها وكذلك بداخل الجدول أو migration الخاص بهذا ال Model نضيف $table->softDeletes(); حتى يضيف العمود deleted_at بنوع date على هذا الجدول. وهكذا تضاف الحذف الناعم لدينا. ويترتب على هذه الميزة أنه في حال كانت هنالك بيانات محذوفة بالطريقة الناعمة فلا يمكنك إستدعائها بالطريقة العادية مثلاً: Product::all(); فيجب أن تضيف عليها الدالة withTrashed كما يلي: Product::withTrashed() ->get(); هذا في حال كنت تريد تضمين البيانات الغير محذوفة مع البيانات المحذوفة حذفاً ناعماً, أما إذا كنت تريد فقط البيانات المحذوفة بشكل ناعم نستخدم: Product::onlyTrashed(); وفي حال كنت تريد إستعادة إحدى البيانات من كونها محذوفة بطريقة ناعمة نستخدم الدالة restore كالتالي: $product = Product::withTrashed()->where('id', 1)->restore(); وأي معلومات إضافية يمكننا مساعدتك بها ولكن يمكن التوجه أيضاً إلى التوثيق الرسمي للارافيل.
    1 نقطة
  24. يُمكن إستخدام eloquent لحذف السجلات بشكل ناعم، عند الحذف الناعم للسجل، لن تُحذف السجلات فعليًّا، وإنما ستُعيّن الخاصية deleted_at على السجل وتُحفظ في قاعدة البيانات. في حال كان السجل يملك قيمة deleted_at غير فارغة non-null، هذا يعني أنه قد حُذف. لتمكين الحذف الناعم لسجل ما نضيف ال trait SoftDeletes للمودل الذي نريد أن يُطبق الحذف الناعم: <?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; class User extends Model { use SoftDeletes; } و نضيف العمود deleted_at لملف التهجير الخاص بالمودل: <?php Schema::table('users', function ($table) { // other fields $table->softDeletes(); }); بهذا الشكل عند إستخدام التابع delete على أي كائن من الصنف User: <?php $user = User::find(1); $user->delete(); لن يتم حذفه فعلياً بل سيتم تعديل السجل بتعديل قيمة deleted_at إلى التاريخ الذي تم حذف السجل فيه. و سيبقى في قاعدة البيانات، و عند الإستعلام على المُستخدمين: <?php $users = User::all(); لن تظهر السجلات المحذوفة بشكل ناعم مع السجلات الكلية. هناك عدة توابع أخرى يُمكن إستخدامها لمعرفة ما إذا كان سجل ما محذوف بشكل ناعم، او جلب السجلات المحذوفة ناعماً بالإضافة إلى عملية إسترجاع هذه السجلات يُمكنك الإطلاع عليها من خلال توثيق موسوعة حسوب: الحذف الناعم (Soft Deleting)
    1 نقطة
  25. في الحذف الناعم أو soft delete عند حذف نموذج ما ، لا تتم إزالته بالفعل من قاعدة البيانات الخاصة بك. بدلاً من ذلك ، يتم تعيين الطابع الزمني delete_at على السجل. وبذلك تمكّنك لارافيل من استعادة البيانات فيما بعد. لتمكين عمليات الحذف الناعمة لنموذج ، حدد خاصية softDelete على النموذج، مثال: عند كتابة ملفات التهجير، نضيف الحقل softDeletes كالتالي: use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateItemsTable extends Migration { public function up() { Schema::create('items', function(Blueprint $table) { $table->increments('id'); $table->string('title'); $table->text('description'); $table->softDeletes(); $table->timestamps(); }); } public function down() { Schema::drop("items"); } } ثم عند تعريف المودل item نقوم باستخادم use softDeletes كالتالي: namespace App; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; class Item extends Model { use SoftDeletes; public $fillable = ['title','description']; protected $dates = ['deleted_at']; } والآن، عند استرجاع بيانات محددة، ستقوم لارافيل بإعادة السجلات فقط التي تحوي القيمة null ضمن العمود deleted_at، أي بمعنى آخر سيتم إهمال أي سجلات تحوي قيم ضمن الحقل deleted_at وكأنها غير موجودة، ولكن يمكنك بأي وقت الرجوع إلى قاعدة البيانات ورؤيتها حيث لن يتم حذفها بشكل نهائي: مثلاً عند تنفيذ الأمر التالي: $data = Item::get(); ستعيد كافة الحقول التي قيمة deleted_at فيها هي null أما لاستعادة كافة السجلات (المحذوفة والغير محذوفة) عندها يجب أن تستعمل الأمر التالي: $data = Item::withTrashed()->get(); إذاً، الفائدة هنا هي عند وجود بعض السجلات التي ترغب بعدم حذفها نهائياً من قاعدة البيانات وحتى لا يتم استرجاعها عند كل عملية جلب للبيانات من القاعدة يمكنك استخدام تقنية الحذف الناعم وبالتالي ستبقى ضمن قاعدة البيانات ويمكنك الرجوع إليها عند الضرورة ولكن لن يتم استرجاعها إلا عندما ترغب بذلك. وهذا مفيد جداً لأنه يحسّن من الأداء والسرعة.
    1 نقطة
  26. نعم مفهومك عنها صحيح وهي غالبا تستعمل مع الملفات التي تحتوي على عدد لا بأس به من القيم تفاديا لاستهلاك الميموري ويمكنك ان ترى في المثال في الاسفل def numbers_sum(nums): result = [] for i in nums: result.append(i+i) return result my_nums = numbers_sum([1, 2, 3, 4, 5]) print(my_nums) # [2, 4, 6, 8, 10] في المثال لدينا قائمة وببساطة نحن نرجع قائمة اخرى للقيم مجموعة لنفسها وطول القائمة هو 5 لكن لو كانت لديك قائمة طولها 100 مليون وادخلتها للمعالجة في الكود السابق سوف تلاحظ مشاكل في الكمبيوتر وقد يتوقف عن الاستجابة اذا كان كمبيوتر قديم نوعا ما ولحل المشكلة نستخدم generators ونقرا القائمة قيمة بعد قيمة def numbers_sum(nums): for i in nums: yield(i+i) my_nums = numbers_sum([1, 2, 3, 4, 5]) print(my_nums) # <generator object numbers_sum at 0x7f95f264f518> for num in my_nums: print(num) الكود في الاعلى هو محاكات للكود السابق لكن باستخدام generators الفرق هنا انك ستتلقى كل قيمة على حدى عوض انك ستتلقاهم في قائمة وتلاحظ انني استخدمت for loop للدوران على my_nums وذلك لان for loop لديها القابلية للتوقف عند انتهاء القيم فعند مناداة next على my_num اكثر من 5 مرات في مثالنا سنتحصل على خطأ برمجي يخبرنا ان القيم انتهت print(next(my_nums)) # 2 print(next(my_nums)) # 4 print(next(my_nums)) # 6 print(next(my_nums)) # 8 print(next(my_nums)) # 10 print(next(my_nums)) # error StopIteration
    1 نقطة
×
×
  • أضف...