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

كل الأنشطة

تحدث تلقائيًا

  1. الساعة الماضية
  2. وعليكم السلام ورحمة الله وبركاته . نعم الأمر بسيط إن شاء الله . أولا تاكد من العميل أى لغة يريد تنفيذ جزء الواجهة الخلفية سواء php او nodejs . ويمكنك البحث على اليوتيوب كيفية تسجيل مستخدم جديد و تسجيل الدخول وستجد العديد من الشروحات حول ذلك . واذا كان يريد إستخدام php فيمكنك إستخدام إطار عمل laravel حيث سيسهل الكثر من الأمور عليك . ويمكنك قراءة هذا المقال حول ذلك اما إذا وجدت الأمر صعب وسياخذ وقت طويل فيمكنك أن تستعين بمطور backend يساعدك فى ذلك
  3. السلام عليكم طلب مني عميل ان اقوم بعمل صفحه للشركه الخاصة به بعدها طلب مني انشاء قاعده بيانات لتسجيل الدخول وتسجيل دخول جديد وانا لست backend هل عمل هذا بسيط بحيث يمكن أن ابحث واقوم به ام استعين ب backend
  4. اليوم
  5. public_html.zipالسلام عليكم اني صممت هذا الموقع واريد https://samabludan.com. لكن الموقع جدا بطيء اتمنى واحد يطيني رائيه لان اهواي سئلت ومحد اطه جواب اني اشتركت بالكورس لهدف المساعده وايضا راح اضيف ملفات الموقع واتمنى اتشوفوه وتعرضون الموقع حتى اعرف وين خطاي واعالجه public_html.zip
  6. السلام عليكوم ورحمة الله و بركاته ،اخواني في الله احتاج كيفية برمجة سوفتوير الرسيفر علما اني امتلك التعريفات الازمة مثل البوت و الاشارة و المداخل إلخ... انا بعد البحث علمت ان السوفت يمكن تعديلة من خلال برنامج hex على الكمبيوتر لكن البرمجة لا اعرف كيف يمكنني البرمجة و دمج التعريفات و انا لا املك الخبرة الازمة فهل من مساعد.
  7. بالتأكيد استخدام الـ templates الجاهزة يكون مفيداً في بعض الحالات . حيث انه يوفر الوقت والجهد في انشاء الهيكل الاساسي للموقع/التطبيق. مع إجراء تعديلات وإضافات على الـ template حتى يناسب احتياجات العميل ولكن يعتمد على الإتفاق بينك وبين العميل فهناك عميل يعرف ما يريد تنفيذه ويخبرك بذلك إذا كان يحتاج بناء الموقع من الصفر وهناك ما يهمه التكلفه فقط فيمكنك توضيح ذلك له وهناك العديد من المواقع لشراء ال templates مثل بيكاليكا و ThemeForest
  8. السلام عليكم هل من المفضل استخدام Templates الجاهزة في مشاريع الفريلانس ؟ مثلا اعرض الtemplate على العميل فان اعجبه اقوم بشراءه (ان كان مدفوعا) واعدل عليه ! بالمناسبة أين اجدNextjs templates ?
  9. اطلعت على الشيفرات الخاص بك، وتبدو صحيحة، وأنت بالفعل قمت بعمل الاتصال مع قواعد البيانات، وإرسال البيانات إليها، المفترض أن يتم الاتصال ثم تسجيل البيانات. فإذا لم يحدث كما هو متوقع يرجى بحث النقاط التالية - أولاً: التأكد من الاتصال الصحيح بقواعد البيانات أنت تستخدم localhost, 8889 لذلك يرجى التأكد أن فعلًا قواعد البيانات متصلة بهذا الخادم على نفس المنفذ، وسنقوم بعمل تعديل صغير بالشيفرات، لأن السطر الخاص بالاتصال إذا حدث به مشكلة فلن يتم تنفيذ باقي الأسطر <?php $servername = "localhost:8889"; $username = "root"; $password = "root"; $dbname = "student_information2"; try { // نضع الشيفرات داخل كتلة // try-catch $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); } if ($_SERVER["REQUEST_METHOD"] == "POST") { // باقي الأسطر تكتب بشكل طبيعي // ... if (mysqli_query($conn, $sql)) { echo "Data inserted successfully!"; } else { echo "Error inserting data: " . mysqli_error($conn); } } $conn->close(); } catch (Exception $e) { echo "An error occurred: " . $e->getMessage(); } ?> - ثانيًا: التأكد من استخدام أسماء الحقول الصحيحة عند القراءة باستخدام $_post
  10. كنت شوفت تعليقك هذا فى احد المنشورات وحاولت استخدام الطريقة على قدر فهمي ولكني لم استطيع لاني مبتدأ اعتقد ان elevenlabs.io الـ API الخاص بهم ليس مجاني ومحدود جدا صوت مايكروسوفت للعربية المصرية شاكر وسملي اعتقد موجود فى كذا مشروع على github ولكني لا استطيع معرفة مكانة فى المشاريع الموجودة هذا هو البرنامج الذي انشأتة لتوضيح الفكرة كنت اريد اضافة ميزة قراءة الصوتية مثل الموجودة فى متصفح ايدج
  11. أولاً لا يوجد مكتبة في اللغة العربية تدعم بشكل كامل تحويل النص إلى صوت في اللغة العربية (لكي ترتاح من عناء البحث عن مكتبة تقوم بذلك) اذا كان الهدف فقط التجربة تستطيع ذلك. يمكنك الاطلاع على هذا المشروع والاستفادة منه في تحويل النص إلى صوت text_to_speech. ومن الأفضل استخدام تعلم الآلة لفعل ذلك لديك مثلاً elevenlabs.io استخدم الـ API الخاص بهم. بخصوص pyttsx3 تأكد من أنك قمت بتحديد اللغة العربية كلغة النص الذي تريد تحويله إلى صوت باستخدام الأمر التالي: engine = pyttsx3.init() engine.setProperty('rate', 150) # سرعة النطق engine.setProperty('voice', 'com.apple.speech.synthesis.voice.sara') # اسم الصوت العربي وتستطيع استبدال 'com.apple.speech.synthesis.voice.sara' بالصوت العربي المناسب لجهازك. ستجد تفصيل أكثر حول تلك المشكلة هنا بخصوص gtts و pyttsx3 :
  12. قمت بإنشاء محرر لقراء الكتب والروايات وكنت اريد اضافة ميزة جديدة لقراءة الكتاب او الرواية بالتعليق الصوتي كنت اريد ان يتم قرائتها وهي اوفلاين واستخدمت مكتبة pyttsx3 وحاولت فيها كثير لاستخدام اللغة العربية ولكني لما انجح وحاولت استخدام مكتبة gTTS للقراءة المباشرة ولكنها لم تعمل هل هناك حل ؟ لا اعتقد اني استخدمهم بطريقة صحيحة او ان هذة الطريقة الصحيح لاستخدام ميزة القراءة كنت افضل استخدام مكتبة مايكروسوفت المفتوحة للقراءة ولكني لم استطيع ايضا
  13. نتحدث في هذه السلسلة من المقالات عن خطوات بناء تطبيق بسيط يمثل واجهة خلفية على هيئة واجهة برمجية API باستخدام إطار عمل Express.js ولغة TypeScript. كيف أكتب واجهة برمجية REST في بيئة Node.js غالبًا ما تكون المكتبة Express.js هي الخيار اﻷول من بين إطارات عمل Node.js عند كتابة واجهة خلفية لتكون واجهة برمجية REST. وعلى الرغم من أنها تدعم أيضًا بناء صفحات وقوالب HTML، لكننا سنركز على بناء واجهة خلفية باستخدام لغة TypeScript كي تتمكن أي واجهة أمامية أو واجهة خلفية خارجية (خادم آخر) من الاستعلام منها، لهذا عليك أن: تمتلك معرفة أساسية بلغة جافا سكريبت، وكذلك معرفة ببيئة عمل Node.js ومطلعًا على معمارية REST. نسخة مثبّتة وجاهزة من Node.js (يفضل النسخة 14 وما بعد). سنبدأ من الطرفية أو (محرر سطر اﻷوامر) لإنشاء مجلّد خاص بالمشروع، ثم ننفّذ اﻷمر run npm init يُنشئ هذا الأمر بعض الملفات الأساسية التي نحتاجها لمشروع Node.js. ثم نضيف بعد ذلك إطار العمل Express.js وبعض المكتبات المفيدة اﻷخرى لمشروعنا من خلال الأمر التالي: npm i express debug winston express-winston cors وبالطبع هناك أسباب وجيهة كي يفضّل مطوّرو Node.js المكتبات السابقة: debug: وهي وحدة برمجية تُستخدم لتفادي استخدام اﻷمر ()console.log أثناء تطوير التطبيقات. إذ تستخدم لترشيح العبارات التي نريد تنقيحها عند محاولة حل المشاكل التي تواجهنا. وباﻹمكان إيقافها كليًا في نسخة اﻹنتاج بدلًا من إزالتها يدويًا. winston: وستكون المسؤولة عن تسجيل الطلبات القادمة إلى الواجهة البرمجية والاستجابات (واﻷخطاء) التي تعيدها الواجهة. وتتكامل express-winston مباشرة مع Express.js لهذا ستكون شيفرة واجهة برمجية المتعلقة بعملية إدارة السجلات التي تؤديها winston جاهزة. cors: هي جزء من أداة Express.js الوسيطة والتي تسمح لنا بمشاركة الموارد ذات اﻷصول المختلطة cross-origin resource sharing. وبدون هذه المكتبة لن تتمكن الواجهة البرمجية من تخديم سوى الواجهة الأمامية الموجودة في نفس النطاق الفرعي الذي يحوي الواجهة الخلفية. تستخدم الواجهة الخلفية في تطبيقنا تلك الحزم عند يعمل التطبيق، لهذا علينا تثبيت بعض اعتماديات مرحلة التطوير لتهيئة TypeScript. لهذا ننفذ الأمر التالي: npm i --save-dev @types/cors @types/express @types/debug source-map-support tslint typescript نحتاج الاعتماديات السابقة لتفعيل TypeScript في شيفرة تطبيقنا، واﻷنواع التي تستخدمها Express.js والاعتماديات اﻷخرى. وسيوّفر هذا اﻷمر وقتك عند استخدام بيئات تطوير متكاملة مثل WebStorm أو VSCode، إذ تتيح لك ميزات اﻹكمال التلقائي لبعض التوابع أثناء كتابة الشيفرة. ينبغي أن تكون الاعتمادات بشكلها النهائي ضمن الملف package.json كالتالي: "dependencies": { "debug": "^4.2.0", "express": "^4.17.1", "express-winston": "^4.0.5", "winston": "^3.3.3", "cors": "^2.8.5" }, "devDependencies": { "@types/cors": "^2.8.7", "@types/debug": "^4.1.5", "@types/express": "^4.17.2", "source-map-support": "^0.5.16", "tslint": "^6.0.0", "typescript": "^3.7.5" } وهكذا تكون جميع الاعتماديات اللازمة لعمل تطبيقنا جاهزة! هيكيلية مشروع واجهة برمجية REST باستخدام TypeScript سنستخدم في مشروعنا ثلاث ملفات وهي: app.ts/. common/common.routes.config.ts/. users/users.routes.config.ts/. إن الفكرة من استخدام مجلدين (common و users) في مشروعنا هو تكوين وحدتين لكل منهما مسؤولياتها الخاصة. وبالتالي قد نعطي الوحدتين كل أو بعض الميزات التالية: تهيئة الوجهة Rourte: لتعريف الطلبات التي يمكن أن تتعامل معها الواجهة البرمجية. خدمات Services: لتنفيذ مهام مثل الاتصال بقاعدة البيانات وتنفيذ استعلامات أو الاتصال بخدمات خارجية ضرورية للاستعلام. وسيط أو برمجية وسيطة middleware: للتحقق من صلاحية طلب معيّن قبل أن يتعامل المتحكم النهائي بالمسار مع تفاصيل الاستعلام. وحدات Models: لتعريف وحدات البيانات التي تطابق تخطيط قاعدة بيانات محددة، لتسهيل تخزين البيانات واستعادتها. متحكّمات controllers: لفصل معلومات تهيئة المسار أو الوجهة التي سننتقل إليها route configuration عن الشيفرة التي تعالج في النهاية (بعد المرور على أية برامج وسيطة) طلب هذا المسار أو تستدعي دوال خدمة من مستوى أعلى عند الحاجة، وتعيد الاستجابة على هذا الطلب إلى العميل. للمجلد هيكلية ذات تصميم بسيط متوافق مع الواجهة البرمجية. ملفات مسارات Routes شائعة الاستخدام في TypeScript لننشئ الملف common.routes.config.ts في المجلّد common ونضع فيه الشيفرة التالية: import express from 'express'; export class CommonRoutesConfig { app: express.Application; name: string; constructor(app: express.Application, name: string) { this.app = app; this.name = name; } getName() { return this.name; } } إن الطريقة التي ننشئ فيها المسارات routes هنا اختيارية، لكن، وطالما أننا نعمل مع TypeScript، فمن الجيد أن نتدرب على بناء المسارات باستخدام الوراثة من خلال التعليمة extends كما سنرى بعد قليل. وسيكون لجميع الملفات في هذا المشروع السلوك ذاته، كما سيكون لها اسم وإمكانية الوصول إلى كائن Express.js اﻷساسي في تطبيقنا Application. لنبدأ اﻵن ملف الوجهة الخاص بالمستخدمين ضمن المجلد users، لهذا سننشئ الملف users.routes.config.ts: import {CommonRoutesConfig} from '../common/common.routes.config'; import express from 'express'; export class UsersRoutes extends CommonRoutesConfig { constructor(app: express.Application) { super(app, 'UsersRoutes'); } } ندرج هنا الصنف CommonRoutesConfig ونوّسعه إلى صنف جديد ندعوه UsersRoutes. ونرسل من خلال الدالة البانية التطبيق (كائن express.Application الرئيسي) والاسم إلى الدالة البانية للصنف CommonRoutesConfig. قد يبدو المثال بسيطًا لكن عند توسيع الأمر ليشمل عدة ملفات وجهات، وسيساعدنا ذلك في تفادي تكرار الشيفرة. لنفترض أننا سنحتاج إلى إضافة ميزات جديدة في هذا الملف، مثل إدارة السجلات، عندها بإمكاننا إضافة الحقول الضرورية إلى الصنف CommonRoutesConfig وعندها ستتمكن جميع اﻷصناف المشتقة منه من الوصول إلى هذه الميزة. استخدام دوال TypeScript المجرّدة لتقديم وظائف متشابه بين اﻷصناف ماذا لو أردنا الحصول على وظائف متشابهة ضمن اﻷصناف المختلفة (مثل تهيئة نقاط الاتصال بالواجهات البرمجية)، على الرغم من اختلاف طرق تنفيذ هذه الوظائف من صنف ﻵخر؟ أحد الخيارات المتاحة هو استخدام ميزة تُدعى التجريد abstraction في TypeScript. لنحاول إنشاء دالة مجرّدة بسيطة جدًا يرثها الصنف UsersRoutes (وبقية أصناف التوجيه التي قد ننشئها لاحقًا) من الصنف CommonRoutesConfig. ولنفترض أننا سنجبر كل الوجهات على امتلاك دالة (حتى نتمكن من استدعائها من الدالة البانية المشتركة) تُدعى()configureRoutes، وفيها نصرّح عن نقاط الوصول الخاصة بكل مورد من موارد الصنف. ولتنفيذ اﻷمر، سنضيف هذه اﻷشياء إلى الملف common.routes.config.ts: الكلمة المحجوزة abstract إلى السطر الذي يضم الكلمة class كي نفعّل خاصية التجريد لهذا الصنف. تصريح عن دالة جديدة في نهاية الصنف abstract configureRoutes(): express.Application، تجبر أي صنف مشتق من الصنف CommonRoutesConfig على تقديم آلية تطابق توقيع الدالة function signature، وسيرمي مصرّف TypeScript خطأ إن لم يجد آلية كهذه. استدعاء الدالة ()this.configureRoutes في نهاية الدالة البانية طالما أننا متأكدين من وجود هذه الدالة. ستبدو الشيفرة اﻵن كالتالي: import express from 'express'; export abstract class CommonRoutesConfig { app: express.Application; name: string; constructor(app: express.Application, name: string) { this.app = app; this.name = name; this.configureRoutes(); } getName() { return this.name; } abstract configureRoutes(): express.Application; } وهكذا ينبغي على كل صنف مشتق من الصنف CommonRoutesConfig أن يمتلك دالة ()configureRoutes تُدعى تُعيد كائنًا من النوع express.Application، وبالتالي لا بد من تحديث الملف users.routes.config.ts: import {CommonRoutesConfig} from '../common/common.routes.config'; import express from 'express'; export class UsersRoutes extends CommonRoutesConfig { constructor(app: express.Application) { super(app, 'UsersRoutes'); } configureRoutes() { // (we'll add the actual route configuration here next) return this.app; } } دعنا نراجع ما فعلناه حتى الآن: أدرجنا بداية الملف common.routes.config ومن ثم الوحدة البرمجية express، وعرفنا بعد ذلك الصنف UserRoutes الذي أردناه أن يرث الصنف اﻷساسي CommonRoutesConfig وبالتالي سيضمّ الدالة ()configureRoutes ويقدّم آلية لتنفيذها. وﻹرسال المعلومات عبر الصنف CommonRoutesConfig، نستخدم الدالة البانية للصنف التي تتوقع تمرير كائن express.Application إليها، وهذا ما سنشرحه بتفاصيل أكثر لاحقًا. نمرر من خلال الدالة ()super التطبيق إلى الدالة البانية للصنف CommonRoutesConfig واسم الوجهة (وهي في هذه الحالة UsersRoutes). وتستدعي الدالة ()super بدورها الدالة ()configureRoutes. تهيئة وجهات Express.js الخاصة بنقاط الوصول إلى المستخدمين ستكون الدالة المكان الذي ننشئ فيه نقاط الوصول بين المستخدم والواجهة البرمجية REST. وفيها نستخدم التطبيق مع وظائف التوجيه من خلال Express.js. تكمن الفكرة في استخدام الدالة ()app.route لتفادي تكرار الشيفرة، وهذا اﻷمر سهل نسبيًا طالما أننا ننشئ واجهة برمجية REST ذات موارد محددة تمامًا. إن المورد اﻷساسي في تطبيقنا هو users، ولدينا حالتان: عندما يريد مستدعي الواجهة البرمجية إنشاء مستخدم جديد أو الحصول على قائمة بالمستخدمين الموجودين، لا بد أن يكون اسم المورد فقط users في نهاية المسار إلى المورد (لا نريد الخوض في هذه الحالة في فلترة أو تنظيم نتائج الاستعلام أو غيرها من العمليات في هذا التطبيق). عندما يريد المستدعي أن ينفّذ عملية ما على سجل مستخدم، وعندها لابد أن يكون نمط المسار إلى المورد كالتالي: users/:userId. تتيح آلية عمل الدالة ()route. في Express.js التعامل مع طلبات HTTP بأسلوب متسلسل أنيق، لأن جميع التوابع ()get. و ()post. وغيرها، ستعيد نفس النسخة من الكائن التي يعيدها التابع ()route.. لهذا سننهي عملية التهيئة كالتالي: configureRoutes() { this.app.route(`/users`) .get((req: express.Request, res: express.Response) => { res.status(200).send(`List of users`); }) .post((req: express.Request, res: express.Response) => { res.status(200).send(`Post to users`); }); this.app.route(`/users/:userId`) .all((req: express.Request, res: express.Response, next: express.NextFunction) => { // /users/:userId يُنفّذ البرنامج الوسيط هذه الدالة قبل أي استعلام // لكنه لا ينفذ شيئًا اﻵن // next() بل يمرر ببساطة التحكم إلى الدالة التالية في التطبيق تحت next(); }) .get((req: express.Request, res: express.Response) => { res.status(200).send(`GET requested for id ${req.params.userId}`); }) .put((req: express.Request, res: express.Response) => { res.status(200).send(`PUT requested for id ${req.params.userId}`); }) .patch((req: express.Request, res: express.Response) => { res.status(200).send(`PATCH requested for id ${req.params.userId}`); }) .delete((req: express.Request, res: express.Response) => { res.status(200).send(`DELETE requested for id ${req.params.userId}`); }); return this.app; } تتيح الشيفرة السابقة لعميل الواجهة البرمجية المتوافقة مع REST استدعاء نقطة الوصول users باستخدام أحد الاستعلامين POST أو GET، وتتيح له بنفس اﻷسلوب استدعاء نقطة الوصول users/:userId من خلال استعلامات GET أو PUT أو PATCH أو DELETE. كما أضفنا إلى نقطة الوصول users/:userId برنامج وسيط يستخدم الدالة ()all التي تُنفَّذ قبل أي استدعاء للدوال ()get أو ()put أو ()patch أو ()delete. وسيكون لهذه الدالة أهميتها عندما ننشئ لاحقًا مسارات يصل إليها فقط المستخدمين المستوثقين. وقد تلاحظ أن جميع الدوال ()all -وأية أجزاء من البرنامج الوسيط- تمتلك ثلاثة أنواع من الحقول Request و Response و NextFunction: النوع Request هو طريقة Express.js لتقديم طلبات HTTP التي يعالجها. ويُحدّث هذا النوع ويوسّع نوع Node.js اﻷصلي الذي يتعامل مع الطلبات. النوع Response هو طريقة Express.js لتقديم استجابات HTTP التي يعالجها. ويُحدّث هذا النوع ويوسّع نوع Node.js اﻷصلي الذي يتعامل مع الطلبات. كما يستخدم الحقل NextFunction الذي لا يقل أهمية عن الاثنين السابقين كدالة استدعاء تسمح بتمرير التحكم إلى أية دوال أخرى يضمها الوسيط. وتتشارك جميع البرامج الوسيطة نفس كائنات الطلب والاستجابة قبل أن يُرسل المتحكم الاستجابة إلى صاحب الطلب في النهاية. الملف app.ts المدخل إلى Node.js بعد أن وضعنا هيكلية بسيطة للتوجّه في التطبيق، ننتقل إلى تهيئة مدخل entry point إليه، لهذا سننشئ الملف app.ts في المجلد الجذري للمشروع ونبدؤه بالشيفرة التالية: import express from 'express'; import * as http from 'http'; import * as winston from 'winston'; import * as expressWinston from 'express-winston'; import cors from 'cors'; import {CommonRoutesConfig} from './common/common.routes.config'; import {UsersRoutes} from './users/users.routes.config'; import debug from 'debug'; هناك إدراجان فقط جديدان في هذا الملف هما: http: وهو وحدة برمجية أصلية في Node.js، نحتاجها في تشغيل تطبيق Express.js. body-parser: وهو وسيط يأتي مع Express.js، ويفسّر الطلب (صيغة JSON في حالتنا) قبل وصول التحكم إلى معالج الطلب الذي حددناه. ننتقل بعد إدراج الملفات إلى التصريح عن المتغيرات التي نريد استخدامها: const app: express.Application = express(); const server: http.Server = http.createServer(app); const port = 3000; const routes: Array<CommonRoutesConfig> = []; const debugLog: debug.IDebugger = debug('app'); تعيد الدالة ()express كائن تطبيق Express.js اﻷساسي الذي نمرره عبر تطبيقنا، من خلال إضافته بدايةً إلى الكائن http.Server (نحتاج إلى تشغيله بعد تهيئة الكائن express.Application الخاص بتطبيقنا) نترقب اﻵن الطلبات إلى المنفذ 3000 الذي تفهمه TypeScript على أنه من النوع Number بدلًا من المنافذ المعيارية مثل 80 لطلبات HTTP و 443 لطلبات HTTPS التي تُستخدم نمطيًا للاتصال مع الواجهة الأمامية للتطبيق. لماذا المنفذ 3000؟ لا توجد قاعدة تنص على أن المنفذ يجب أن يكون 3000، وسيُختار رقم المنفذ اعتباطيًا إن لم نخصص واحدًا. لكن الرقم 3000 يستخدم بكثرة في أمثلة توثيق Node.js و Express.js لهذا أكملنا على هذا النحو! هل يمكن أن تتشارك Node.js المنفذ مع الواجهه اﻷمامية؟ يمكننا أن نشغّل التطبيق محليًا على منفذ مخصص حتى لو أردنا من الواجهة الخلفية أن تستجيب للطلبات على المنافذ المعيارية. يتطلب اﻷمر خادم وكيل عكسي reverse proxy له نطاق رئيسي أو فرعي يستقبل الطلبات على أحد المنفذين 80 أو 443 ثم يعيد توجيهها إلى المنفذ الداخلي 3000. تتبع المصفوفة routes ملفات التوجيه الخاصة بنا لأغراض التنقيح كما سنرى، ونرى أخيرا كيف ينتهي debugLog بدالة مشابهة للدالة console.log، لكنها أفضل من ناحية إمكانية الضبط الدقيق، إذ تغطي تلقائيًا ما نريد أن ندعو به ملفاتنا أو وحداتنا البرمجية (دعوناه في حالتنا "app" عندما مررناه كنص إلى الدالة البانية ()debug). أصبحنا اﻵن جاهزين لتهيئة جميع وحدات Express.js الوسيطة والوجهات إلى الواجهة البرمجية: // JSON نضيف هنا وسيط لتفسير كل الطلبات القادمة بصيغة app.use(express.json()); // CORS نضيف هنا وسيطًا للسماح بالطلبات مختلطة الأصول app.use(cors()); //expressWinston نحضّر هنا إعدادات الوحدة الوسيطة المخصصة ﻹدارة التسجيل //Exprress.js التي تعالجها HTTP والتي تسجّل جميع طلبات const loggerOptions: expressWinston.LoggerOptions = { transports: [new winston.transports.Console()], format: winston.format.combine( winston.format.json(), winston.format.prettyPrint(), winston.format.colorize({ all: true }) ), }; if (!process.env.DEBUG) { loggerOptions.meta = false; // سجل الطلب على سطر واحد إن لم يكن التنقيح مفعّلًا } // هيئ المسجل بالإعدادات السابقة app.use(expressWinston.logger(loggerOptions)); //Express.js إلى مصفوفتنا بعد إرسال كائن UserRoutes نضيف //كي تضاف الوجهات إلى التطبيق routes.push(new UsersRoutes(app)); // هذه وجهة بسيطة للتأكد أن كل شيء يعمل كما هو مطلوب const runningMessage = `Server running at http://localhost:${port}`; app.get('/', (req: express.Request, res: express.Response) => { res.status(200).send(runningMessage) }); يرتبط expressWinston.logger تلقائيًا بالمكتبة Express.js ويسجل التفاصيل من خلال نفس البنية التحتية التي يستخدمها debug، وذلك لكل طلب مكتمل. وستنسق الخيارات التي مررناها إليه وتلوّن خرج الطرفية التي تعرض السجلات، إضافة إلى عرض سجلات أكثر تفصيلًا (وهو الأمر الافتراضي) عندما نفعّل نمط التنقيح. وتجدر الملاحظة إلى ضرورة تعريف وجهاتنا بعد إعداد expressWinston.logger. وأخيرًا نأتي إلى اﻷمر اﻷكثر أهمية: server.listen(port, () => { routes.forEach((route: CommonRoutesConfig) => { debugLog(`Routes configured for ${route.getName()}`); }); //console.log الحالة الوحيدة التي لن تحاشى فيها استخدام // هو معرّفة متى ينتهي الخادم من عملية اﻹقلاع console.log(runningMessage); }); تشغّل الشيفرة السابقة الخادم فعليًا، وعندما يبدأ تنفيذها يشغّل Node.js توابع الاستدعاء الخاصة بنا والتي تسجّل في وضع التنقيح أسماء كل الوجهات routes التي أعددناها وهي UsersRoutes حتى اللحظة. تنبهنا دوال الاستدعاء بعد ذلك إلى أن الواجه الخلفية جاهزة لاستقبال الطلبات، حتى لو كانت تعمل في وضع الإنتاج. تحديث الملف package.json لنقل شيفرة TypeScript إلى جافا سكريبت وتشغيل التطبيق بعد إنجاز البنية اﻷساسية للتطبيق وتحضيره للتشغيل، نحتاج أولًا إلى بعض اﻹعدادات لتمكين نقل transpilation شيفرة TypeScript: { "compilerOptions": { "target": "es2016", "module": "commonjs", "outDir": "./dist", "strict": true, "esModuleInterop": true, "inlineSourceMap": true } } نضيف أخيرًا بعض اللمسات النهائية على الملف package.json على هيئة سكربتات: "scripts": { "start": "tsc && node --unhandled-rejections=strict ./dist/app.js", "debug": "export DEBUG=* && npm run start", "test": "echo \"Error: no test specified\" && exit 1" }, يعمل السكربت test كملف مؤقت سنستبدله لاحقًا. تنتمي الوحدة tsc في السكربت start إلى TypeScript، وهو المسؤول عن نقل شيفرة TypeScript إلى جافا سكريبت التي ستظهر في المجلد dist. ثم نشغّل النسخة المبنية من التطبيق باستخدام التعليمة node ./dist/app.js. نمرر الوسيط unhandled-rejections=strict-- إلى Node.js (حتى في النسخ 16 وأعلى) لإيقاف التنفيذ عند ظهور خطأ غير محسوب في الشيفرة، ويسهّل ذلك معرفة سبب الخطأ وتصحيحه وهذا اﻷسلوب أوضح من الخيار اﻵخر وهو الاعتماد على كائن السجلات expressWinston.errorLogger الذي يزوّدك بقائمة اﻷخطاء بعد توقف المصرّف. ومعنى ذلك أننا سنترك Node.js يعمل على الرغم من وجود خطأ غير محسوب في الشيفرة وقد يسبب ذلك سلوكًا غير متوقع للخادم وظهور أخطاء أخرى قد تكون أكثر تعقيدًا. يستدعي السكربت debug السكربت start لكنه يعرّف أولًا متغير البيئة DEBUG. ولهذا المتغير تأثير في تمكين جميع عبارات ()debugLog (إضافة إلى تلك التي تقدمها Express.js، والتي تستخدم نفس وحدة التنقيح debug التي نستخدمها) لعرض تفاصيل مفيدة على الطرفية، وإلا ستختفي هذه التفاصيل عند تشغيل الخادم في وضع اﻹنتاج باستخدام التعليمة npm start. جرّب تنفيذ اﻷمر npm run debug. بنفسك، وقارن نتائج الخرج على الطرفية مع تلك التي تنتج عن تنفيذ npm start. تلميح: بإمكانك تحديد خرج التنقيح ليعطي فقط عبارات ()debugLog الموجودة في الملف app.ts، وذلك باستخدام DEBUG=app بدلًا من *\=DEBUG. فالوحدة debug مرنة عمومًا، وهذه الميزة ليست استثناءً. قد يحتاج مستخدمي ويندوز استبدال export بالتعليمة SET لأن export هي الطريقة التي تعمل على لينكس و ماك أو إس. أما إن أردت دعم عدة بيئات تطوير في تطبيقك، جرّب الحزمةcross-env package التي تزوّدك بحلول واضحة لهذه المسألة. اختبار الواجهة الخلفية مع تنفيذ أحد اﻷمرين npm run debug أو npm start ستكون الواجهة الخلفية جاهزة لتلقي الطلبات على المنفذ 3000. يمكننا عندها استخدام أحد المكتبات cURL أو Postman أو Insomnia لاختبار الواجهة الخلفية. وطالما أننا لم ننشئ سوى هيكلية للمورد users، بإمكاننا ببساطة إرسال طلبات دون جسم للطلب لنتأكد أن كل شيئ يجري كما هو متوقع، فمثلًا: curl --request GET 'localhost:3000/users/12345' ستعيد عندها الواجهة الخلفية الاستجابة: GET requested for id 12345. وعند استخدام POST: curl --request POST 'localhost:3000/users' \ --data-raw '' وغيرها من أنواع الطلبات، ستعيد الواجهة الخلفية نفس الاستجابة. الخلاصة بدأنا في هذا المقال في إنشاء واجهة برمجية REST بتهيئة المشروع من الصفر ومن ثم دخلنا في أساسيات إطار العمل Express.js. خطونا بعد ذلك أولى خطواتنا في احتراف TypeScript عن طريق بناء نموذج UsersRoutesConfig يرث CommonRoutesConfig وسنعيد استخدام هذا النموذج في الجزء الثاني من هذه السلسلة. أنهينا العمل بعد ذلك بتهيئة ملف المدخل app.ts لاستخدام الوجهات، ومن ثم تهيئة ملف package.json بالسكربتات اللازمة لبناء وتشغيل التطبيق. وعلى الرغم من استخدام أساسيات الواجهة البرمجية REST مع Express.js و TypeScript في مقالنا، فسوف نركز في المقال التالي على بناء متحكمات مناسبة للموارد والتعرف على نماذج أخرى مثل الخدمات والوحدات الوسيطة والمتحكمات وغيرها من الوحدات البرمجية. ترجمة -وبتصرف- للمقال Building a Node.js TypeScript REST API Part1 Express.js اقرأ أيضًا مدخل إلى Node.js وExpress دليلك لربط واجهة OpenAI API مع Node.js شرح فلسفة RESTful - تعلم كيف تبني واجهات REST البرمجية إنشاء مدوّنة باستخدام Node.js و Express (الجزء الأول)
  14. لا إياك حذف أى كلمة مرور قم فقط بالذهاب وتغيرها لأنه بالفعل الآن يملك جميع كلمات المرور ولن يفيد أى شئ حذفها . قم بالذهاب إلى كل كلمة مرور محفوظة وقم بالذهاب للموقع وتغيرها هذا فقط يكفى مع التأكد من تسجيل الخروج من جميع الأجهزة الأخرى . بالفعل تم سرقة جميع كلمات المرور منه ولكن جوجل الحماية الخاصة بها قوية تكتشف سواء أنت من تحاول الوصول أم لا وبما أنه تم إخبارك بإكتشاف suspetious activity فإذا قد تم تسجيل خروجك من الأجهزة بالفعل ولكن للتاكد قم بتنفيذ الخطوات التى أخبرتك بها سابقا . قم بمحاولة تذكر الأشياء المهمة مثل التى تحمل ايميلات مواقع التواصل مثلا او البريد الإلكترونى فإن كنت قمت بتسجيل دخول yahoo مثلا او microsoft ستجد بالفعل أجهزة قد دخلت على جميع تلك الحسابات فقم بتغيرها فورها وتسجيل الخروج من الاجهزة الآخرى . وقم بمتابعة بريدك الإلكترونى إذا اكتشفت محاولة تغير كلمة مرور أى موقع فقم بالذهاب مباشرة لهذا الموقع وتغير كلمة المرور القديمة سريعا
  15. شكرا جزيلا لك انا فعلا كنت حافظ باسووردات في حساب جوجل وبعضها كنت عامل جعلي مسجل دخول دائم. طب لو انا مش هعرف اوصلهم كلهم اعمل ايه؟؟ اللاب حاليا مع واحد بيسطب نسخة ويندوز جديدة فكل الايميلات ده من التلفون وهل ممكن يكون حساب جوجل اتهكر كمان؟ اخش على الباسووردات المحفوظة في حساب جوجل واحذفها؟؟ ولا اعمل ايه؟؟
  16. اعتقد انك بالفعل قد تم تهكير جهازك وسرقة ملفات الإرتباط المتعلقة بجميع حساباتك على الجهاز . أول شئ يجب عليك تحميل برنامج malwarebytes ومن ثم فحص الجهاز باكمله من خلاله وهو افضل برنامج حماية لإكتشاف ملفات ال malware . ثانى شئ اذا لم تقم بعمل نسخه ويندوز بعد فيجب عليك اكتشاف جميع المواقع التى قمت بحفظ تسجيل الدخول الخاص بها سواء كلمة المرور او قمت بإختيار جعلك مسجل دخول دائما . حيث بملفات الإرتباط التى تم سرقتها من جهازك هو الآن يملك صلاحية الوصول لأى موقع قد قمت بحفظ تسجيل الدخول إليه . لذلك أكتشف تلك المواقع وقم بتغير كلمة المرور وتسجيل الخروج من جميع الأجهزة من تلك المواقع. وثم من خلال حساب جوجل قم بالدخول إلى إعدادات الحساب ثم إعدادات الأمان وستجد أنه يخربك بإقتراحات للأمان بعد إكتشاف نشاط مشبوه قم بتنفيذ تلك الإقتراحات وايضا قم بالذهاب إلى جزء الجلسات وأبحث عن أى جلسة ليست لك وقم بحذفها . وأخيرا قم بتحميل نسخة ويندوز جديدة مع التأكد من عمل format للقرص C حتى يتم حذف أى فيروسات متبقية . ونصيحة قم بتحميل برنامج حماية من الفايروسات على جهازك وتاكد من أى برنامج تقوم بتحميله والموقع الذى تقوم بالتحميل منه . حيث إذا لاحظت أن عنوان الموقع تغير ويتم تحويلك إلى العديد من الصفحات فهذا بشكل مؤكد برامج ضارة.
  17. من يومين حملت برنامج من كروم (قعد ينقلني ل ٤ صفحات قبل التحميل)، لما نزل عاللاب وفعلته عشان يبدا يتسطب لقيته فتح ملفات كتير فقمت قافلهم وحاذفه. بعد كده لقيت اللاب بيفتح ويندوز سيستم (لونها اسود وبادءة بكود) كذا مرة. وديت اللاب لحد يحملي نسخة ويندوز جديدة. انا كنت مسجل في اللاب بتلات حسابات، جالي ايميلات عالتليفون ان في suspetious activity فقمت مغير كلمات السر بتوعهم. بس بعد كده لقيت اكونتات الى على التطبيقات التانية (داخل بنفس حساب جوجل الى حملت منه) بعتالى كام ايميل ان في حاجة غريبة (كذا ايميل من لينكد ان مدينى فيه PIN مع انى محاولتش اغير الباسوورد/ ايميل بيقولى ان باسوورد ميكروسوفت اتغير / ميجا بعتتلي ان في suspetious activity)، لما كانت بتجيلي الرسايل كنت بغير الباسوورد بتاع كل برنامج. انا مفروض اعمل ايه دلوقتي؟ وهل كده في مشكلة ولا لا؟؟
  18. قبل البدء بالتفاصيل التقنية، لنتكلم قليلا لماذا ومتى نحتاج إلى اتصالات قاعدة بيانات متعددة في تطبيق Laravel الخاص بنا ؟ - تطبيق مبدأ فصل الاهتمام: فغالباً ما تنتمي البيانات المختلفة إلى مجالات أو خدمات مختلفة. - تحسين الأداء: من خلال توزيع بياناتك عبر قواعد بيانات متعددة، يمكنك تحسين أداء قاعدة البيانات. فعلى سبيل المثال، يقوم البعض باستخدام قاعدة بيانات مخصصة للعمليات الثقيلة للقراءة وأخرى للعمليات الثقيلة للكتابة. - عمليات تكامل الجهات الخارجية: في بعض الأحيان، قد تحتاج إلى الاتصال بقواعد بيانات خارجية أو قديمة لا تتوافق مع مخطط قاعدة البيانات الأساسية. تمكنك الاتصالات المتعددة من العمل مع مصادر البيانات هذه بكفاءة. - في تطبيقات التي تقدم خدمة بالاجار تسمى SAAS وخاصة في حالة تريد فصل بيانات المستخدمين عن بعضهم البعض حيث تكون الواجهة واحدة ولكن بقواعد بيانات مخصصة لكل عميل حيث تسمى هذه الهيكلية بMulti-Tenancy والآن سأقوم بشرح الخطوات لتحقيق ذلك: 1. يجب إعداد قواعد البيانات التي أريد التعامل معها: لإعداد اتصالات قاعدة بيانات متعددة نحتاج لتعريف كل اتصال منها في ملف config/database.php: // config/database.php 'connections' => [ 'mysql' => [ 'driver' => 'mysql', 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '3306'), 'database' => env('DB_DATABASE', 'default'), 'username' => env('DB_USERNAME', 'default'), 'password' => env('DB_PASSWORD', ''), // ... ], 'second_db' => [ 'driver' => 'mysql', 'host' => env('SECOND_DB_HOST', '127.0.0.1'), 'port' => env('SECOND_DB_PORT', '3306'), 'database' => env('SECOND_DB_DATABASE', 'second'), 'username' => env('SECOND_DB_USERNAME', 'second'), 'password' => env('SECOND_DB_PASSWORD', ''), // ... ], // يمكنك الإضافة بقدر ما تشائين من الاتصالات بقواعد البيانات هنا ], في هذا المثال، حددنا اتصالين بقاعدة البيانات: "mysql" (الاتصال الافتراضي) و"second_db". يمكنك إضافة المزيد من الاتصالات كما هو مطلوب، ولكل منها تكوينها الخاص.2. تعيين متغيرات البيئة: للحفاظ على أمان بيانات الوصول لقاعدة البيانات، يجب الالتزام باستخدم ملف .env لتخزينها. لذلك يجب تعيين متغيرات البيئة لكل اتصال قاعدة بيانات قمنا بانشائه كما يلي: DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=your_database DB_USERNAME=your_username DB_PASSWORD=your_password SECOND_DB_CONNECTION=mysql SECOND_DB_HOST=127.0.0.1 SECOND_DB_PORT=3306 SECOND_DB_DATABASE=second_database SECOND_DB_USERNAME=second_username SECOND_DB_PASSWORD=second_password وتأكد من تطابق أسماء متغيرات البيئة مع تلك المعرفة في config/database.php. 3. نقوم بإنشاء النماذج (models): مثلاً هنا سأقوم بإنشاء نموذج لكل قاعدة بيانات: php artisan make:model User -m php artisan make:model Product -m يقوم هذا الأمر بإنشاء ملفات النموذج وملفات الترحيل (migrations) لكل نموذج. 4. تحديد الاتصال في ملفات النموذج التي تم إنشاؤها: // app/Models/User.php protected $connection = 'mysql'; // app/Models/Product.php protected $connection = 'second_db'; 5. تشغيل عمليات الترحيل (migrate) الآن، يمكنك تشغيل عمليات الترحيل لكل اتصال على حدة: php artisan migrate php artisan migrate --database=second_db سيؤدي هذا إلى إنشاء الجداول اللازمة في قواعد البيانات الخاصة بكل منها.الآن أصبح كل نموذج يتعامل مع قاعدة بيانات مختلفة: فمثلاً للتأكد يمكنك الآن الاستعلام عن البيانات من قواعد بيانات متعددة باستخدام نماذج كل قاعدة بيانات. وفيما يلي مثال على كيفية استرداد المستخدمين والمنتجات من قاعدتي البيانات لدينا: use App\Models\User; use App\Models\Product; // Retrieve users from the 'mysql' database $users = User::all(); // Retrieve products from the 'second_db' database $products = Product::all(); وهنا يتولى لارافل مهمة توجيه استعلاماتك إلى قاعدة البيانات الصحيحة بناء على خاصية اتصال النموذج التي قمنا بوضها في كل نموذج.
  19. نعم، في إمكانك توصيل مشروع لارافل بأكثر من قاعدة بيانات بكل سهولة. ساشرح لك الخطوات بالتفصيل: 1. تعديل ملف الإعدادات .env: - أول شئ ستفعله هي إضافة إعدادات الاتصال للقواعد البيانات المختلفة في ملف .env الخاص بمشروعك. مثلاً، لو عندك قاعدتين بيانات، واحدة اسمها db1 والتانية db2، هتضيف إعدادات زي الأتي: DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=main_database DB_USERNAME=root DB_PASSWORD= DB_CONNECTION_SECOND=mysql DB_HOST_SECOND=127.0.0.1 DB_PORT_SECOND=3306 DB_DATABASE_SECOND=second_database DB_USERNAME_SECOND=root DB_PASSWORD_SECOND= 2. تعديل ملف config/database.php: - بعد ما تضيف الإعدادات في .env، الان يجب الذهاب لملف config/database.php عشان تضيف الاتصالات الجديدة تحت الـ connections array: 'mysql' => [ 'driver' => 'mysql', 'url' => env('DATABASE_URL'), 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '3306'), 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'unix_socket' => env('DB_SOCKET', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'prefix_indexes' => true, 'strict' => true, 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), ]) : [], ], 'second' => [ 'driver' => 'mysql', 'url' => env('DATABASE_URL_SECOND'), 'host' => env('DB_HOST_SECOND', '127.0.0.1'), 'port' => env('DB_PORT_SECOND', '3306'), 'database' => env('DB_DATABASE_SECOND', 'forge'), 'username' => env('DB_USERNAME_SECOND', 'forge'), 'password' => env('DB_PASSWORD_SECOND', ''), 'unix_socket' => env('DB_SOCKET_SECOND', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'prefix_indexes' => true, 'strict' => true, 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA_SECOND'), ]) : [], ], 3. استخدام الاتصال بالقاعدة المطلوبة في كودك: يمكنك صنع جدول لقاعدة البيانات عبر Schema بحيث نعرف Schema::connection لقاعدة البيانات الأخرى مثل Schema::connection('second')->create('users_two', function($table) { $table->increments('id'): }); لما تحب تستخدم قاعدة بيانات معينة في أي استعلام بالكود، تقدر تحدد الاتصال عن طريق الاسم اللي حددته. مثلاً، لو عايز تجيب بيانات من القاعدة الثانية: $users = DB::connection('second')->select(...); ايضا يمكنك توجيه Model إلى استخدام قاعدة الاتصال الثاني الخاص بقاعدة البيانات الثانية باستخدام protected $connection = 'second';
  20. نعم ذلك ممكن عن طريق اجراء بعض التعديلات في ملف config/database.php بحيث ان كل نموذج Model من نماذج لارافيل يحتوي على الخاصية connection والتي عادة ما تكون مظبوطة على قاعدة البيانات الافتراضية المضمنة الان ستقوم باضافة تعريف لقاعدة البيانات الموجودة لديك كالتالي 'sqlite2' => [ 'driver' => 'sqlite', 'database' => env('DB_DATABASE', database_path('database.sqlite')), 'prefix' => '', ], sqlite هو اسم قاعدة البيانات يمكنك استبدالها بالاسم الموجود لديك وبالتالي اصبح بامكانك استخدام اسم الاتصال الذي قمت بتعريفه في ملف database.php لتحديد أي قاعدة بيانات تريد التواصل معها كالتالي $users = DB::connection('sqlite2')->select(...); والان سنقوم باسنادها كقيمة ل connection في ملف النموذج المستهدف class User extends Model { protected $connection = 'sqlite2'; } وبالتوفيق لك ...
  21. مرحبا سؤالي هل ممكن اخلي مشروع اللارافل يتصل باكثر من قاعدة بيانات وكيف أحقق هالشي؟؟
  22. الشرح عظيم جدا شكرا لك اخ علي
  23. كمبرمجين، لا بدّ وأننا تعرضنا لهذه المشكلة، ولا مناص منها، فلا داعي للقلق، ففي الأساس الأصل ليس في حفظ الأكواد البرمجية إنما في فهمها والمداومة على العمل، وعندما تتعلم لغة برمجة جديدة مثل Python، خصوصا في البداية فمن البديهي أن تنسى، فالبرمجة تتطلب ممارسة مستمرة وتعرضا دوريا للمفاهيم لترسيخها بشكل جيد في الذاكرة. كنصائح يمكن تقديمها، هو أن لا يكون هدفك الأساسي هو حفظ ما تتعلمه، فالمراجع والتوثيقات ما أنشئت إلا لهذا الأمر، لنرجع إليها في وقت الحاجة، ولا يمكن استظهارها عن ظهر قلب، فالتحديثات التقنية والبرمجية لا حصر لها فكيف يحصي المرء كل شاردة وواردة. ما ساعدني شخصيا على الفهم والترسيخ هو استخدام طريقة التعليم العكسي، أي أن تحاول أن تشرح ما تعلمته لشخص آخر فالتعليم يعزز الفهم ويساعد في ترسيخ المعلومات في الذهن بشكل جيد. يمكنك الاستفادة أكثر من هنا ومن الإجابات على هذا السؤال:
  24. تحياتي , شكرا لاهتمامك , حسنا اخي الكريم هل امكنك رؤية ملفات المشروع , انا اقوم باعداد الاتصال بين قاعدة البيانات على جهازي والمشروع , لكنني اريد ان اعرف هل هنالك خطأ ما في هيكلة المشروع او عند ارسال البيانات الى قاعدة البيانات, مثلا يوجد لدي صفحة ال register والكود الخاص بها (أعني كود ال php) يوجد في ملف اخر اسمه welcome2.php وعند ارسال البيانات لا تضاف البيانات الى قاعدة البيانات . هل هذا الترتيب خاطئ ام انه يعمل اذا كان الاتصال بقاعدة البيانات صحيح. سؤالي هنا اخي الكريم بحكم خبرتك , هل المشروع كامل منطقيا ويجب علينا فقط التاكيد على الربط الصحيح بين المشروع وقاعدة البيانات , ام هنالك امر ما خاطئ او ناقص يحب علينا مراعاته , انا اعمل الى الان على الربط بين القاعدة والمشروع . وشكرا مرة اخرى على وقتك.
  25. الخدمات المصغرة هي نمط من الهندسة البرمجية يقسم التطبيقات إلى مجموعة صغيرة من الخدمات المستقلة، كل منها تعمل في عملية مستقلة وتتواصل مع بعضها البعض باستخدام واجهات برمجة التطبيقات الخفيفة والموحدة (APIs) بحيث كل خدمة تركز على تنفيذ مهمة محددة وتمتلك قاعدة بياناتها الخاصة بها، مما يتيح لها أن تكون مستقلة في التطوير، النشر، والتشغيل. لا توجد برامج بعينها تقدم هذه الخدمة، لكن توجد برامج وأدوات تدعم التطوير بهذه التقنية ك: Docker: يوفر حاويات خفيفة لتشغيل الخدمات المصغرة بشكل معزول ومستقل. Kubernetes: نظام لأتمتة نشر، توسيع نطاق، وإدارة تطبيقات الحاويات، مثالي لإدارة تطبيقات الخدمات المصغرة على نطاق واسع. Istio: خدمة ليست مفتوحة المصدر توفر طريقة سهلة لإدارة الشبكات المعقدة للخدمات المصغرة مع توفير المصادقة، الرصد، والسياسات المركزية. Spring Boot: إطار عمل شهير لتطوير الخدمات المصغرة باستخدام Java. العديد من الفوائد يمكن استخلاصها من التطوير بالخدمات المصغرة كالتوسع والمرونة حيث يمكن توسيع كل خدمة بشكل مستقل دون الحاجة إلى توسيع التطبيق بأكمله، مما يسهل التعامل مع الأحمال المتزايدة بكفاءة، كما أن كل فريق يمكن أن يعمل على خدمة مختلفة باستخدام الأدوات واللغات التي تناسب تلك الخدمة بشكل أفضل، مما يزيد من سرعة التطوير وجودته، فالخدمات المصغرة حقيقة تسهل عملية الصيانة والتحديثات المستمرة لأن التغييرات في خدمة واحدة لا تؤثر على الخدمات الأخرى وفشل خدمة واحدة لا يؤدي بالضرورة إلى تعطل النظام بأكمله، مما يعزز من استقرار النظام وكنتيجة فنظرا لاستقلالية الخدمات، يمكن نشر كل خدمة بشكل مستقل مما يسهل عمليات التسليم والنشر المستمر (CI/CD). يمكنك الاطلاع أكثر من هنا:
  26. معدل الوصول أو "Rate Limiter" في تطبيقات الويب يستخدم للحد من معدل الطلبات التي يمكن أن يرسلها المستخدم أو النظام خلال فترة زمنية محددة، هذا الأمر يساعد في الحماية ضد الهجمات التي تحاول إغراق النظام بالطلبات (مثل هجمات DDoS) ويضمن توزيع الموارد بشكل عادل بين المستخدمين. ففي الشيفرة المقدمة في الصورة الأولى تظهر تعريف الحد الأقصى العالمي للطلبات حيث لا يمكن لأي مستخدم إرسال أكثر من 1000 طلب في الدقيقة الواحدة. use Illuminate\Support\Facades\RateLimiter; use Illuminate\Http\Request; /** * Bootstrap any application services. */ protected function boot(): void { RateLimiter::for('global', function (Request $request) { return Limit::perMinute(1000); }); } فهذا الجزء RateLimiter::for('global', ...) يعرف حدّا للطلبات ينطبق على جميع المستخدمين بينما هنا function (Request $request) { return Limit::perMinute(1000); } تحدد هذه الوظيفة أنه يمكن إجراء ما يصل إلى 1000 طلب في الدقيقة من أي مستخدم أو IP. في الصورة الثانية، يتم تحديد الحد الأقصى للطلبات على مستوى واجهة برمجة التطبيقات (API)، حيث يتم السماح بـ 60 طلب في الدقيقة الواحدة لكل مستخدم لكنه هنا يعتمد على وجود المستخدم المسجل فذا كان الطلب يأتي من مستخدم مسجل (أي لديه معرف)، فسيستخدم المعرف كمفتاح لمعدل الطلبات؛ وإذا كان الطلب غير مرتبط بمستخدم مسجل، يستخدم عنوان IP للمستخدم كمفتاح. RateLimiter::for('api', ...) يعرف حدا للطلبات خاص بواجهة برمجة التطبيقات. function (Request $request) { ... } تحدد هذه الوظيفة الحد الأقصى للطلبات لكل مستخدم. $request->user()?->id ?: $request->ip() هذا التعبير يقرر مفتاح الحد للطلبات: إذا كان هناك مستخدم مسجل ($request->user()?->id)، يستخدم عرف المستخدم كمفتاح. إذا لم يكن هناك مستخدم مسجل، يستخدم عنوان IP للمستخدم كمفتاح. ?: هو مشغل ثلاثي يعود بالقيمة الأولى إذا كانت غير null، وإلا يعود بالقيمة الثانية.
  1. عرض المزيد
×
×
  • أضف...