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

Sam Ahw

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

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

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

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

    16

إجابات الأسئلة

  1. إجابة Sam Ahw سؤال في عملية الدمج او التكامل او integration في تطبيقات الاندرويد كانت الإجابة المقبولة   
    يمكنك طلب تزويدك بتوثيق لخطوات الدمج من قبلهم، كما أنك لن تحتاج لبناء موقع ويب كامل بخصائص أخرى، يكفي وجود خادم ويب لمعالجة هذه العملية وحفظ البيانات اللازمة لتطبيقك في قاعدة البيانات.
  2. إجابة Sam Ahw سؤال في كيفية انشاء ملف javascript في asp.net كانت الإجابة المقبولة   
    المشكلة إذاً في التعرّف على ClientID، ضع القيمة ClientIDMode = Static ضمن صفحة aspx ثم يمكنك الوصول بشكل مباشر للعنصر بهذا الشكل:
    $("#1stBoxTest")  
  3. إجابة Sam Ahw سؤال في مثال على الجرائم الالكترونية Cyber Crime كانت الإجابة المقبولة   
    تعرف الجريمة الإلكترونية على أنها جريمة يكون فيها الكمبيوتر هدفًا للجريمة أو يُستخدم كأداة لارتكاب جريمة أو للوصول إلى المعلومات الشخصية للمستخدم أو المعلومات التجارية السرية أو المعلومات الحكومية أو لتعطيل جهاز معيّن. يعد بيع المعلومات المذكورة أعلاه أو الحصول عليها عبر الإنترنت جريمة إلكترونية. ولها أيضاً عدة أنواع منها:
    هجمات منع الوصول للخدمة DDOS: تُستخدم هذه لجعل الخدمة عبر الإنترنت غير متاحة وتعطيل الشبكة عن طريق إغراق الموقع بحركة المرور من مجموعة متنوعة من المصادر. Botnets أو شبكات الروبوت: هي شبكات من أجهزة كمبيوتر تم اختراقها يتم التحكم فيها خارجيًا بواسطة متسللين عن بُعد. ثم يرسل المتسللون عن بُعد رسائل غير مرغوب فيها أو يهاجمون أجهزة كمبيوتر أخرى من خلال شبكات الروبوت هذه. يمكن أيضًا استخدام شبكات الروبوت للعمل كبرامج ضارة وأداء المهام الضارة. التصيد أو Phishing: يتضمن هذا النوع من الهجوم قراصنة يرسلون مرفقات بريد إلكتروني ضارة أو عناوين URL إلى المستخدمين للوصول إلى حساباتهم أو أجهزة الكمبيوتر الخاصة بهم. الهندسة الاجتماعية Social Engineering: تتضمن قيام المجرمين بالاتصال المباشر بالشخص المراد اختراقه عادةً عن طريق الهاتف أو البريد الإلكتروني لاكتساب ثقته وعادة ما يقومون بانتحال شخصية وكيل خدمة عملاء وهي بحد ذاتها جريمة أخرى. يمكنك الاطلاع على المزيد من التفاصيل من خلال البحث على الانترنت على مصطلح Cyber Crime أو الجريمة الالكترونية كما يمكنك إيجاد المزيد من التفاصيل هنا:
     
  4. إجابة Sam Ahw سؤال في فهم طريقة العمل أو مبدأ theming system برمجيًا في لارافل كانت الإجابة المقبولة   
    إن مصطلح Theming system هو مصطلح عام، ويجب عليك تحديد ما الذي ترغب بتحقيقه في مشروعك. ولكن بشكل عام يمكن إنشاء قوالب أو themes مختلفة ضمن مشروع لارافل ضمن ثلاثة مستويات: على مستوى التنسيقات CSS، أو على مستوى هرمية الملفات Folder Structure أو ضمن مستوى قاعدة البيانات نفسها.
    بحيث يتم استبدال القطع أو التنسيقات اللازمة لكل ثيم، ويتم اعتماد إحدى هذه المستويات أو جميعها تبعاً لغايتك أثناء بناء المشروع وماهي الخصائص التي ترغب بإجراء التعددية لها.
    فعلى سبيل المثال أبسط المستويات هي من خلال CSS بحيث يتم اعتماد وحذف التنسيقات اللازمة، أما في حال أردت التخصيص أكثر أو تغيير المكونات بشكل كامل سيتم ذلك على مستويات إضافية مثل المتحكّمات وبنية الملفات، بحيث يتم تقسيم بنية الملفات في مشروعك لكل قالب على حدى وإظهار الشيفرات البرمجية حسب القالب المختار:
    بفرض لديك: darkTemplate و lightTemplate من الممكن إنشاء مجلدين منفصلين لكل قالب كالتالي: resources/views/layouts/darkTemplate/master.blade.php resources/views/layouts/lightTemplate/master.blade.php أو إنشاء مجلّد واحد والتبديل بين عناصر المقاطع sections ضمن الصفحات.
    أما من طرف المستخدم، فيجب تخزين القالب المختار بطريقة معيّنة في قاعدة البيانات لديك أو ضمن المتصفح لحفظ هذه الإعدادات للمستخدم وتكرارها في الزيارات المنفصلة.
    لا يوجد قاعدة معيّنة لذلك فيمكنك تضمين هذه الخصائص بما يتناسب مع مشروعك، وفي حال كنت تستخدم blade أو يتم التعامل مع إطار عمل لواجهة المستخدم. ولكن المبدأ نفسه في أي لغة برمجة أو إطار عمل تعمل عليه.
     
  5. إجابة Sam Ahw سؤال في ما هو مفهوم SEMI-JOIN في SQL كانت الإجابة المقبولة   
    يتيح مفهوم semi-join تنفيذ عدّة عمليات أثناء الاستعلام أي في وقت تحضير البيانات ويمكنه تنفيذ عدّة استراتيجيات على البيانات والجداول مثل سحب البيانات المتعددة والمطابقة بين البيانات والتحقق وغيرها..  وبالتالي يحسّن من أداء استخدام الاستعلامات الفرعية من خلال تصفية مجموعة من صفوف البيانات rows بناءً على دمجها مع مجموعة صفوف أخرى.
    أو بمعنى آخر، في حال كنا نقوم بعملية مقارنة inner-join بين جدولين، هنا يعيد الاستعلام جميع البيانات طالما هنالك تقابل بين الجدولين، ولكن في بعض الاستعلامات يلزمنا فقط معرفة في حال كان هنالك تقابل ولا نرغب بمقارنة جميع الأسطر والحصول على عددها، وهنا يمكننا استخدام مفهوم semi-join وهي تعمل بشكل مشابه للاستعلام التالي في MySQL:
    SELECT * FROM A WHERE A.key IN (SELECT B.key FROM B) وبالتالي يمكننا اختصار بعد الاستعلامات الطويلة مثل الاستعلام الذي يعتمد على left outer join:
    SELECT DISTINCT c.id FROM customers c LEFT JOIN salaries s ON s.customer_id = c.id WHERE s.customer_id IS NOT NULL بحيث يصبح بالشكل التالي:
    SELECT c.id FROM customers c WHERE EXISTS (SELECT 1 FROM salaries s WHERE s.customer_id = c.id)  
  6. إجابة Sam Ahw سؤال في الخاصية fetch PDO في PHP كانت الإجابة المقبولة   
    يقوم التابع setFetchMode بضبط وضع جلب البيانات، فيمكنك التحكم بطريقة جلب هذه البيانات لاستخدامها لاحقاً في شيفرتك البرمجية من خلال أنماط عديدة ومنها:
    PDO::FETCH_ASSOC والتي تقوم بجلب البيانات وفهرستها اعتماداً على اسماء الأعمدة في قاعدة البيانات PDO::FETCH_BOTH الافتراضية والتي تقوم بجلب البيانات وفهرستها ضمن مصفوفة من اسماء الأعمدة والقيم. PDO::FETCH_BOUND تعيد القيمة true والتي تقوم باسناد قيم الأعمدة إلى النتيجة النهائية كما يوجد أيضاً FETCH_CLASS , PDO::FETCH_INTO , PDO::FETCH_LAZY وغيرها الكثير. يمكنك الاطلاع عليها من التوثيق الرسمي ل PHP لمعاينة بعض الأمثلة وطرق الاستخدام.
  7. إجابة Sam Ahw سؤال في تخزين مسار الملف مع اللاحقة ضمن node.js كانت الإجابة المقبولة   
    يمكنك تخزين اللاحقة بشكل يدوي في كان كانت ثابتة مع الملفات من خلال الكود التالي:
    var multer = require('multer'); var storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, 'uploadsFolder/') }, filename: function (req, file, cb) { cb(null, Date.now() + '.jpg') //مثال عن إضافة لاحقة } }) var upload = multer({ storage: storage }); أو يمكنك تخزين الصيغة التي تأتي مع الملف من خلال التالي:
    var storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, 'uploadsFolder/') }, filename: function (req, file, cb) { cb(null, Date.now() + path.extname(file.originalname)) //سيتم الحصول على اللاحقة من الملف المحمّل } }) كما ينصح باستخدام mimetype للحصول على كامل الصيغة، مثال:
    filename: function (req, file, cb) { console.log(file.mimetype); // مثال image/jpeg  
  8. إجابة Sam Ahw سؤال في ما الفرق بين app.render و res.render في node.js كانت الإجابة المقبولة   
    إن res.render يعتمد على app.render ضمنياً، فهو ليس شيء منفصل أو جديد. ومن بعض الفروقات الأساسية بينهما:
    تستطيع استدعاء app.render على المستوى الأول (الجذر root) أما res.render حصراً ضمن وسيط أو مسار. يعيد app.render دوماً صفحة html ضمن callback أما res.render يعيد ذلك فقط في حال قمت بوضع callback كمعامل ثالث، أما في حال قمت باستدعاء res.render دون معامل ثالث أو callback، سيتم إرسال صفحة html إلى الزبون تلقائياً مع رسالة بالرمز 200. مثال: //باستخدام app.render app.render('index', {title: 'app.render example'}, function(err, html) { console.log(html) }); //باستخدام res.render بدون المعامل الثالث app.get('/home', function(req, res) { res.render('index', {title: 'res.render example'}) }) //باستخدام res.render مع معامل ثالث app.get('/render', function(req, res) { res.render('index', {title: 'res.render example'}, function(err, html) { console.log(html); res.send('Hello'); }) }) أما من ناحية الاستخدام فعادةً يتم استخدام app.render عند إجراء render للصفحة دون الحاجة لإرسالها إلى المستخدم من خلال http، مثل حالات قوالب البريد الالكتروني مثلاً وغيرها.
  9. إجابة Sam Ahw سؤال في فك ضغط decompress محتوى الطلبات عبر gzip في node.js كانت الإجابة المقبولة   
    يمكنك فك الضغط من خلال http نفسه عن طريق تخزين فك التشفير في buffer وإضافة الرد response إلى gunzip من خلال pipe كالتالي:
    var http = require("http"), zlib = require("zlib"); function getGzipped(url, callback) { var buffer_stream = []; http.get(url, function(res) { var gunzip = zlib.createGunzip(); res.pipe(gunzip); gunzip.on('data', function(data) { // إضافة الجزء الجاهز من فك التشفير إلى buffer buffer.push(data.toString()) }).on("end", function() { //تجميع الأجزاء وإرسال الرد callback(null, buffer.join("")); }).on("error", function(e) { callback(e); }) }).on('error', function(e) { callback(e) }); } getGzipped(url, function(err, result) { console.log(result); }); كما يمكنك تجنّب ذلك من خلال إضافة خيار encoding: null إلى الطلب request وبذلك ستتجنّب تحويل الجزء الذي يتم تحميله من جسم الطلب body إلى النمط string ويبقى بشكل binary buffer
    مثال:
    request = require('request'); zlib = require('zlib'); request(url, {encoding: null}, function(err, response, body){ if(response.headers['content-encoding'] == 'gzip'){ zlib.gunzip(body, function(err, dezipped) { callback(dezipped.toString()); }); } else { callback(body); } });  
  10. إجابة Sam Ahw سؤال في تمييز طلبات AJAX عن الطلبات التقليدية في node.js كانت الإجابة المقبولة   
    إن معظم أطر العمل من طرف المستخدم تقوم بإضافة X-Requested-With إلى ترويسة الطلب Header. وفي إطار العمل express تستطيع التأكد من أن الطلبات قادمة من خلال AJAX باستخدام الخاصية xhr كالتالي:
    app.get('/test', function(req, res) { var isAjax = req.xhr; ... }); أما في أطر العمل التي لا تقوم بإضافة هذه الترويسة مثل Angular، بهنا يحب عليك التأكد من أن الترويسة تستطيع قبول رد من النمط JSON أو XML كالتالي:
    if (req.xhr || req.headers.accept.indexOf('json') > -1) { // نقوم هنا بإرسال الرد XHR } else { // نقوم هنا بإرسال الرد الافتراضي }  
  11. إجابة Sam Ahw سؤال في هل يمكنني الاعتماد على لغة برمجة واحدة فقط؟ كانت الإجابة المقبولة   
    يجب عليك تحديد ماهو المسار الذي ستعمل ضمنه أو ماهي المشاريع التي ستعمل عليها، فلغات وتقنيات تطوير الويب مثلاً تختلف عن تطوير تطبيقات الجوال وهي أيضاً تختلف عن تطوير تطبيقات سطح المكتب وهكذا. وحتى ضمن هذه المسارات يوجد عدّة فروع ولكل منها يتم استخدام تقنية أو لغة برمجة معيّنة لأداء مهام معيّنة. فتعدد لغات البرمجة هو بسبب أن لكل منها إيجابيات وسلبيات فيما يتعلّق ببعض الخصائص، وبالتالي يلجأ المبرمج إلى استخدام لغات البرمجة التي تساعده على إكمال مشروعه.
    في حال كانت لغة البرمجة لديك قادرة على تنفيذ جميع الخصائص التي ستعمل عليها، نعم يمكنك استخدام لغة برمجة واحدة وكثيراً ما نجد شركات تطلب متخصّص في لغة برمجة معيّنة وحتى بمكتبة أو حزمة برمجية معيّنة.
    أما بالنسبة للغة الأكثر طلباً فذلك يعود إلى المسار الوظيفي،  يمكنك البحث على الانترنت مثلاً عن لغات البرمجة الأكثر طلباً في تطوير الويب وستجد مثلاً PHP و python و جافاسكريبت وغيرها..، ولكن لا يمكنك مقارنة لغة أكثر طلباً في تطوير الويب مع لغة أخرى في مجال مختلف تماماً، لأن النتيجة لن تكون دقيقة عندها.
    وفي النهاية لغات البرمجة والتقنيات في تحديث مستمر، ويجب عليك تحديد غايتك من استخدام لغة البرمجة وما نوعية المشاريع التي تفضّل العمل عليها قبل تحديد لغة البرمجة. ثم البقاء على اطلاع على مايجري من تحديثات في اللغة التي تستخدمها وما التقنيات التي يتم استخدامها
  12. إجابة Sam Ahw سؤال في تقسيم الشيفرة البرمجية ومشاركة المتغيّر app في node.js كانت الإجابة المقبولة   
    بما أنك تستخدم إطار العمل express، يمكنك الحصول على محتوى app من خلال req.app التي يتم تضمينها مع كل طلب. بحيث يتم إضافة أي بيانات إضافية من خلال app.set:
    app.set('anykey', {}) والحصول عليها ضمن الكود يكون من خلال المتغير req الذي سيكون موجود مع كل طلب يتم ربطه بالمتحكّم الخاص به بالشكل التالي:
    req.app.get('anykey') كما يمكنك تعديل كود الملف الرئيسي لديك وجعل app متغيّر عام بهذا الشكل:
    var app = module.exports = express(); app.use(app.router); وعندها يمكنك تضمين app في الأجزاء المتفرقة من الكود لديك كالتالي:
    var app = require('../app'); app.get('/', function(req, res, next) { res.render('index'); }); وبشكل مشابه يمكنك بباسطة تمرير المتغيرات إلى المتحكمات لديك بهذا الشكل:
    var controllers = require('./controllers')({app: app}); وإنشاء واجهة عامة للمتحكمات تستقبل هذه المتغيرات:
    // controllers.js module.exports = function(params) { return require('controllers/index')(params); } ثم الوصول إليها يكون بهذا الشكل:
    // controllers/index.js function controllers(params) { var app = params.app; controllers.users = require('./users'); controllers.index = function(req, res) { ... }; } module.exports = controllers; ويمكنك الإطلاع على طريقة مشابهة من خلال استخدام locals في node.js موجودة هنا:
     
  13. إجابة Sam Ahw سؤال في التأكد من أن المستخدم قام بتسجيل الدخول في node.js حزمة passport.js كانت الإجابة المقبولة   
    إذا قام المستخدم بتسجيل الدخول، سيتم إنشاء الغرض user ضمن نسخة الطلب req وإرساله مع كل طلب في express.js والذي يتيح لك التأكد من وجوده أو التحقق من المعلومات الموجودة فيه من خلال أي وسيط:
    if (req.user) { //قام المستخدم بتسجيل الدخول } else { ... } كما يمكنك فصل عملية التحقق إلى وسيط خارجي واستدعائه عند اللزوم بالشكل التالي:
    function isLoggedIn(req, res, next) { if (req.user) { next(); } else { res.redirect('/login'); } } بحيث سيتم إعادة توجيه المستخدم إلى صفحة تسجيل الدخول في حال حاول الوصول إلى أي جزء من الكود البرمجي لديك يحتاج توثيق. ويمكنك استخدام الوسيط السابق بالشكل التالي:
    app.get('/testLogin', isLoggedIn, function(req, res, next) { ... }); بحيث سيتم الدخول إلى الوسيط والتأكد من تسجيل الدخول قبل الوصول إلى هذا الكود
  14. إجابة Sam Ahw سؤال في تضمين ملف نصي في node.js كانت الإجابة المقبولة   
    في حال كان المحتوى بسيط وغير معقّد يمكنك استخدام handler خاص وتضمينه بالشكل التالي:
    var fs = require('fs'); require.extensions['.txt'] = function (module, filename) { module.exports = fs.readFileSync(filename, 'utf8'); }; var test = require("./mytext.txt"); console.log(typeof words); حيث سيتم تخزين المحتوى النصي ضمن المتغيّر test ويمكنك استعماله في أماكن أخرى من الكود البرمجي.
    كما يمكنك استخدام كل من fs.readFile و require.resolve بالشكل التالي:
    var fs = require('fs'); function readModuleFile(path, callback) { try { var filename = require.resolve(path); fs.readFile(filename, 'utf8', callback); } catch (e) { callback(e); } } readModuleFile('./mytext.txt', function (err, result) { console.log(result); }); أو من خلال readFileSync:
    const fs = require('fs') const path = require('path') const mytext = fs.readFileSync(path.resolve(__dirname, 'testfile.txt'), 'utf8') وعموماً أنت لا تقوم بتخزين المحتوى النصي في المتغيّر، بل يتم الإشارة إليه ضمن ذاكرة التخزين العشوائي إلى هذا المتغيّر بشكل مشابه عندما تقوم بعملية نسخ ولصق لمحتوى ما في جهازك.
  15. إجابة Sam Ahw سؤال في إنشاء موقع يدعم لغتين كانت الإجابة المقبولة   
    في حال كان الموقع صغير الحجم والمحتوى بداخله ثابت (ٍStatic) أي لا يتم التواصل مع طرف الخادم لجلب المعلومات، يمكنك استخدام خاصيات الإخفاء والإظهار للنصوص التي تدعمها CSS مع تكرار نفس الصفحة لكل لغة:
    display: block display: none مثال بسيط:
    <html> <head> <style type="text/css"> body.fr > p[lang=en] { display: none; } body.en > p[lang=fr] { display: none; } </style> </head> <body class="en"> <button onclick="document.body.className='en'">English</button> <button onclick="document.body.className='fr'">French</button> <p lang="en">English text here</p> <p lang="fr">French text here</p> </body> </html> ولكن لا أعتقد أنها طريقة عملية خصوصاً في حال وجود كم كبير من النصوص والعناصر. ولا أعتقد أيضاً أنه يوجد أي طريقة عملية بالاعتماد فقط على HTML و CSS. كما أنه لن يتم حفظ اللغة التي سيختارها المستخدم في المتصفح وبالتالي عند أي عملية انتقال من صفحة لأخرى سيتم إعادة تعيين النصوص كما كانت.
    باستخدام الجافاسكريبت ستصبح المهمّة أسهل بكثير، حيث يمكننا تخزين اللغة التي اختارها المستخدم ضمن المتصفح localStorage و sessionStorage وأيضاً ستتيح لنا العديد من الطرق للتغيير بين هذه اللغات، ومن أبسط هذه الطرق هو جمع المحتوى النصي في ملفات JSON وتغيير المحتوى بناءً على اللغة التي تم اختيارها
  16. إجابة Sam Ahw سؤال في استخدام إطار العمل Laravel مع قاعدة بيانات mongodb كانت الإجابة المقبولة   
    نعم لا يوجد أي مشكلة باستخدام قاعدة بيانات mogodb مع laravel، ويمكنك الاطلاع على بعض الأمثلة الموجودة ضمن التوثيق الرسمي ل mongodb عن كيفية استخدامها بالشكل الصحيح مع إطار العمل Laravel.
    ومن ناحية استخدام الاستعلامات لن تجد فرق كبير بما أنك تستخدم Eloquent الموجود في لارافل لأن الحزمة jessegers/mongodb تمكنك من استخدام Eloquent أيضاً، أما من ناحية بعض العمليات مثل reset password وغيرها، فيمكنك أيضاً إجرائها بشكل مماثل على mongodb ولكن يجب عليك التأكد من اسماء الحقول التي ستقوم بتعريفها ضمن schema وأيضاً أنماط هذه البيانات، فهنا يجب عليك التأكد من وضع أنماط صحيحة وإلا ستواجه العديد من المشاكل بسبب مرونة هذا النوع من قواعد البيانات ولن تكتشف الخطأ بسهولة.
    وبما أنك تستخدم الحزمة jessegers/mongodb باستطاعتك استخدام Authenticable base model والذي سيقوم باستبدال Illuminate\Foundation\Auth\User الافتراضي الموجود في لارافيل ليتوافق مع مستند المستخدم الذي ستقوم بتعريفه:
    use Jenssegers\Mongodb\Auth\User as Authenticatable; class User extends Authenticatable { .... } كما يمكنك التحكّم بتغيير اسماء الحقول عن الاسماء الافتراضية في حال احتجت ذلك لإتمام بعض الوظائف، مثلاً ضمن عملية إعادة تعيين كلمة المرور في ملف Auth/ResetsPasswordController.php يمكنك تغيير اسماء الحقول لتتناسب مع الاسماء التي قمت بتعريفها في بنية schema لديك كالتالي:
    protected function credentials(Request $request) { $data = $request->only( 'password', 'password_confirmation', 'token' ); $data['userEmail'] = $request->get('email'); return $data; } ويمكنك إيجاد بعض الأمثلة على الانترنت في حال واجهت أي مشكلة في تطبيق بعض الخصائص
  17. إجابة Sam Ahw سؤال في ما وظيفة الملف ./bin/www في express 4 ضمن node.js كانت الإجابة المقبولة   
    الطريقة الصحيحة لتشغيل المشروع في express 4 في حالتك هي بتنفيذ الأمر التالي بدلاً من node app.js:
    npm start وفي حال كنت ترغب بالاستغناء عن عملية الفصل هذه التي حدثت في النسخة الرابعة والعودة للطريقة المتّبعة في النسخة الثالثة، يمكنك حذف السطر التالي من نهاية الملف الرئيسي لمشروعك app.js:
    module.exports = app; وإضافة الكود التالي:
    app.set('port', process.env.PORT || 3000) app.listen(app.get('port'), () => { console.log(`Server running on: ${app.get('port')}`); }) ثم، يمكنك تعديل ملف التشغيل الموجود ضمن package.json ليصبح كالتالي:
    "scripts": { "start": "node app.js" }  
  18. إجابة Sam Ahw سؤال في إزالة الترويسة X-Powered-By في express ضمن node.js كانت الإجابة المقبولة   
    بالنسبة للنسخ Express 3 وما قبلها يمكنك استخدام:
    app.disable('x-powered-by'); أما في بعض النسخ من Express 4 يجب عليك استخدام التالي:
    app.set('x-powered-by', false) وكما في التعليق السابق يمكنك إجراء ذلك باستخدام وسيط لإزالة هذه الترويسة أو حتى تعديل محتواها:
    app.use(function (req, res, next) { res.removeHeader("X-Powered-By"); //أو res.setHeader( 'X-Powered-By', 'New Content Here' ); next(); });  
  19. إجابة Sam Ahw سؤال في وضع خصائص إضافية في غرض Express Request باستخدام typescript في node.js كانت الإجابة المقبولة   
    في النسخ السابقة يمكنك كما تمت الإشارة في التعليق السابق تعريف متغيّر express عام لأي خصائص إضافية:
    declare global { namespace Express { interface Request { context: Context } } } بحيث يصبح الكود الكامل عندما تريد استخدامه بالشكل التالي:
    import * as express from 'express'; export class Context { constructor(public newVariable) { } log(message: string) { console.log(this.newVariable, { message }); } } declare global { namespace Express { interface Request { context: Context } } } const app = express(); app.use((req, res, next) => { req.context = new Context(req.url); next(); }); app.use((req, res, next) => { req.context.log('returning from the context') res.send('Hi There!'); }); app.listen(5000, () => console.log('Server is listening on port: 5000')) أما في النسخ الحديثة من express 4.17.1 وما فوق  أصبح يجب عليك استخدام وتضمين express-serve-static-core مع المودل بهذا الشكل:
    import {Express} from "express-serve-static-core"; declare module 'express-serve-static-core' { interface Request { newProperty?: string } interface Response { anotherProperty?: string }  
  20. إجابة Sam Ahw سؤال في استدعاء توابع بايثون من خلال node.js كانت الإجابة المقبولة   
    من أسهل الطرق هو استخدام child_process في node.js ثم يمكنك الوصول إلى مسار الكود في بايثون مع إمكانية تمرير المتغيرات بشكل مصفوفة بالشكل التالي:
    const spawn = require("child_process").spawn; const pythonCode = spawn('python',["..../pathhere/script.py", args1, args2, ...]); ثم يجب التأكد من تضمين أو (import sys) ضمن كود بايثون لديك وعندها ستتمكن من الوصول إلى قيم المتغيرات التي تم تمريرها من node.js بالشكل التالي: sys.argv[1] ....إلخ.
    أما لإرسال البيانات مجدداً من بايثون إلى node.js يمكنك إضافة التالي إلى الكود في بايثون:
    print(dataToSendBack) sys.stdout.flush() ثم يمكن لطرف node.js استقبال البيانات بالشكل التالي:
    pythonCode.stdout.on('data', (data) => { .... }); كما يمكنك استخدام الحزمة python-shell ويتم تحميلها بالشكل التالي:
    npm install python-shell ثم يتم استدعاء ملفات بايثون:
    const PythonShell = require('python-shell').PythonShell; PythonShell.run('script.py', null, function (err) { if (err) throw err; console.log('done'); }); ويتم تمرير المتغيرات من خلالها بهذا الشكل:
    var options = { mode: 'text', pythonPath: 'path/here/', pythonOptions: ['-u'], scriptPath: 'path/to/script', args: ['v1', 'v2', 'v3'] }; PythonShell.run('script.py', options, function (err, result) { if (err) throw err; console.log('test results: %j', result); }); كما يوجد بعض الحزم المشتركة مثل حزمة zerorpc التي يمكنك تضمينها في كل من كود الجافاسكريبت في node.js وكود بايثون واستخدامها في كلا الطرفين على منفذ واحد مما قد يسهّل آلية العمل خصوصاً في حال تبادل البيانات بشكل مكرر بين كل من الطرفين، بالشكل التالي:
    ضمن كود الجافاسكريبت:
    //في طرف node.js var zerorpc = require("zerorpc"); var client = new zerorpc.Client(); client.connect("tcp://127.0.0.1:3000"); client.invoke("hello world", "RPC", function(error, res, more) { console.log(res); }); ضمن بايثون:
    import zerorpc class HelloRPC(object): def hello(self, name): return "Hello there: , %s" % name t = zerorpc.Server(HelloRPC()) t.bind("tcp://0.0.0.0:3000") t.run()  
  21. إجابة Sam Ahw سؤال في إظهار صفحة HTML ضمن إطار العمل express.js في node.js كانت الإجابة المقبولة   
    يوجد عدة طرق لإرسال الصفحات من خلال node.js ومنها استخدام محرك القوالب jade من خلال إنشاء الملف index.jade ضمن المجلّد الذي يحوي صفحات الموقع لديك pages وإضافة الكود التالي:
    include plain.html ثم وفي نفس المجلّد نجعل الصفحة plain.html تحوي كود HTML الخاص بهذه الصفحة بهذا الشكل:
    <!DOCTYPE html> ... وأخيراً في كود node.js من طرف الخادم نستطيع تمرير هذه الصفحة بالشكل التالي:
    res.render(index) ومع تحديث نسخة express.js بدءً من النسخة الثالثة، أصبح بإمكانك استخدام المحرّك ejs من خلال تحميل الحزمة التالية:
    npm install ejs --save وتمرير الصفحات بالشكل التالي:
    app.set('views', __dirname + '/pages'); app.engine('html', require('ejs').renderFile); أما في نسخة express 3.4 ومافوق يمكنك استخدام المحرّك ejs يالشكل التالي:
    app.set('view engine', 'ejs'); app.get('/home', function (req, res) { res.render('home.html'); });  
  22. إجابة Sam Ahw سؤال في إعادة التوجيه مع إضافة متغيرات في express.js ضمن node.js كانت الإجابة المقبولة   
    يوجد عدّة طرق لتمرير المتغيرات عبر مسارات التوجيه في node.js والأفضل بينها هو عن طريق query string أي في المسار مباشرةً من خلال إضافة العلامة ? إلى المسار ووضع اسم المتغيّر وقيمته.
    ولكن عندها يجب عليك التأكد من أن قيم هذه المتغيرات سيتم ترميزها وفك ترميزها بالشكل الصحيح ( encodeURIComponent ) لأنه لا يمكنك كتابة أي نص ترغب به وتقوم بإضافته بشكل مباشر إلى الرابط.
    فيصبح الكود بالشكل التالي:
    app.port('/test', function(req, res) { var string = encodeURIComponent('نضع هنا القيم المراد تمريرها'); res.redirect('/?check=' + string); }); وبعد ذلك، يمكنك الحصول على قيم هذه المتغيرات من خلال التابع req.query بالشكل التالي:
    app.get('/', function(req, res) { var testValues = req.query.check; ..... }); كما يمكنك استخدام الحزمة url الموجودة في node.js لسهولة إنشاء query string في حال كان لديك أكثر من قيمة يجب أن تقوم بتمريرها من خلال التابع url.format بالشكل التالي:
    const url = require('url'); app.post('/test', function(req, res) { res.redirect(url.format({ pathname:"/", query: { "variable1": 1, "variable2": 2, "check":"test value" } })); }); وفي حال كنت تستخدم نسخة من node.js أعلى من النسخة السابعة، يمكنك استخدام الحزمة queryString بهذا الشكل:
    const querystring = require('querystring'); app.post('/test', function(req, res) { const query = querystring.stringify({ "variable1": 1, "variable2": 2, "check":"test value" }); res.redirect('/?' + query); }); كما يوجد طرق أخرى لتحقيق ذلك من خلال استخدام الجلسات sessions أو req.flash ولكن في النسخ الحديثة من إطار عمل express من الممكن أن تحتاج استخدام حزم أخرى إضافية لتحقيق ذلك من خلالها.
  23. إجابة Sam Ahw سؤال في مشكلة في الوصول لملفات التنسيقات في إطار العمل express.js ضمن node.js كانت الإجابة المقبولة   
    يمكنك تجربة الرابط التالي:
    http://localhost:5000/main.css أما في حال أردت وجود /styles في الرابط، فيجب أن تقوم بتعديل الكود لديك ليصبح بالشكل التالي:
    app.use("/styles", express.static(__dirname + '/styles')); فمع عدم ذكر أي مسار في كود app.use ستتم الاستجابة إلى المسار الرئيسي لمجلّد مشروعك دون أي إضافات.
  24. إجابة Sam Ahw سؤال في التحديث التلقائي لملفات SASS في node.js كانت الإجابة المقبولة   
    لقد تم تعديل الحزمة node-sass إلى node-sass-middleware وأصبح من الممكن استخدامها مباشرةً بالكود لديك كالتالي:
    var fs = require('fs'), path = require('path'), express = require('express'), sassMiddleware = require('node-sass-middleware') var app = module.exports = express(); app.use( sassMiddleware({ src: __dirname + '/sass', dest: __dirname + '/src/css', debug: true, }) ); app.use(express.static(path.join(__dirname, 'public'))); بحيث تضع المسارات حسب وجود ملفات النسيقات في مشروعك بدلاً من sass و src/css.
    مع الانتباه لضرورة تضمين الوسيط قبل إضافة كود express.static حتى يتم التحديث على الملفات قبل إعادتها إلى المتصفح.
  25. إجابة Sam Ahw سؤال في عدم ظهور حجم البيانات في طلبات express ضمن node.js كانت الإجابة المقبولة   
    بالإطلاع على محتوى الرد نجد الخاصية Transfer-Encoding: chunked، وهنا لا يمكن تضمين content-length لأن البيانات يتم تقسيمها إلى جزء أو عدة أجزاء (ما يدعى ب chunks) ضمن محتوى الرد (response body) مع وجود علامات ضمن كل جزء تدل على حجم بيانات هذا الجزء فقط.
    وإن node.js بشكل افتراضي يقوم بإضافة Transfer-Encoding: chunked ضمن ترويسة الطلب، ولكن عند إضافة Content-Length يتم تعطيلها. أما وجود الخاصية Content-Encoding:gzip ضمن الترويسة فتدل على أنه تم تفعيل الوسيط connect.compress والذي يقوم أيضاً بإيقاف Content-Length.
    ولكن بجميع الأحوال السابقة في حال لم تقم بإنشاء محتوى مضغوط بنفسك بشكل يدوي، فإن الترويسة Content-Length التي قمت بإنشائها بشكل يدوي ستكون غير ملائمة للمحتوى الأخير الذي يتم إرسالة من طرف الخادم وبالتالي يجب عليك الاعتماد على الوسيط connect بدلاً من إجرائها بشكل يدوي لتجنب بعض المشاكل. وفي النهاية يجب الأخذ بعين الاعتبار أن البيانات التي يتم إرسالها من الخادم إلى المستخدم النهائي من الممكن أن تخضع للعديد من الإضافات أو التعديلات بحسب الوسطاء التي يتم استخدامها والتي تقوم بدورها بالتعديل مرات عديدة على ترويسة الطلب.
×
×
  • أضف...