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

شرف الدين حفني

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

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

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

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

    2

كل منشورات العضو شرف الدين حفني

  1. الproblem solving يعتمد بشكل أساسي على الخوارزميات وهياكل البيانات, من الجيد أن تبدأ بدراسة الخوارزميات وهياكل البيانات, فإن جزأ كبير من المشكلات ستجده مبنى على تكتيكات مثل: الخوارزمية الجشعة(greedy algorithm) والتي تشبه الى حد كبير الحل البديهى للمسألة , حيث أنك تمر على عناصر المدخلات عنصر عنصر وتقم بعملية على كل عنصر حتى يتم حل المشكلة فرق واغزٌوا(divide and conquer) والتي اكتسبت إسمها من أحد تكتيكات الحروب في العصور الوسطى, حيث كان يتم تفرقة جيش الخصم إلى فرق صغيرة يسهل محاصرتهم للإقصاء, حيث يتم في هذا التكتيك الخوارزمي تقسيم المشكلة إلى مشاكل اصغر بإستخدام الrecursion ويتم حل كل مشكلة على حدة دون أن تتداخل مع مثيلتها حتى يتم حل المشكلة البرمجة الديناميكية(dynamic programming) تشبه الى حدٍ كبير التكتيك السابق ولكن لا تتم بالrecursion , وتتداخل نواتج حل المشكلات الصغيرة سويا حتى يتم إستخدام تلك النواتج لحساب الناتج للمشكلة ككل بفهمك لتلك التكتيكات وتكتيكات مختلفة أخرى بالإضافة إلى التدريب على مشكلات مختلفة سيساعدك على ترتيب وتحديد خطواتك لحل المشكلة, ولكن ستقابلك مشكلة أخرى وهى كيفية تخزين المدخلات للمشكلة؟ وهنا يأتى دور هياكل البيانات حيث تتعرف على هياكل مختلفة لحمل البيانات مثل المصفوفة array , الصفqueue, المكدس stack, القائمةlist, كل هيكل من تلك الهياكل المختلفة لديه عيوب ومميزات وكل هيكل منهم يُعد الأنسب لمشكلة ما الملخص: تعلم الخوارزميات وهياكل البيانات بالإضافة إلى اساسيات الرياضيات وتدرب على مشكلات مختلفة وعندها ستتعلم مواضيع أخرى تساعدك في فهم باقى المشكلات التي سوف تقابلها
  2. سأشرح لك الخطوات المنطقية ولكن عليك كتابة الشفرة البرمجية بفسك حتى تستفاد من التطبيق العملي تعتمد فكرة التحويل بشكل أساسي على أخذ ناتج قسمة العدد العشري على 2 ,فإما يكون باقي القسمة صفرًا أو إثنين نبدأ بأخذ الرقم من المستخدم وتخزينه في متغير يعبر عن الرقم العشري ننشئ متغير يعبر عن الرقم الثنائي نقوم بعمل حلقة تكرارية while loop ونضع بداخلها شرطًا أن لا يكون العدد العشرى يساوي صفرًا في كل دورة من الحلقة نقم بالقسمة على إثنين ونضيف باقي القسمة إلى متغير الرقم الثنائي تستمر تلك العملية حتى تصبح قيمة الرقم العشري صفرًا وفي هذه الحالة يكون متغير الرقم الثنائي يحمل القيمة التي تعبر عن ناتج تحويل الرقم العشري إلى ثنائى
  3. having تستخدم عند إستخدام group by , ويتم إستخدامها لتصفية المجموعات , بينما where يتم إستخدامها لتصفية التسجيلات مثال: select name, Count(1) From users Where rating >4 Group By rating في هذا الكود يتم إختيار الإسم وعدد العناصر من الجدول users ويتم فلترة التسجيلات حيث يتم إختيار فقط التقييمات الأكبر من 4 , ثم يقسمو مجموعات حسب تقييمهم حسنا ماذا إن أردنا تصفية المجموعات الناشئة بدلًا من تصفية التسجيلات فقط؟ , إليك مثال select name, Count(1) From users Where rating >4 Group By rating HAVING count(1)>3 في هذا المثال قمنا بتصفية التسجيلات حيث نختار الطلاب الذين تقييمهم أعلى من 4 وأيضًا قمنا بتصفية المجموعات حيث عرضنا فقط المجموعات التي تحتوي على أكثر من ثلاث طلاب, تلك هي وظيفة العبارة having , أن تقوم بتصفية المجموعات الناشئة من دوال الaggregation
  4. ال node js تستخدم thread واحد لجميع الطلبات ,ولكن في الكواليس يتم إستخدام multi threads, ما معنى هذا ؟ معنى هذا أن عمليات القراءة والكتابة(i/o operations) تحدث بإستخدام الmultithreading , وتلك العمليات تشمل القراءة والكتابة من و إلى قاعدة بيانات القراءة والكتابة من و إلى شبكة القراءة والكتابة من وإلى المساحة التخزينية أي عملية قراءة وكتابة أخرى فمثلا هذا الكود funca(){ ///some code// fetch(URL).then(()=>callback()); ///some code } هنا يتم إستخدام الmulti threading في الخلفية حيث تتم عملية جلب البيانات بإستخدام الدالة fetch من خلال thread أخر محجوز في الnode js من أجل عمليات القراءة والكتابة, وفي نفس الوقت لدينا الthread الذى يستقبل الطلبات من المستخدمين والذى يقوم بتنفيذ باقي الكود فإذا كان لدينا 10 مستخدمين قاموا بإرسال طلب لكل مستخدم وكل طلب منهم يحتوي على عملية قراءة من قاعدة بيانات, في هذه الحالة يكون لدينا thread واحد فقط لمعالجة ال10 طلبات, و10 threads أخرين من أجل تنفيذ عمليات القراءة والكتابة
  5. هذا لأن قاعدة البيانات عند بحثها عن حقول من الindex يكون الأمر مختلفًا عن بحثها عن حقول عادية, والprimary key و الunique يعدون من الindexes ولكن كيف يختلف البحث ؟ عندما تقوم بتخزين تسجيل ما فإن قاعدة البيانات تضع قيمة الindex الخاص بهذا التسجيل بداخل هيكل بيانات من نوع الhash table (ليس جميع قواعد البيانات يستخدمون نفس نوع هيكل البيانات فبعضهم يستخدم الbinary tree ولكن حتى تفهم جيدا فلنتعامل مع الHash table) والhash table هو عبارة عن مصفوفة ولكن بدلا من الوصول إلى العنصر بإستخدام ترتيبه نعصر عليه بإستخدام الkey فمثلا hash_table[ "sharaf":"ashraf", "mahmoud":"hossam" ] الhash table هذا يخزن مفتاح sharaf ويحمل قيمة ashraf كيف يتم هذا التخزين؟ يتم إجراء عملية hashing للمفتاح ويتم وضع القيمة المرتبطة بالمفتاح في الذاكرة عند العنوان الناتج من عملية الhashing التي تتم للمفتاح, فإذا ان كان لدينا قيمة اي مفتاح في الجدول نستطيع أن نصل إلى قيمته لحظيًا بدون إجراء بحث لأننا بالفعل نمتلك عنوانه في الذاكرة (قيمة الhashing لهذا المفتاح) بالتالي عندما تقوم بتخزين سجل ما في قاعدة البيانات يتم بيانات هذا السجل كقيمة للمفتاح المسمى على إسم الindex فبالتالي عندمة تقوم بالبحث عن سجل بإستخدام الindex تحصل على السجل لحظيًا, على عكس باقي الحقول التي تعطيك قيمة السجل بعد إجراء عملية بحث على جميع السجلات في الجدول
  6. علاقة الmany to many أو للإختصار nm حتى يتم إنشاؤها نحتاح أولاً إنشاء جدول حتى يتم فيه تخزين المفتاح الرئيسي للجدولين المراد عمل علاقة بينهما فمثلاً table user{ name,age,id } table article{ title,content,id } table user_article{ user_id(references user(id)), article_id(references article(id)) } هنا لدينا جدولين هما user و article , المستخدم يمكنه كتابة عدة مقالات, كما أن المقالة الواحدة ممكن كتابتها من قِبل عدة مستخدمين , فإذا بينهما علاقة كثير:كثير (may to many) , الحل أننا قمنا بإنشاء جدول ثالث يربط بين الجدولين السابقين, فإذا يجب تطبيق هذا الأمر في sequelize كما في المثال الآتي: const User_Article = sequelize.define('user_article', {}, { timestamps: false }); بعد أن قمنا بإنشاء الجدول الرابط بينهما نحتاج أن نربطه بهم في العلاقة فردي:فردي كنا نستخدم الدالة model.hasOne بينما في العلاقة فردى:كثير نستخدم model.hasMany من طرف وmodel.balongsTo من طرف أخر بينما في هذا النوع من العلاقات كثير:كثير نستخدم model.belongsToMany كما في الشفرة بالأدنى User.belongsToMany(Article, { through: User_Article }); Article.belongsToMany(User, { through: User_Article }); بهذا الشكل قد انشأت علاقة كثير:كثير بين الجدولين, مع مراعاة أن يتم كتابة الجدول الرابط في الخاصية through بالإضافة أنه ليس من الإلزامى ان تقم بإنشاء وتعريف الجدول الرابط بنفسك فإن sequelize ستقوم بذلك بالنيابة عنك,ولكن يفضل إنشاؤه بنفسك في حالة اردت التعديل على إحدى الخصائص الإفتراضية أو إضافة أحد الأعمدة
  7. Invent your computer games with python ليس مجانى ولكن يمكنك البحث عنه بصيغة pdf
  8. هذا لانك قمت بإختيار الجدول article_reviews مرتين مرة قبل الinner join مرة بعد عبارة ال inner join الحل: عليك بإختياره مرة واحدة في الinner join وحذفه من العبارة الأسبق لها كما هو موضح في الشفرة البرمجية بالأدنى select u.*,a.rating from users u inner join article_reviews a on u.id=a.user_id
  9. هذا لأنك قمت بعمل علاقة join بين article_reviews و article_reviews a بينما أنت تحاول الوصول إلى بيانات داخل الجدول users وهذا غير ممكن يجب أن تعدل العلاقة join لتجعلها بين الجدول users و article_reviews عن طريق تعديل الكود إلى الشكل الآتي select u.*,article_reviews.rating from article_reviews, users u inner join article_reviews a on u.id=a.user_id بهذا الشكل العلاقة أصبحت بين الجدولين users و article_reviews حيث أنه يجب وضع جدولي العلاقة قبل وبعد الinner join مباشرةً
  10. سأشرح لك طريقة الحل ولكن عليك كتابة الكود بنفسك حتى تستفاد من التطبيق البرنامج الأول: ستقوم بعمل مصفوفة مكونة من 10 عناصر وتقم بعمل حلقة تكرارية ,في كل لفة من الحلقة التكرارية تقوم بأخذ قيمة من المستخدم بإستخدام الدالة cin ستقوم بتعريف ثلاث متغيرات, max, min, temp ونقم بإعطاء المتغيرين min,max قيم إفتراضية تساوى قيمة العنصر رقم 0 في المصفوفة سنقوم بتعريف حلقة تكرارية أُخرى وفي كل لفة نقوم بمقارنة العنصر مع المتغيرين max, min إذا كانت قيمته أكبر من max نقم بعملية swapping بينهما بإستخدام المتغير temp إذا كانت قيمته أقل من min نقم بعملية Swapping بينهما بإستخدام المتغير temp في نهاية الحلقة ستجد أن العنصرين min, max اخذو قيمتي أكبر وأقل عنصر في المصفوفة البرنامج الثاني: تعتمد فكرة هذا البرنامج على مبدأ أننا نتعامل بالنظام العشري في الارقام حيث اكبر رقم يحمل خانة واحدة هو 10, يوجد انظمة اخرى مثل الثنائي الذي اكبر خانة به 2 او الثماني او السادس عشر إعتمادا على هذا المبدأ يمكننا معرفة أخر خانة في العدد عن طريق إيجاد باقي القسمة على 10, فمثلا إذا كان العدد 152 وقسمناه على 10 نحصل على باقي قسمة 2 إذا يمكننا أن نقوم بعمل حلقة تكرارية في كل لفة نأتي بباقي قسمة العدد ونضيفها إلى متغير العدد المعكوس بعد ضربه في 10 , ثم نقسم العدد القديم على 10, وتستمر الحلقة حتى تصل قيمة العدد القديم إلى 0, بذلك تجد المتغير الجديد يحمل قيمة العدد القديم ولكن معكوسة
  11. ذلك طبيعي لأن react تعمل في الواجهة الأمامية, حتى يظهر الكود في الpage source يجب أن تقم بعمل server side rendering وذلك من خلال عدة تقنيات اشهرهم next.js ولكن لا تقلق فإن المعلومات تظهر لدى جوجل,ولكنها لا تظهر لدى باقي زواحف الإنترنت (web crawler)
  12. سبب المشكلة أنك لا تضع parameters في الخانة الثانية من دالة الuseEffect مما يجعلها تعمل في كل مرة يحدث تغيير للstate وفي نفس الوقت عندما تعمل الدالة فإنها تقوم بتغيير الstate فبالتالي تعمل مرة أخرى إلى ما لا نهاية, الحل أن تضع مصفوفة بها المتغيرات التى تعتمد عليها دالة الuseEffect, وإن كان لا يوجد متغيرات تعتمد عليها فلتمرر مصفوفة فارغة كما في الشكل التالي useEffect(()=>{ axios.get("/api/"+id+"/label") .then(res=>setLabel(res.data),[]) })
  13. ذلك لأن الmysqlclient هو واجهة للmysql في لغة البايثون , ولكنه ليس الmysql نفسها الحل أن تقوم بتثبيت الmysql اولاً عن طريق هذا الأمر إن كنت تستخدم نظام تشغيل لينكس sudo apt-get install mysql-server أما في حالة كنت تستخدم نظام تشغيل ويندوز, يمكنك تنزيل خادم الmysql من الموقع الرسمى ومن ثم يمكنك تثبيت الconnector pip install mysql-connector-python ومن ثم تثبيت الmysqlclient pip install mysqlclient
  14. الuse strict تجعل البرنامج يعمل في وضعية الstrict إذا ماهي وضعية الStrict ؟ وضعية الstrict تفرض عليك بعض القيود عند كتابة الشيفرة البرمجية , تلك القيود مهمتها أن تجعل الشيفرة السيئة المقبولة "مرفوضة" ,بمعنى أن بعض العادات السيئة التي كان بإمكانك القيام بها عند كتابة شيفرة الجافاسكريبت لن يعد بإمكانك القيام بها , أمثلة من تلك العادات : لا يمكنك الإشارة إلى متغير أو كائن بدون أن تقم بتعريفه مسبقاً فمثلاً "use strict"; name="sharaf" ; هذه الشفرة في المسبق كانت مقبولة ولن تتسبب بأخطاء, لكن بعد تفعيل وضعية الstrict او(الوضعية الصارمة) سيتسبب هذه السطر بخطأ لأنك قمت بالإشارة إلى المتغير name بدون أن تقم بتعريفه لا يمكنك حذف كائن أو متغير let name = "sharaf"; delete name; هذه الشفرة تعمل بدون الوضعية الصارمة ولكن بعد تفعيل الوضعية الصارمة سيحدث خطأ لأنك حاولت أن تحذف المتغير name وهذا لا يعُد مقبولاً في الوضعية الصارمة لا يمكنك إستخدام النظام الثماني let octa_number = 010; هذه الشفرة ستتسبب في خطأ عند تفعيل الوضعية الصارمة لأن القيمة 010 تعد في النظام الثماني ليس العشري لا يمكنك الكتابة إلى كائن قمت بتعريفه مسبقاً بأنه مُعد للقراءة فقط "use strict"; const car = {}; Object.defineProperty(car, "name", {value:"bmw", writable:false}); car.name ="kia"; تلك الشفرة أيضا ستتسبب بخطأ عند إستخدام الوضعية الصارمة بسبب محاولتك للتعديل على كائن مُعد للقراءة فقط ويوجد العديد من القواعد الأخرى ,حتى لا أقوم بتشتيتك سأترك لك رابط ينص على القواعد جميعها اما عن فائدة هذه الوضعية فيمكن تلخيصها في الآتي: تقوم بإزالة ما يسمى بالأخطاء الصامتة, وهي تلك الأخطاء التي قد تسبب مشاكل في الشفرة مستقبلاً ولكن لا توقف تنفيذه فبالتالي تتحول الي bugs تجبرك على كتابة شفرة نظيفة منظمة قابلة للقراءة بسهولة تحسن من أداء الشفرة حيث أن عمليات التحسين "optimizations" يستطيع المحرك أن يحددها ويقم بها بسهولة أكبر عند تفعيل هذه الوضعية وها هو رابط يحتوي على قواعد الوضع الصارم https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode وتلك مقالة من اكاديمية حسوب تشرح الوضع الصارم
  15. الinheritance "الميراث" عندما يكن لدينا الكلاس A وكلاس اخر من نفس نوعه ولكن مزود بخصائص اكثر يسمى class B , وعادة يتم استخدام الميراث كما قلنا عندما يكون B فعلا صنف ممتد من A مثل الuser وال adminUser يتم الميراث كما فى المثال: class User{ String name; int age; /////////getters and setters/ } class SuperUser extends User{ banUser(){ //////logic to ban user } unbanUser(){ ////logic to unban user } } في المثال السابق نجد ان الSuperUser لديه جميع خصائص الكلاس User ولديه بالاضافة إلى ذلك وظائف جديدة كحظر وفك الحظر عن المستخدمين ولكن إذا كان لدينا كلاس أخر يدعى book ,فهنا ليس من العقل ان يتم ميراثه من قِبل الكلاس user لإنهم ليسوا نفس النوع ,فهنا يتم استخدام الcomposition وهو أن يتم وضع الbook على هيئة خاصية للكلاس user كما في المثال class book{ String name; int price; ///////getters and setters//// } class User{ String name; int age; Book b; ///////getters and setters////// } هنا يمكننا استخدام دوال الكلاس book بدون ميراثه عن طريق استدعاء الكائن b وبوجه عام فإن الcomposition يتم تفضيله عن الinheritance(ميراث) لعدة اسباب من ضمنها : عدد من لغات البرمجة لا يدعم تعدد الميراث, بالإضافة الى أن تعدد الميراث يسبب مشاكل وتعقيد الcomposition يمكنك من تغيير نوع الكلاس المستخدم فى مرحة التشغيل(runtime) مثلاً إذا كان لدينا كلاس يسمى SuperBook وكلاس يسمى OrdinaryBook وكلاً منهم يشترك في نفس الواجهة البرمجية interface يمكنك في مرحلة الruntime أن تقم بتغيير خاصية الbook لدى الuser إلى الSuperBook او الOrdinaryBook ,بينما الميراث لا يحدث إلا في مرحلة الترجمة(compile time) الcomposition اسهل في عملية الاختبار
  16. لا يمكنك إرسال رسائل من عميل لآخر بشكل مباشر, يجب إرسال الرسائل الى الخادم اولاً ثم يتم تمريرها الى العميل الاخر , كما في المثال بالادنى , لدينا endpoint لدى الخادم تسمى msg واللتي تأخذ parameters عبارة عن نص الرسالة:message معرف المرسل إليه :recieverId this.io.on('connection', (socket) => { socket.on('msg', (message) => { socket.broadcast.to(data.recieverId).emit('getMsg',{ msg:data.msg }); }); وتقم تلك الendpoint بإرسال الرسالة الى الكلاينت المطلوب من خلال الدالة broadcast.to.emit حتى يحدث fire لل event المسمى getMsgالكلاينت المرسل إليه ويستقبل الرسالة كما في المثال: clientSocket.on("getMsg",(data)=>doSomethingWithData(data)) ويتم إرسال الرسائل من العميل الى الخادم عن طريق اطلاق الحدث msg لدى الخادم من خلال الكلاينت كما هو موضح: socketClient.emit("msg",data);
  17. يمكنك القيام بذلك من خلال مكتبة bcrypt import bcrypt بعدها نقم بتوليد الsalt وهو عبارة عن نص عشوائى يتم اضافته للشيفرة حتى لا يمكن توقعها salt = bcrypt.gensalt() بعدها نحصل على الhash hashed = bcrypt.hashpw(passwd, salt)
  18. يمكنك إنجاز ذلك بسهولة من خلال تعديل الخاصية timeout فى السيرفر كما هو موضح في هذا المثال const server = app.listen(app.get('port'), function() { debug('hasoub is running on port ' + server.address().port); }); server.timeout = 1000;//ضع هنا قيمة الوقت اللذي تريده
  19. يمكنك تحقيق ذلك عن طريق إستخدام الmodule المسمى بcsvtojson ويمكنك الحصول عليه عن طريق تثبيته من خلال حزمة الادوات npm من خلال هذا الأمر npm install csvtojson ولتقم بتحويل ملف csv الى json نفعل كالأتي const csvParser=require("csvtojson"); csvParser().fromFile("ضع هنا مسار الملف").then(jsonFile=>doSomeThing(jsonFile)) وفي حالة كان ملف الcsv ضخم يمكنك تحويله عن طريق استخدام الstream وال pipe كما هو موضح فى المثال أدناه csv() .fromStream(ضع هنا reference لstrem تقم بقراءة الملف) .subscribe(function(json){ //يجب عليك معالجة كل جزأ من الملف على حدة لأنه يصل من خلال الstreamعلى هيئة chunks return new Promise(function(resolve,reject){ doSomeThing(json,function(){resolve()}) }) }) وللتوضيح, الفرق بين الكود بالأعلى وبالأدنى أن بالأعلى يتم قراءة الملف كله في الذاكرة ومن ثم تتم العملية عليه, بينما في المثال بالأدنى يتم قراءة الملف على هيئة اجزاء صغيرة ومعالجة كل جزأ منها على حدة حتى لا تمتلئ الذاكرة
  20. عادةً كلمات السر فى قاعدة البيانات لا يحدث لها عملية تشفير وإنما يحدث عليها عملية Hashing ويوجد فرق بين التشفير وبين الhashing , فإان التشفير هو طريقة لتحويل النص الى نص اخر لا معنى له ويكن عادةً هناك ما يسمى بمفتاح التشفير اللذي يمكنك من تحويل الشيفرة الى الكلمة الاصلية مرة اخرى وانما الHashing هو عبارةة عن دالة احادية الإتجاه, اى إن دالة الHashing تقم بأخذ النص الأصلي وتحويله الى نص اخر , ولكن لا يوجد مفتاح ليقم بإرجاع الشيفرة الى النص الاصلي, وهذا هو ما يحدث للكلمات السرية في قواعد البيانات من اجل ضمان امن البيانات فإذا حدث اختراق في قاعدة البيانات لا يستطيع المخترق معرفة مفتاح التشفير ويحصل على جميع المعلومات, فإنه لا يوجد في الأساس مفتاح تشفير وبالتالي لا يكون المخترق قادرً على اختراق البيانات وتتم عملية الHashing عادة بإستخدام دالة تسمى B-crypt وهي من أشهر دوال الhashing
  21. يوجد عدة فروق بينهما استاذ باسل مثل: app يعمل فى الroot level بينما res لا يعمل الا فى الroute/middleware دالة app.render يجب ان تمدها بالcallback وتقم بارجاع الhtml المزود فيه, بينما res.render فإن هذا الأمر اختياري, يمكنك ان لا تمدها بالcallback وفي هذه الحالة سوف تقوم الnodejs بإرجاع status code 200
  22. https يعني ان موقعك مزود بssl وأمن للتواصل, والكود اللذي كتبته انت لا يتضمن تلك المعلومة, انما يتضمن معلومات اخرى : function getBaseUrl( ) { if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') echo "https".$_SERVER['HTTP_HOST'].strrev( strstr( strrev( $_SERVER['PHP_SELF'] ), "/" ) ); else echo "http".$_SERVER['HTTP_HOST'].strrev( strstr( strrev( $_SERVER['PHP_SELF'] ), "/" ) ); } ينقصك هنا ان تتأكد اذا كان الاتصال مؤمن تضف كلمة https للرابط عدا ذلك تضف http فقط,وهذا يمكن اتمامه على النحو التالي:
  23. حسب ما فهمت انك تريد ان تبدل المسافات بعلامة - صحيح؟ إذا كان الأمر كذلك فان سبب المشكلة لديك ان كلا من السطرين $string = preg_replace('#[^\w]#', ' ' , $string); $string = preg_replace('#[\s]+#', ' ', $string); كل ما يفعلونه انهم يقومون بتحويل المسافات, الى مسافات مرة اخرى , وهذا لان الرمز \s يرمز للمسافات والرمز \w يرمز لاى رمز غير الحروف الابجدية, فاذا انتا تقوم بتحويل الرموز والمسافات الى مسافات مرة اخرى بدل من تحويلهم الى شرطة - والسطر الاخير والاول $string = trim($string); return trim(strtolower($string), '-') وظيفتهم أنهم يمسحون المسافات من الجانب الايمن والايسر بفضل الدالة trim ولكن ماذا عن المسافات فى المنتصف بين الكلام؟ الحل ان تقم باستخدام دالة preg_replace كما فعلت سابقا, ولكن تقم باستبدالهم بشرطة - بدلاً من تبديلهم بمسافات كما في الكود الاتي: function seo($string) { $string = trim($string); $string = preg_replace('/\s+/', '-', $string); return strtolower($string); }
  24. يمكنك تحقيق ذلك بإستخدام unique_together فبعد تعريف الموديل يمكنك إستخدام الunique_together لجعل حقلين نادرين , كما في المثال التالي class Post(models.Model): id = models.AutoField(primary_key=True) field1 = models.CharField(max_length=150) field2 = models.CharField(max_length=150) class Meta: unique_together=('field1','field2') بذلك الشكل لقد قمنا بجعل الحقلين field1, field2 بمثابة حقل مركب نادر
  25. تقوم دالة الهوك useEffect بعمل تلك الوظيفة بالإضافة إلى باقي الدوال الخاصة بدورة حياة الكائن , كما هو موضح في الأمثلة القادمة يمكنك محاكاة الدالة componentDidMount ببساطة عن طريق إدخال مصفوفة فارغة في المدخل الثانى للدالة كما في هذا الشكل const HsoubComponent=()=>{ const [a,setA()]=useState(""); useEffect(()=>doSomething(),[]); } كما يمكنك محاكاة الدالة componentDidUpdate عن طريق إدخال القيم اللتي يترتب عليها تحديث الcomponent في المدخل الثاني كما في هذا الشكل const HsoubComponent=()=>{ const [a,setA()]=useState(""); useEffect(()=>doSomething(),[a]); } كما يمكنك محاكاة الدالة componentWillUnmount عن طريق وضع return واللتي تمثل عملية الclean up او التنظيف للموارد const HsoubComponent=()=>{ const [a,setA()]=useState(""); useEffect(()=>{ doSomething() return( doCleanup(); ) },[]); }
×
×
  • أضف...