لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 10/05/21 في كل الموقع
-
هل يمكنني التحكم في ارتفاع وعرض الصوره عند عرضها في هذه اللغه لان التناسب بين الصوره والنص المكتوب غير موجود بالمره2 نقاط
-
2 نقاط
-
إن متطلبات تشغيل المشروع، تعتمد على إصدار Laravel بالإضافة للمكتبات الخارجية التي قمت بتثبيتها في composer.json متطلبات لارافيل العامة: في مسار PHP في ملف php.ini أزل الفاصلة المنقوطة ; من أمام كل من الميزات التالية لأن لارافل تعتمد عليهم ثم احفظ الملف وأعد تشغيل المخدم. على الأغلب تجد تنصيب PHP في مسار تثبيت المخدم الذي تستعمله أو نفذ سكربت <php phpinfo(); ?> المتطلبات: PHP >= 7.3 BCMath PHP Extension Ctype PHP Extension Fileinfo PHP Extension JSON PHP Extension Mbstring PHP Extension OpenSSL PHP Extension PDO PHP Extension Tokenizer PHP Extension XML PHP Extension بعد إنشائك لمشروع لارافل، احتفظ بالمجلد public بموقعه ضمن public_html ولا تبدله ولا تنقله المهم أن يكون متاح على الشبكة ، إنما باقي المشروع يمكن أن تضعه خارج public_html وتعدل السطرين التاليين في index.php ليدلا على مجلد الجذر للمشروع require __DIR__.'/../bootstrap/autoload.php'; $app = require_once __DIR__.'/../bootstrap/app.php'; إعداد ngnix الموصى به من لارافل: server { listen 80; # منفذ server_name example.com; # دومين root /srv/example.com/public; # مسار المشروع على الاستضافة add_header X-Frame-Options "SAMEORIGIN"; # إعدادات حماية add_header X-Content-Type-Options "nosniff"; index index.php; # الملف الجذر لتصفح المشروع charset utf-8; # ترميز الأحرف ليقبل العربية و غيرها من اللغات location / { try_files $uri $uri/ /index.php?$query_string; # إعادة توجيه الطلبات } location = /favicon.ico { access_log off; log_not_found off; } # أيقونة الموقع location = /robots.txt { access_log off; log_not_found off; } # ملف الفهرسة error_page 404 /index.php; # صفحة غير متوفرة location ~ \.php$ { # إعداد PHP fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; include fastcgi_params; } location ~ /\.(?!well-known).* { deny all; } } لرفع المشروع، ادخل مجلد المشروع ثم حدد جيمع الملفات والمجلدات بدون vendor ثم قم بعمل أرشيف أو ضغطه zip منهم، تحديد بزر الفأرة ثم add to archive ثم علينا رفع هذا الملف للاستضافة. نسجل دخول للوحة التحكم في الاستضافة، ثم نفتح متصفح الملفات ثم نتوجه ل public_html ونرفع الملف المضغوط عليه، ثم نفك الضغط. ننتقل لمسار المشروع ثم نقوم بتثبيت الاعتماديات: composer install --optimize-autoloader --no-dev ^^^^^^^^ لاتثبت اعتماديات المطورين نتأكد من أن المجلد public متاح للقراءة وله صلاحية (يمكن 644 ) مناسبة (755 موصى بها) مثله مثل مجلد التخزين storage و cache. chmod -R o+w storage chmod -R o+w bootstrap/cache وربط التخزين php artisan storage:link ln -s /home/username/laravel-project/storage/app/public/ /home/username/public_html/laravel-project/storage إنشاء قاعدة بيانات فارغة، لأن لارافل تقوم بعملية تهجير وتبني الجداول (طبعا أنت يفترض أن تتبع هذه الطريق) يفضل أن يكون للمستخدم صلاحيات كالة على القاعدة ALL PREVILLAGE ثم يبقى تعديل ملف البيئة env وإدراج معلومات قاعدة البيانات التي أنشأناها مع معلومات المستخدم. APP_URL=http://localhost DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=homestead DB_USERNAME=homestead DB_PASSWORD=secret ونقوم بإلغاء تفعيل app_debug APP_DEBUG=false وباقي الإعدادت APP_NAME=Laravel اي اسم APP_ENV=production APP_KEY= سيتم توليده من خلال أمر لاحق APP_DEBUG=false APP_URL=http://localhost رابط الاستضافة لديك ثم نولد مفتاح: php artisan key:generate نحذف الكاش: php artisan config:cache php artisan route:cache php artisan view:cache ثم نقوم بعمل التهجير php artisan migrate php artisan db:seed في حال بيانات افتراضية الآن الموقع جاهز للعمل، جزء API ليس له متطلبات إضافية في حال اتصالك بقواعد بيانات خارجية تأكد من ضبط driver الخاص بها لكل خدمة laravel/config/database.php ... 'connections' => [ 'sqlite' => [ 'driver' => 'sqlite', 'database' => env('DB_DATABASE', database_path('database.sqlite')), 'prefix' => '', ], 'mysql' => [ 'driver' => 'mysql', 'host' => env('RDS_HOSTNAME', '127.0.0.1'), 'port' => env('RDS_PORT', '3306'), 'database' => env('RDS_DB_NAME', 'forge'), 'username' => env('RDS_USERNAME', 'forge'), 'password' => env('RDS_PASSWORD', ''), 'unix_socket' => env('DB_SOCKET', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'strict' => true, 'engine' => null, ], ... لإضافة تعديلات، نطفي artisan ثم نعيد تشغيله بعد الانتهاء php artisan down إيقاف php artisan up تشغيل في حال قمت بعدد من التعديلات الكثيرة، ولكي لارفع المجلد المضغوط عددة مرات، يمكن رفع المشروع على مستودع مثل github أو gitbucket ثم استنساخ المستودع git clone أول مرة ثم git pull.. بعد كل تحديث تقوم به (git push إلى المستودع) لكي تسحب التحديثات للاستضافة تابع المستجدات على توثيق لارافل.2 نقاط
-
قبل أن نبدأ البرمجة، سنستعرض بعض المبادئ المعتمدة في تطوير الويب من خلال الاطلاع على هذا التطبيق النموذجي عبر الرابط: studies.cs.helsinki.fi/exampleapp. صممت هذه التمارين لتوضيح بعض المفاهيم الأساسية في المنهاج، وليس لتقديم الطريقة التي ينبغي أن تبنى بها تطبيقات الويب. فهي على العكس تمامًا، ستشرح بعض التقنيات القديمة في تطوير الويب والتي يمكن أن تعتبر في أيامنا هذه عادات برمجية سيئة. مع هذا ستتعلم كتابة الشيفرة بالأسلوب الأنسب في القسم 1. استعمل متصفح Chrome الآن ودائمًا خلال رحلتك في هذا المنهاج. ثم استخدمه في فتح التطبيق النموذجي، قد يستغرق ذلك وقتًا. القاعدة الأولى في تطوير الويب: ابق طرفية التطوير (Development Console) مفتوحةً دومًا في متصفحك. إن كنت تعمل على نظام التشغيل Windows اضغط زر F12 أو أزرار ctrl-shift-i معًا لفتحه. أما في نظام التشغيل MacOS فاضغط زر F12 أو الأزرار Option-cmd-i معًا. قبل المتابعة، اكتشف طريقة فتح طرفية التطوير على حاسوبك، وتذكر أن تبقيها مفتوحةً دومًا عندما تعمل على تطوير تطبيقات الويب. ستظهر طرفية التطوير بالشكل التالي: تأكد أن نافذة (Network) مفتوحة، ثم ألغ تفعيل خيار (Disable Cache). إن حفظ سجل العمل (log) قد يكون مفيدًا، إذ سيحفظ سجلات تنفيذ التطبيق عند إعادة تحميل الصفحة. لاحظ جيدًا: إن أكثر النوافذ أهميةً في الطرفية هي (Network)، و سنستخدمها بكثرة في البداية. الطلبية من النوع HTTP GET يتواصل الخادم (Server) مع المتصفح باستخدام بروتوكول HTTP، وتعرض نافذة (Network) تفاصيل هذا التواصل. فعندما نطلب إعادة تحميل الصفحة ( الزر F5 أو الرمز ↺ على المتصفح)، ستُظهر الطرفية أن حدثين قد وقعا: جلب المتصفح محتوى صفحة التطبيق من الخادم. نزّل المتصفح الصورة Kuva.png. ] عليك تكبير شاشة الطرفية لترى ذلك إن كانت شاشة العرض صغيرة. ستظهر لك معلومات أكثر عند النقر على الحدث الأول: يظهر القسم العلوي (General)، أن المتصفح قدم طلبًا إلى العنوان: https://fullstack-exampleapp.herokuapp.com مستخدما أسلوب GET، وأن الطلب كان ناجحًا لأن الخادم استجاب معيدًا رمز حالة (Status Code) قيمته 200. توجد العديد من الترويسات (Headers) للطلب والاستجابة، يُظهر الشكل التالي بعضها: تعطينا ترويسات الاستجابة (Response headers) معلومات عدة، مثل حجم الاستجابة مقدرة بالبايت والوقت الدقيق لها. كذلك الأمر تخبرنا ترويسة نوع المحتوى (Content_Type) أن الاستجابة كانت على شكل ملف نصي بصيغة utf-8، وتحدد المحتوى الذي سيظهر بتنسيق HTML. وبهذا يعلم المتصفح أن الاستجابة ستكون على شكل صفحة HTML قياسية، ليعرضها كصفحة ويب. تُظهر نافذة (Response) بيانات الاستجابة على شكل صفحة HTML. حيث يحدد القسم Body هيكل الصفحة التي ستُعرض على الشاشة. وتحوي صفحة HTML أيضًا العنصر Div الذي يضم عناصر أخرى مثل معرّف العنوان h1 والرابط a إلى صفحة الملاحظات ومعّرف الصورimg وأخيرًا معرّف الفقرة p الذي يُظهر في مثالنا عدد الملاحظات التي تم إنشاؤها. ونظرًا لوجود معرّف الصور img، أرسل المتصفح طلب HTTP جديد إلى الخادم لإحضار الصورة التي عنوانها kuva.png. يُظهر الشكل التالي تفاصيل الطلب: أُرسل طلب HTTP-GET إلى العنوان: https://fullstack-exampleapp.herokuapp.com/kuva.png وتخبرنا ترويسات الاستجابة أن حجم الاستجابة يعادل 89350 بايت، ومحتواها صورة بصيغة png. يستخدم المتصفح هذه المعلومات لإظهار الصورة بشكل صحيح على الشاشة. يمثل المخطط التتابعي التالي، سلسلة الأحداث التي بدأت بفتح الصفحة https://fullstack-exampleapp.herokuapp.com: أرسل المتصفح في البداية، طلبًا إلى الخادم من نوع HTTP-GET للحصول على شيفرة HTML للصفحة. يخبر معرّف الصور img الموجود في شيفرة HTML المتصفح أن يحضر صورة بعنوان kuva.png. ثم يعالج المتصفح شيفرة HTML والصورة ويظهرهما على الشاشة. مع ذلك يصعب ملاحظة أن معالجة صفحة HTML بدأت قبل أن يحضر المتصفح الصورة من الخادم. تطبيقات الويب التقليدية يماثل عمل صفحة التطبيق النموذجي السابق عمل تطبيقات الويب التقليدية. فعند الدخول إلى الصفحة، يحضر المتصفح من الخادم ملف HTML الذي يُنسِّق طريقة عرض الصفحة ومحتواها النصي. لقد بنى الخادم هذا المستند بطريقة ما. فقد يكون المستند عبارة عن مستند نصي ذي محتوًى ثابت محفوظ على الخادم. كما يمكن للخادم أيضًا أن يبني مستند HTML ديناميكيًا وفقًا للتعليمات الموجودة في شيفرة التطبيق مستخدمًا على سبيل المثال، بيانات موجودة في قاعدة بيانات محددة. فشيفرة ملف HTML في التطبيق النموذجي السابق مثلًا، كُتبت ديناميكيًا من قبل الخادم، كونه احتوى معلومات تدل على عدد الملاحظات التي دونت في الصفحة. تظهر شيفرة HTML لصفحة التطبيق النموذجي بالشكل التالي: const getFrontPageHtml = (noteCount) => { return(` <!DOCTYPE html> <html> <head> </head> <body> <div class='container'> <h1>Full stack example app</h1> <p>number of notes created ${noteCount}</p> <a href='/notes'>notes</a> <img src='kuva.png' width='200' /> </div> </body> </html> `) } app.get('/', (req, res) => { const page = getFrontPageHtml(notes.length) res.send(page) }) بالطبع ليس عليك استيعاب الشيفرة المكتوبة حاليًا. يُحفظ محتوى صفحة HTML على شكل قالب نصي (Template String) أو على شكل سلسلة نصية تسمح على سبيل المثال، بتحديد قيمة المتغيرات الموجودة ضمنها. فالقسم الديناميكي (القابل للتغيير) في صفحة التطبيق النموذجي السابق هو القسم الذي يشير إلى عدد الملاحظات المدونة و يدعى notecount. يُستبدَل هذا القسم بالعدد الفعلي للملاحظات notes.length ضمن القالب النصي للصفحة. لاحظ أن وجود شيفرة HTML ضمن الشيفرة السابقة هو أمر غير مُحبَّذ، لكن مبرمجي مدرسة PHP التقليدية يعتبرون ذلك شيئًا طبيعيًا. يُعتبَر المتصفح في تطبيقات الويب التقليدية "محايدًا". فوظيفته فقط إحضار بيانات HTML من الخادم الذي يقع على عاتقه القيام بكل العمليات المنطقية التي يحتاجها التطبيق. يمكن بناء الخادم باستعمال لغة Java Spring كالخادم الذي استخدم في منهاج Web-palvelinohjelmointi لجامعة هلسنكي، أو استعمال لغة Python Flask كمنهاج tietokantasovellus ، أو باستعمال Ruby and Rails. سيستعمل التطبيق السابق Express من Node.j.s، وسيستخدم هذا المنهاج التقنيتين السابقتين لبناء الخادم. تشغيل التطبيق من المتصفح ابق طرفية التطوير مفتوحةً، واحذف ما فيها بالنقر على ?. عندما تنقر الآن على رابط notes، سيرسل المتصفح أربع طلبات HTTP: لهذه الطلبات أنواع مختلفة. ويمثل النوع (مستند document)، شيفرة HTML للصفحة ويظهر بالشكل التالي: الآن، عندما نقارن الصفحة الظاهرة على المتصفح مع شيفرة HTML التي يعيدها الخادم، سنلاحظ أن الشيفرة لا تحتوي على قائمة الملاحظات. تحتوي ترويسة القسم html من الشيفرة على العنصر script الذي يطلب من المتصفح إحضار ملف JavaScript يدعى main.js. تظهر شيفرة JavaScript كالتالي: var xhttp = new XMLHttpRequest() xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { const data = JSON.parse(this.responseText) console.log(data) var ul = document.createElement('ul') ul.setAttribute('class', 'notes') data.forEach(function(note) { var li = document.createElement('li') ul.appendChild(li) li.appendChild(document.createTextNode(note.content)) }) document.getElementById('notes').appendChild(ul) } } xhttp.open('GET', '/data.json', true) xhttp.send() لا تهمنا حاليًا التفاصيل الواردة في الشيفرة السابقة، لكن جزء منها قد كتب لتجميل مظهر الصور والنصوص (من المرجح أن نبدأ كتابة شيفرات في القسم 1). ونلفت انتباهك أن كتابة الشيفرة السابقة لا تتناسب إطلاقًا وتقنيات كتابة الشيفرات التي ستتعلمها في هذا المنهاج. قد يتساءل البعض عن مغزى استخدام كائن xhttp بدلًا من الأسلوب الحديث لجلب البيانات. إن السبب الرئيسي هو أننا لانريد الآن إظهار ما وعدنا به، و أيضًا للدور الثانوي الذي تلعبه هذه الشيفرة في هذا القسم من المنهاج. لكننا سنطبق في القسم الثاني الطرق الأحدث في إرسال الطلبات إلى الخادم. بعد إحضار ماطلبه عنصرscript مباشرةً، يبدأ المتصفح بتنفيذ الشيفرة. حيث يشير السطرين الأخيرين إلى أن المتصفح سيرسل طلبا من نوع HTTP-GET إلى العنوان التالي data.json/ على الخادم: xhttp.open('GET', '/data.json', true) xhttp.send() سنكون بذلك قد وصلنا إلى آخر طلب سيظهر ضمن النافذة (Network). يمكننا بطبيعة الحال الوصول إلى هذا العنوان مباشرة من نافذة المتصفح كما في الشكل التالي: سنحصل عند فتح العنوان السابق على الملاحظات مكتوبة بصيغة بيانات غير معالجة (raw data) كالتي يستخدمها JSON. لا يمكن للمتصفح في الحالة الطبيعية إظهار هذه البيانات بشكل واضح، لذلك يمكن تثبيب إضافة (Plugin) للتعامل مع هذه الصيغة من البيانات. ثبت على سبيل المثال JSONView على متصفح Chrome ثم أعد تحميل الصفحة. ستظهر البيانات الآن بشكل مفهوم. إذًا، تُحمِّل شيفرة HTML في صفحة الملاحظات Notes بيانات JSON تحتوي على الملاحظات، وترتبها على شكل قائمة نقاط. ويتم ذلك بتنفيذ الشيفرة التالية: const data = JSON.parse(this.responseText) console.log(data) var ul = document.createElement('ul') ul.setAttribute('class', 'notes') data.forEach(function(note) { var li = document.createElement('li') ul.appendChild(li) li.appendChild(document.createTextNode(note.content)) }) document.getElementById('notes').appendChild(ul) تُنشأ الشيفرة بداية قائمة غير مرتبة ul كما يلي: var ul = document.createElement('ul') ul.setAttribute('class', 'notes') ثم تضيف العنصرli (الذي يمثل عنصرًا من قائمة نقاط) لكل ملاحظة، وتضع بداخله محتويات الحقل content فقط من الملاحظة. أما القيم الزمنية الموجودة في الحقل date، فلن تستخدم هنا. data.forEach(function(note) { var li = document.createElement('li') ul.appendChild(li) li.appendChild(document.createTextNode(note.content)) }) افتح الآن النافذة Console ضمن طرفية التطوير كالتالي: سيظهر النص كاملًا عند النقر على المثلث الصغير في بداية السطر: نتج النص السابق عن تعليمة console.log الموجودة في الشيفرة التالية: const data = JSON.parse(this.responseText) console.log(data) وبالتالي ستطبع الشيفرة تلك البيانات في الطرفية بعد استقبالها من الخادم. ستعتاد التعامل مع نافذة Console ومع تعليمة Console.log خلال مسيرتك في هذا المنهاج. معالج الأحداث (Event Handler) و دوال رد النداء (Callback functions) ستبدو لك بنية هذه الشيفرة غريبةً نوعا ما: var xhttp = new XMLHttpRequest() xhttp.onreadystatechange = function() { // الشيفرة التي ستعالج استجابة الخادم } xhttp.open('GET', '/data.json', true) xhttp.send() لقد أُرسِل الطلب إلى الخادم في آخر سطر من الشيفرة، لكن التعليمات التي تعالج الاستجابة أتت في البداية. ما الذي يحدث؟ في هذا السطر: xhttp.onreadystatechange = function () { تم تحديد معالج (handler) للحدث onreadystatechange، الخاص بالكائن xhttp، أثناء إرسال الطلب إلى الخادم. فعندما تتغير حالة هذا الكائن، يستدعي المتصفح الدالة التي تمثل معالج هذا الحدث، ثم تتحق الدالة من أن قيمة الخاصة 'readystate' تساوي 4 (والتي تشير إلى أن العملية قد اكتملت)، وأن قيمة رمز الحالة (status code) لبروتوكول HTTP عند الاستجابة تساوي 200. xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { // الشيفرة التي ستعالج استجابة الخادم } } إن هذا الأسلوب في استدعاء معالجات الأحداث شائع جدًا في لغة JavaScript، وتسمى دالة معالج الأحداث (نداء callback). لا تستدعي شيفرة التطبيق الدوال بنفسها، بل يستدعي المتصفح الذي يعتبر (بيئة التشغيل) في هذه الحالة، الدوال في الوقت المناسب وذلك عندما يقع الحدث. نموذج كائن المستند (Document Object Model DOM) يمكنك التفكير بصفحة HTML على أنها بنًى شجرية متداخلة. html head link script body div h1 div ul li li li form input input يمكن مشاهدة بنًى كهذه ضمن الطرفية /نافذة Elements: تعتمد آلية عمل المتصفح على فكرة تمثيل عناصر HTML على شكل شجرة. وبما أن نموذج كائن المستند DOM هو واجهة تطبيقات برمجية API، قادرة على تعديل العناصر الشجرية لصفحة الويب برمجيًا، فقد استخدمت شيفرة JavaScript التي رأيناها سابقًا الواجهة DOM-API لإضافة لائحة بالملاحظات المدونة في الصفحة. تضيف الشيفرة التالية عقدة جديدة للمتغيِّر ul، ثم تضيف عقدًا ضمنه (عقد أبناء): var ul = document.createElement('ul') data.forEach(function(note) { var li = document.createElement('li') ul.appendChild(li) li.appendChild(document.createTextNode(note.content)) }) وأخيرًا، بعد اكتمال فرع الشجرة الذي يمثله المتحول ul، سنضمه إلى شجرة HTML الممثلة لكامل صفحة الويب في مكانه المناسب. document.getElementById('notes').appendChild(ul) إجراء التعديلات على DOM من الطرفية يمكننا القيام بالعديد من العمليات على صفحة الويب باستخدام واجهة DOM-API. تدعى العقدة الأعلى في شجرة ملف HTML، كائن document. وللوصول إلى كائن مستند صفحة الويب من الطرفية اكتب كلمة document في النافذة Console. لنضف ملاحظة جديدة إلى الصفحة باستخدام الطرفية. دعونا نستعرض أولًا قائمة الملاحظات الموجودة في أول عنصر ul تحتويه الصفحة: list = document.getElementsByTagName('ul')[0] بعد ذلك سننشئ عنصر li جديد ونكتب نصًا ما داخله: newElement = document.createElement('li') newElement.textContent = 'Page manipulation from console is easy' وأخيرًا سنضيف العنصر الجديد إلى القائمة: list.appendChild(newElement) على الرغم من أن محتوى الصفحة قد تغير على متصفحك، إلا أنَّ هذا التغيير مؤقت. فلو حاولت إعادة تحميل الصفحة ستختفي التغيرات التي أجريتها، ذلك أن التغيرات لم ترفع إلى الخادم. إذًا، ستنشئ شيفرة JavaScript التي أحضرها المتصفح، قائمة بالملاحظات الموجودة فقط في العنوان https://fullstack-exampleapp.herokuapp.com/data.json صفحات الأنماط الانسيابية Cascading Style Sheets CSS يحتوي عنصر head في ملف HTML المرتبط بالصفحة Notes، عنصر ارتباط Link، يخبر المتصفح ضرورة إحضار ملف CSS من العنوان main.css. وتعتبر ملفات CSS لغة وصفية (Markup) تستخدم بكثرة في التحكم بمظهر صفحات الويب. يظهر ملف CSS الذي سيحضره المتصفح كالتالي: .container { padding: 10px; border: 1px solid; } .notes { color: blue; } يعرّف الملف محددي صنف (Class Selectors). يستخدم محدد الصنف لاختيار أجزاء من صفحة الويب، يطبق عليها قواعد محددة للتحكم بمظهرها. يبدأ سطر تعريف محدد الصنف بنقطة (.)، يليها اسم لهذا الصنف. وتعتبر هذه الأصناف (خاصيات attributes) يمكن إضافتها إلى عناصر HTML للتحكم بمظهر هذه العناصر. يمكن تفحص خاصيات CSS ضمن نافذة Elements في الطرفية: ] لاحظ أن العنصر div يمتلك الصنف container، بينما يمتلك العنصر ul الصنف notes. وبالعودة إلى ملف CSS، فإن أي عنصر يمتلك الصنف container سيُحاط بمربع مستمر سماكته 1 بكسل وسيُضبط بعد العنصر عن محيطه (padding) بمقدار 10 بكسل، وأي عنصر يمتلك الصنف notes سيكون النص فيه أزرق اللون. يمكن لعناصر HTML امتلاك خاصيات أخرى غير classes. فالعنصر div الذي يحتوي الملاحظات notes، يمتلك خاصية تدعىid. تستخدم JavaScript هذه الخاصية لإيجاد العنصر. يمكن استخدام النافذة Elements في الطرفية لتغيير مظهر العناصر. وكما هي الحال لن تكون التغييرات التي نجريها دائمة. إن أردت تغييرات دائمة، عليك أن تحفظها في مستند CSS الموجود على الخادم. تحميل صفحة تحتوي على شيفرة JavaScript (نظرة ثانية) دعونا نعيد النظر إلى ما يجري عندما نفتح الصفحة https://fullstack-exampleapp.herokuapp.com/notes من خلال المتصفح. يحضر المتصفح شيفرة HTML التي تحدد هيكل ومحتوى الصفحة من الخادم عبر طلب HTTP-GET. تطلب العناصر link في شيفرة HTML من المتصفح إحضار ملف CSS عنوانه main.css وكذلك ملف JavaScript عنوانه main.js من الخادم. ينفذ المتصفح شيفرة JavaScript. ترسل الشيفرة طلب HTTP-GET إلى العنوان https://fullstackexampleapp.herokuapp.com/data.json الذي سيستجيب بإرسال الملاحظات على شكل بيانات JSON. عندما تصل البيانات، سينفذ المتصفح الشيفرة الموجودة ضمن معالج حدث، وهذا الأخير سيظهر الملاحظات على صفحة الويب مستخدمًا الواجهة DOM-API. الاستمارات Forms وطلبات HTTP-POST دعونا نتفحص الآن كيف أُضيفت ملاحظة جديدة. تحتوي الصفحة Notes على عنصر استمارة Form، عندما ننقر على الزر الموجود في الاستمارة، سيرسل المتصفح المعلومات التي أدخلها المستخدم إلى الخادم. لنفتح النافذة Network ولنرى كيف يتم إرسال الاستمارة: نتج عن إرسال الاستمارة خمس طلبات HTTP. يمثل الأول حدث إرسال الاستمارة (Form Submit Event)، وهو طلب HTTP-POST إلى العنوان new_note الموجود على الخادم. سيستجيب الخادم برمز حالة رقمه 302، ويعني هذا أن عملية تحويل عنوان (URL-redirect) قد تمت. في هذه العملية يطلب الخادم من المتصفح إن يرفع طلب HTTP-GET جديد إلى العنوان notes الذي نجده ضمن الموقع Location الذي يمثل جزءًا من ترويسة الاستجابة التي أرسلها الخادم. سيعيد الخادم إذًا، تحميل صفحة الملاحظات. وتسبب تلك العملية ثلاثة طلبات HTTP: إحضار ملف CSS باسم main.css إحضار ملف JavaScript باسم main.js إحضار ملف البيانات data.json يمكن أن نشاهد البيانات التي أرسلت أيضًا في نافذة Network: يمتلك معرّف الاستمارةForm خاصيتي action وmethod اللتان تشيرا إلى أن إرسال الاستمارة سيكون على شكل طلب HTTP-POST إلى العنوان new_notes. تعتبر الشيفرة الموجودة على الخادم والمسؤولة عن الاستجابة إلى طلب المتصفح بسيطة (لاحظ: هذه الشيفرة موجودة على الخادم، وليست جزءًا من ملف JavaScript الذي يحضره المتصفح): app.post('/new_note', (req, res) => { notes.push({ content: req.body.note, date: new Date(), }) return res.redirect('/notes') }) ترسل البيانات ضمن جسم (Body) طلب الإرسال (Post-Request) حيث يتمكن الخادم عندها من الوصول إلى البيانات الموجودة في جسم كائن من النوع Request يدعى req باستعمال الطريقة req.body. ومن ثم ينشأ الخادم كائنًا جديدًا من النوع note، ويضيفه إلى مصفوفة تدعى notes: notes.push({ content: req.body.note, date: new Date(), }) يضم الكائن note حقلين، يدعى الأول content يحوي نص الملاحظة، ويدعى الآخرdate ويحوي معلومات عن تاريخ ووقت إنشاء الملاحظة. طبعًا، لم يحفظ الخادم هذه الملاحظة ضمن قاعدة بيانات، وبالتالي ستختفي الملاحظة الجديدة بانتهاء جلسة العمل. تقنية AJAX اعتمدت صفحة Notes في التطبيق السابق أسلوبًا قديمًا في تطوير الويب، بالإضافة إلى استخدامه تقنية AJAX التي تصدرت قائمة تقنيات الويب بداية العقد الماضي. تأتي التسمية AJAX من (Asynchronous JavaScript and XML). قدم هذا المصطلح في فبراير (شباط) عام 2005، على خلفية التطورات في تقنية المتصفح، لتقدم مقاربةً ثوريةً جديدةً تمكن المتصفح من إحضار محتوى صفحات الويب باستخدام شيفرة JavaScript مدمجة ضمن HTML، دون الحاجة لإعادة تكوين (Rerender) الصفحة من جديد. استخدمت جميع تطبيقات الويب أسلوب التطبيق النموذجي الذي استعرضناه سابقًا قبل ظهور Ajax. فجميع البيانات التي تعرض في الصفحة، يتم إحضارها عند تنفيذ شيفرة HTML التي أنشأها الخادم. استخدمت صفحة Note تقنية AJAX لإحضار البيانات، بينما استخدمت الطريقة التقليدية في إرسال الاستمارة. وتعكس العناوين التي استخدمها التطبيق أسلوب الزمن القديم اللامبالي، حيث أحضرت بيانات JSON من العنوان: https://fullstack-exampleapp.herokuapp.com/data.json وأرسلت الملاحظات الجديدة إلى العنوان: https://fullstack-exampleapp.herokuapp.com/new_note. لاتعتبر هذه العناوين مقبولة حاليًا، كونها لا تتقيد بالتفاهمات العامة التي جرى الاتفاق عليها بخصوص واجهة التطبيقات RESTful التي سنراها في القسم 3. شاع مصطلح AJAX كثيرًا لدرجة أنه اعتبر من المسلمات، ثم تلاشى في عالم النسان ولم يعد يسمع به أحد من الأجيال الجديدة. تطبيق من صفحة واحدة تسلك الصفحة الرئيسية في المثال النموذجي الذي عملنا عليه سلوك صفحة الويب التقليدية. حيث تجري العمليات المنطقية للتطبيق على الخادم، بينما يكّون المتصفح ملف HTML بمقتضى الشيفرة المكتوبة. أما صفحة Notes، فتلقي على المتصفح بعض المسؤولية في توليد شيفرة HTML لعرض الملاحظات الموجودة. إذ ينفذ شيفرة JavaScript التي أحضرها من الخادم، وستحضر هذه الشيفرة بدورها الملاحظات على شكل بيانات JSON، ثم يضيف إليها المتصفح عناصر HTML لعرض الملاحظات على الصفحة مستخدمًا DOM-API. سادت فكرة تصميم تطبيق من صفحة واحدة (Single-page application (SPA، في السنوات الأخيرة. فمواقع الويب التي تستخدم هذا الأسلوب، لاتحضر صفحاتها من الخادم بشكل منفصل كما فعل التطبيق النموذجي السابق، بل تضم جميع الصفحات في صفحة HTML واحدة وتحضرها، ويتم التعامل معها لاحقًا بواسطة شيفرة JavaScript التي تُنفَّذ ضمن المتصفح. تحمل صفحة Notes في تطبيقنا السابق شبهًا بتطبيقات الويب ذات الصفحة الواحدة، لكنها لم تبلغ هذا المستوى بعد. فبالرغم من أن منطق تكوين الملاحظات ينفذه المتصفح، لاتزال الصفحة تستخدم الطريقة التقليدية في إضافة الملاحظات. حيث ترسل الاستمارة البيانات إلى الخادم، الذي يوجه المتصفح لإعادة تحميل الصفحة مع إعادة توجيه نحو عنوان جديد. يحوي العنوان التالي https://fullstack-exampleapp.herokuapp.com/spa نسخة الصفحة الواحدة من تطبيقنا النموذجي. حيث نلاحظ للوهلة الأولى تطابق الطريقتين. فللطريقتين شيفرة HTML نفسها، لكن ملف JavaScript مختلف ويدعى (spa.js)، وكذلك حصل تغيير بسيط في كيفية استخدام معرّف الاستمارة Form، فلا تمتلك الاستمارة الآن خاصيات method و action لتحدد كيف وأين سترسل البيانات المدخلة ضمنها. افتح نافذة Network، وامسح محتواها بالنقر على الرمز ?. ستلاحظ أن طلبًا واحدًا فقط أرسل إلى الخادم عند إنشاء ملاحظة جديدة. يتضمن طلب الإرسال POST إلى العنوان new_note_spa ملاحظة جديدة بصيغة بيانات JSON، تضم محتوى الملاحظة content وتوقيتها date: { content: "single page app does not reload the whole page", date: "2019-05-25T15:15:59.905Z" } يفهم الخادم أن البيانات الواردة إليه مكتوبة بصيغة JSON، عن طريق الخاصية Content-Type من ترويسة الطلب. ومن غير هذه الترويسة، لن يعرف المتصفح كيف يفسر البيانات بشكل صحيح. يستجيب الخادم معلنًا نجاح عملية إنشاء الملاحظة الجديدة معيدًا رمز الحالة 201. لن يطلب من المتصفح هذه المرة إعادة توجيه الصفحة إلى عنوان آخر، بل يبقى المتصفح على نفس الصفحة دون أن يرسل أية طلبات HTTP أخرى. لاترسل نسخة SPA من التطبيق بيانات الاستمارة بالطريقة التقليدية، بل تستخدم شيفرة JavaScript التي تحضرها من الخادم. سنلقي نظرة سريعة على هذه الشيفرة، لكن ليس عليك الآن فهم تفاصيلها. var form = document.getElementById('notes_form') form.onsubmit = function(e) { e.preventDefault() var note = { content: e.target.elements[0].value, date: new Date(), } notes.push(note) e.target.elements[0].value = '' redrawNotes() sendToServer(note) } تطلب التعليمة ('document.getElementById('notes_form إحضار العنصر Form من الصفحة، وربطه بمعالج أحداث ليتعامل مع حدث إرسال الاستمارة. يستدعي معالج الأحداث مباشرة التابع ()e.preventDefault لإيقاف الاستجابة الافتراضية لحدث الإرسال. هذه الاستجابة التي لانريد حصولها، هي من ترسل البيانات إلى الخادم من خلال طلب GET جديد. بعدها ينشأ معالج الأحداث ملاحظة جديدة ويضيفها إلى قائمة الملاحظات باستعمال التعليمة (notes.push(note ثم يعيد تكوين هذه القائمة على الصفحة ويرسل الملاحظة إلى الخادم. تمثل الشيفرة التالية تعليمات إرسال الملاحظة إلى الخادم: var sendToServer = function(note) { var xhttpForPost = new XMLHttpRequest() // ... xhttpForPost.open('POST', '/new_note_spa', true) xhttpForPost.setRequestHeader( 'Content-type', 'application/json' ) xhttpForPost.send(JSON.stringify(note)) } تحدد التعليمات السابقة طريقة إرسال البيانات على شكل طلب HTTP-POST وأنها بصيغة JSON، ومن ثم ترسل البيانات على شكل سلسلة JSON النصية. تتوفر شيفرة التطبيق على العنوان https://github.com/mluukkai/example_app. وعليك أن تتذكر أن التطبيق قد صمم لإبراز مفاهيم المنهاج فقط، وأنه اعتمد أسلوبًا ضعيفًا نسبيًا لايجب عليك اتباعه عند كتابة تطبيقاتك الخاصة. وينطبق كلامنا أيضًا على طريقة استخدام العناوين التي لا تتماشى مع معايير البرمجة الأفضل المعتمدة حاليًا. مكتبات JavaScript صمم التطبيق السابق بما يسمى vanilla Javascript أي باستعمال جافاسكربت فقط، التي تستخدم DOM-API و JavaScript في تغيير بنية الصفحة. وبدلًا من استخدام التقنيتين السابقتين فقط، تستخدم مكتبات مختلفة تحتوي على أدوات يسهل التعامل معها مقارنة بتقنية DOM-API. وتعتبر JQuery أحد أشهر هذه المكتبات.طورت المكتبة JQuery في الوقت الذي استخدمت فيه تطبيقات الويب الأسلوب التقليدي المتمثل بإنشاء الخادم لصفحة HTML، وقد حسَّن ظهورها فعالية المتصفح باستخدام JavaScript المكتوبة اعتمادًا على هذه المكتبة. يعتبر أحد أسباب نجاح JQuery توافقها مع المتصفحات المختلفة (cross-browser). حيث تعمل المكتبة أيًّا كان المتصفح أو الشركة التي أنتجته، وبالتالي انتفت الحاجة إلى حلول خاصة بكل متصفح. لا تُستخدَم JQuery اليوم بالشكل المتوقع، على الرغم من تطور أسلوب Vanilla JS -أي كما ذكرنا الاعتماد على جافاسكربت الصرفة- والدعم الجيد الذي تقدمه أشهر المتصفحات لوظائفها الأساسية. دفع انتشار التطبيق وحيد الصفحة بتقنيات أحدث من jQuery إلى الواجهة، حيث جذبت BackboneJS الموجة الأولى من المطورين. لكن سرعان ما أصبحت AngularJS التي قدمتها غوغل، المعيار الفعلي لتطوير تطبيقات الويب الحديثة، بعد إطلاقها عام 2012. لكن شعبيتها انخفضت بعد أن صرّح فريق العمل في أكتوبر (تشرين الأول) لعام 2014، أن دعم النسخة الأولى سينتهي، وأن النسخة الثانية لن تكون متوافقة معها. لذلك لم تلق Angular بنسختيها ترحيبًا حارًا جدًا. تعتبر حاليًا مكتبة React التي أنتجها Facebook، الأكثر شعبية في مشاركة المتصفح عند تنفيذ منطق تطبيقات الويب. وسنتعلم خلال مسيرتنا في هذا المنهاج التعامل معها وكذلك التعامل مع مكتبة Redux التي سنستخدمها مع React بشكل متكرر. تبدو React حاليًا في موقع قوة، لكن عالم JavaScript دائم التغير. فالقادم الجديد لهذه العائلة VueJS يلقى اهتماما متزايدًا الآن (يمكنك الاطلاع على سلسلة "مقدمة إلى Vue.js" للتعرف على هذه المكتبة الرائعة). التطوير الشامل لتطبيق الويب ما الذي يعنيه مصطلح «التطوير الشامل لتطبيق الويب» (Full stack web development)؟. هذا المصطلح الذي يردده الجميع دون معرفة فعلية بمضمونه أو على الأقل ليس هناك اتفاق على تعريف محدد له. تمتلك جميع تطبيقات الويب من الناحية العملية مستويين: الأول مستوى العمل مع المتصفح وهو الأقرب إلى المستخدم النهائي (End-User) ويعتبر المستوى الأعلى. والثاني هو مستوى الخادم وهو المستوى الأدنى. وتوضع أحيانًا قواعد البيانات في مستوًى أخفض من مستوى الخادم. وبالتالي يمكننا التفكير بهندسة تطبيقات الويب على أنها مستويات متراكمة. يتم الحديث أحيانًا عن واجهة أمامية (frontend) وعن واجهة خلفية (backend). سيمثل المتصفح وشيفرة JavaScript التي ينفذها الواجهة الأمامية، بينما يمثل الخادم الواجهة الخلفية. يُفهم من مصطلح التطوير الشامل في سياق هذا المنهاج، أن العمل سيكون على كل المستويات سواء الواجهة الأمامية أو الخلفية، وكذلك على قواعد البيانات. وقد تعتبر البرمجيات الخاصة بالخادم ونظام تشغيله جزءًا من مستويات التطوير، لكننا لن ندخل في هذا الموضوع. سنكتب شيفرة الواجهة الخلفية بلغة JavaScript مستخدمين بيئة التشغيل Node.js. وسيمنح استخدام نفس لغة البرمجة على مستويات التطوير جميعها بعدًا جديدًا لعملية التطوير الشامل، علمًا أن هذا الأمر ليس ملزمًا. اعتاد المطورون على التخصص بأحد مستويي التطوير، ذلك أن التقنيات المستخدمة في المستويين مختلفة تمامًا. لكن في مضمار التطوير الشامل، لابد من وجود مطورين أكفاء في جميع المستويات بما فيها قواعد البيانات. كما ينبغي على المطورين في بعض الأحيان، امتلاك مهارات في التهيئة والإدارة لتشغيل تطبيقاتهم على منصات مختلفة كالمنصات السحابية (Cloud). جافاسكربت المتعبة يحمل التطوير الشامل للتطبيقات تحديات مختلفة. فأمور كثيرة تحدث معًا في أماكن مختلفة، وتنقيح المشاكل أصعب قليلًا مقارنة بتطبيقات سطح المكتب. فلا تتصرف JavaScript كما هو متوقع منها دائمًا (مقارنة بغيرها من اللغات)، كما أن الطريقة غير المتزامنة التي تعمل بها بيئة التشغيل ستبرز كل أنواع التحديات. المعرفة ببروتوكولHTTP ضروري جدًا لفهم الاتصال في الشبكة، وكذلك معالجة الأمور المتعلقة بقواعد البيانات وإدارة وتهيئة الخادم. لابد أيضا من امتلاك معرفة جيدة بتنسيق CSS لتقديم التطبيق بشكل لائق على الأقل. يتغير عالم JavaScript بسرعة، ولهذا الأمر حصته من التحديات. فكل الأدوات والمكتبات حتى اللغة نفسها عرضة للتطوير المستمر، حتى أن البعض سئم من التغيير المستمر، فأطلق مصطلح جافاسكربت المتعبة (أو Javascript fatigue). ستعاني من هذا التعب أنت أيضًا خلال مسيرتك في المنهاج، ولحسن حظنا، هناك طرق عدة لتسهيل الأمور، منها أننا سنبدأ بكتابة الشيفرة بدلًا من الغوص في عمليات التهيئة، والتي لا يمكننا تفاديها تمامًا، لكن سنحاول أن نتقدم خلال الأسابيع القليلة القادمة متجاوزين الأسوء في هذا الكابوس. التمارين 0.1 - 0.6 ارفع حلول التمارين على منصة GitHub، وينبغي عليك الإشارة إلى إتمام عملية التحميل ضمن منظومة تسليم الملفات submission system. يمكنك تحميل جميع التمارين في نفس المكان، أو استخدم أماكن مختلفة. اعط أسماء مناسبة للمجلدات إن رفعت التمارين التي تعود لأقسام مختلفة من المنهاج إلى نفس المكان، وأضف اسم mluukkai إلى قائمة المتعاونين، إن حمَّلت ملفاتك إلى مجلدات خاصة. تعتبر الطريقة التالية جيدة في تسمية المجلدات: part0 part1 Courseinfo unicafe anecdotes part2 phonebook countries لاحظ أن لكل قسم مجلده الخاص الذي يضم مجلدات فرعية لكل تمرين (مثل تمرين unicafe في القسم1). وانتبه جيدًا لرفع كل التمارين العائدة لقسم محدد معًا، فلو رفعت تمرينًا واحدًا فقط، لن تتمكن من رفع أية تمارين أخرى تعود لنفس القسم. 1- التمرين 0.1 (HTML) راجع أساسيات HTML بقراءة هذه الدورة التعليمية من Mozilla. لاترفع هذا التمرين إلى GitHub، يكفي أن تطلع على الدورة. 2- التمرين 0.2 (CSS) راجع أساسيات CSS بقراءة هذه الدورة التعليمية من Mozilla. لاترفع هذا التمرين إلى GitHub، يكفي أن تطلع على الدورة. 3- التمرين 0.3 (HTML forms) تعلم أساسيات استخدام استمارات HTML بقراءة هذه الدورة التعليمية من Mozilla. لاترفع هذا التمرين إلى GitHub، يكفي أن تطلع على الدورة. 4- التمرين 0.4 (ملاحظة جديدة new note) في فقرة تحميل صفحة تحتوي على شيفرة JavaScript (نظرة ثانية)، عرضت سلسلة الأحداث الناتجة عن فتح هذه الصفحة على شكل مخطط تتابعي أُنجز باستخدام خدمة websequencediagrams كالتالي: browser-`server: HTTP GET https://fullstack-exampleapp.herokuapp.com/notes server--`browser: HTML-code browser-`server: HTTP GET https://fullstack-exampleapp.herokuapp.com/main.css server--`browser: main.css browser-`server: HTTP GET https://fullstack-exampleapp.herokuapp.com/main.js server--`browser: main.js note over browser: browser starts executing js-code that requests JSON data from server end note browser-`server: HTTP GET https://fullstack-exampleapp.herokuapp.com/data.json server--`browser: [{ content: "HTML is easy"، date: "2019-05-23" }، ...] note over browser: browser executes the event handler that renders notes to display end note أنشئ مخططًا مماثلًا لتوضيح الحالة التي ينشأ فيها المستخدم ملاحظة جديدة في الصفحة https://fullstack-exampleapp.herokuapp.com/notes، وذلك بكتابة شيء ما في حقل النص ونقر زر إرسال. يمكنك إظهار العمليات على المخدم أو المتصفح كتعليقات على المخطط، إن وجدت هذا ضروريًا. ولا حاجة أن يكون المخطط تتابعيًّا، فلا بأس بأية طريقة مفهومة لعرض الموضوع. ستجد كل المعلومات المتعلقة بحل هذا التمرين مع التمرينين القادمين في نص هذا القسم. فكرة هذه التمارين قراءة النص مرة أخرى والتفكر مليًا بما يحدث. ليس من الضروري قراءة شيفرة التطبيق على الرغم من أن ذلك ممكن. 5- تمرن 0.5 (تطبيق من صفحة واحدة SPA) أنشئ مخططًا لتوضيح الحالة التي ينتقل فيها المستخدم إلى صفحة نسخة تطبيق من صفحة واحدة من تطبيق الملاحظات على الرابط https://fullstack-exampleapp.herokuapp.com/spa. 6- تمرين 0.6 (ملاحظة جديدة new note) أنشئ مخططًا لتوضيح الحالة التي ينشئ فيها المستخدم ملاحظة جديدة مستخدمًا نسخة التطبيق ذو الصفحة الواحدة. بهذا التمرين نصل إلى نهاية القسم. لقد حان الوقت لترفع إجاباتك على GitHub. لا تنسى أن تشير إلى إتمام عملية التحميل ضمن منظومة تسليم الملفات submission system. يمكنك اقتراح تعديلات على القسم أيضًا إن أحببت في المقال الأصلي. ترجمة -وبتصرف- للفصل Fundamentals of web apps من سلسلة Deep Dive Into Modern Web Development1 نقطة
-
عند محاولة استخدام الlike في مكتبة sequelize ياتيني الخطأ Error: Invalid value { $like: '%' } الكود const posts = await Post.findAll({ where:{ title:{ $like:title_like }1 نقطة
-
عندما نقوم باستخدام مكتبة mat لعرض الرسوم البيانية فإنه يتم عرض الصورة لكن لايمكننا حفظها أو تخزينها ضمن متحول ليتم حفظه فهل هناك طريقة لحفظ الرسم البياني، فعلى سبيل المثال قمت بتحليل للبيانات وأريد حفظ الناتج: import pylab as pt pt.figure(1, figsize=(6, 6)) nationalism = 'European','Asian', 'Indian' ratio = [15, 35, 55] ax = pt.axes([0.1, 0.1, 0.8, 0.8]) pt.pie(ratio, explode=(0, 0.05, 0), labels=nationalism, shadow=True) pt.show()1 نقطة
-
وجدت من أنواع تنظيم هياكل قواعد البينات النظام النجمي Star Schema وأريد أن أعلم مافوائده1 نقطة
-
مع تطور مفاهيم قواعد البيانات أوجد الخبراء أنظمة هيكلية تعطي أداء أفضل من أنظمة أخرى. من أنواع هيكلة قواعد البيانات و العلاقات بين الجداول هو النظام النجمي، حيث يعتمد على وجود جدول وسيط يربط بين الجداول الفرعية الأخرى في قاعدة البيانات، هذا يسرع الوصول لبيانات نحتاجها في جدول آخر حيث يقلل عدد عمليات الربط الضرورية. الجدول الرئيسي يدعى جدول الحقيقة Fact table (يحوي غالباً على إحصائيات) والجداول الفرعية الوصفية Dimension تحوي بيانات عادية مثلاً نصية.. البيانات الواقعية رقمية ( عدد مبيعات المنتج) ، بينما بيانات الأبعاد وصفية (مثل سعر المنتج ولونه ووزنه ...). هيكلية نجمية: لاحظ وجود جدول رئيسي يحوي على المفاتيح الأجنبية (الثانوية) لباقي الجداول، أي سنحتاج لعملية ربط واحدة للوصول لأي جدول آخر وقراءة بياناته. أما في حال اتباع الهيكلية الخطية، سنحتاج لعدد عمليات دمج وبحث أكبر بكثير. هيكلية خطية: مثال: استطعنا ربط جميع الجداول الفرعية مع جدول الحقيقة بعملية واحدة، بدل سلسلة عمليات ربط SELECT P.Brand, S.Country AS Countries, SUM(F.Units_Sold) FROM Fact_Sales F INNER JOIN Dim_Date D ON (F.Date_Id = D.Id) INNER JOIN Dim_Store S ON (F.Store_Id = S.Id) INNER JOIN Dim_Product P ON (F.Product_Id = P.Id) WHERE D.Year = 1997 AND P.Product_Category = 'tv' GROUP BY P.Brand, S.Country1 نقطة
-
1 نقطة
-
بالنسبة للصور، عادة نضبط أحد الأبعاد ونترك البعد الآخر تلقائي لكي لا يتغير تناسب الصورة / نسبة الطول إلى العرض / <img src="https://ik.imagekit.io/ikmedia/backlit.jpg" أي رابط .. style='width: 100%; height: auto;' /> style='width: 250px; height: auto;' /> أو لانعطيه قيمة. بشكل عام لكي تجعل الصور متجاوبة مع حجم الصفحة، يمكننا استخدام واحدة قياس rem وهذه تعتمد على حجم الخط. حيث نعطي html حجم خط ما، ثم العنصر يأخد x rem حيت يتم حساب القيمة كنسبة وتكون متوافقة مع مختلف أحجام الشاشات <img src="https://ik.imagekit.io/ikmedia/backlit.jpg" /> <style> html { font-size: 10px; } img { width: 10rem; } </style> تابع جزء واحدات القياس:1 نقطة
-
في لغة HTML يمكن عرض الصور من خلال العنصر img كالتالي: <img src="https://via.placeholder.com/150" /> وستكون النتيحة كالتالي بالطبع: ويمكن التحكم في طول وعرض الصورة من خلال إضافة الخاصية width أو height، على النحو التالي: <img src="https://via.placeholder.com/150" width="300" height="200" /> وستظهر الصورة بحجم مختلف عن المرة السابقة:1 نقطة
-
كيف يمكننا قراءة فيديو وتشغيله للقيام بعمليات معينة عليه؟1 نقطة
-
لدي قاعدة بيانات وفيها جداول، أحاول إضافة حقل COLUMN جديد على جدول الزبائن يحدد نوع الزبون VIP مثلا (افتراضياً False)1 نقطة
-
يمكنك إضافة عمود لجدول موجود بالفعل من خلال الصيغة التالية: ALTER TABLE table_name ADD column_name BOOLEAN DEFAULT false; قد تختلف الصيغة السابقة وفقًا لنوع وإصدار نظام قاعدة البيانات لديك، ويمكنك تجربة الجمل التالية إن لم تعمل الجملة السابقة: ALTER TABLE table_name ADD column_name BOOLEAN SET DEFAULT false; وإن كنت تستعمل SQL Server، فيمكنك إستخدام الجملة التالية: ALTER TABLE table_name add [column_name] BIT default 'FALSE' NOT NULL; لاحظ أنه تمت إضافة NOT NULL إلى الجملة السابقة لأن النوع BIT يقبل قيمة واحدو من ثلاثة قيم (كمدخل)، وهم True و False و NULL لذلك قمنا بإضافة NOT NULL حتى لا يتم تخزين قيمة فارغة في الحقل ويظهر بدلًا من هذا خطأ عند محاولة ذلك. أيضًا يمكن إستخدام '1' بدلًا من 'TRUE' و "2" بدلًا من "FALSE" في الجملة السابقة وسيعمل كل شيء على ما يرام. يمكنك الإطلاع أكثر حول جملة ALTER من خلال موسوعة حسوب من هنا (تعديل الجدول ALTER TABLE - موسوعة حسوب).1 نقطة
-
هل يمكن كتابة عبارة SQL تقوم بإضافة بيانات لجدول ما أو تعديلها، حيث أن البيانات هذه ناتجة عن عمل استعلام فرعي من جدول آخر؟1 نقطة
-
لإضافة بيانات لجدول ما، يمكن استخدام عبارة INSERT INTO ونمرر لها القيم VALUES على شكل استعلام SELECT: INSERT INTO TopStudents SELECT * FROM Students WHERE marks > 90; مثلا لدينا جدول TopStudents يحوي الطلاب المتفوقين في مادة ما، نريد ملأه بقيم الطلاب الذين حصلو على علامة أكبر من 90. عبارة SELECT سوف تعيد حميع القيم الموافقة للشرط (بيانات الطلاب) وتمررهم لعبارة INSERT ليتم إضافتهم. والشكل العام للعبارة: INSERT INTO tableB SELECT * FROM tableA WHERE condition; يمكن أن يكون الاستعلام SELECT معقداً أكثر ولكن انتبه لتوافق الحقول بين ناتج الاستعلام و بنية الجدول لتحديد الحقول التي تريد إضافتها مرر أسماء الأعمدة: INSERT INTO tableB (col1, col2, col3, ...) SELECT col1, col2, col3, ... FROM tableA WHERE condition; والتعديل من SubQuery: نستخدم الكلمة المفتاحية UPDATE SET ..هنا استخدمنا شرط لمعالجة ناتج الاستعلام UPDATE customers SET vip = IF (SELECT sum(Amount) FROM payment WHERE customers.CustomerID = payment.CustomerID) > 5000 THEN True ELSE False; لاحظ أن الحقل VIP سيتم تحديد قيمته إن كان مجموع مشتريات الزبون أكبر من 50001 نقطة
-
1-هل اذا كنت متعلم فيزياء بشكل عادي هل تفيدني ب البرمجه ؟ 2-هل الفيزياء لها اقسام او قوانين خاصه بالبرمجه ؟ 3-هل الفيزياء تفيدني ك مطور مواقع ؟ 4-هل الفيزياء تفيدني في حل مشكلات البرمجيه؟ فقط و شكراً لكم ..!1 نقطة
-
السلام عليكم , ما هي افضل تقنية في الباك اند Back-end هل Laravel او Node.js انا اعشق Node.js لكن الكثير من الناس ينصحونني ب Laravel او .net Framework ما رايكم ؟1 نقطة
-
لا يوجد الأفضل، كل بيئة أو إطار عمل له مزاياه وتطبيقاته التي يتفوق بها، وايضا عند الحاجة يمكن فصل النظام الذي تريد تطويره الى خدمات مترابطة وكل منها تستخدم اطار عمل أو بيئة معينة NodeJS مكتبات عديدة أداء سريع في التطبيقات التي تعتمد على كميات كبيرة من الادخال والاخراج (تطبيقات الوقت الحقيقي - تطبيقات نقل الصوت والفيديو) سهولة بدء التطوير للمبرمج الخبير ب JavaScript، بما انه لديك خبرة في Node JS سيكون العمل أسهل Laravel وقت أقصر لبناء منتج أولي، مكونات ومزايا جاهزة عديدة داخلها تجعل تجربة المطور سهلة الشهرة الواسعة، أغلب المشاكل ستجد لها حلولا لاشخاص واجهوها من قبلك وكيفية حلها أو تضمينها سهولة بدء التطوير للمبرمج الخبير في PHP، يمكن الاستفادة من قراءة المقال التالي1 نقطة
-
أولا التأكد من تنصيب بيئة NodeJS على المخدم بواسطة CPanel يمكنك مراجعة خطوات التنصيب بالإجابة التالية: الآن نحتاج لتنصيب حزمة pm2 فهي process manager ل JavaScript runtime Node.js: npm install -g pm2 ثم في nginx نعطي سماحية للمنفذ الذي يعمل عليه تطبيق NextJS في nginx.conf/server/location أضف السطر proxy_pass http://localhost:6060 ثم نعمل على رفع الملفات الخاصة بالمشروع pages, public, src , package.json إلى مسار ما علة المخدم: /var/www/your-Next-folder ثم نعدل صلاحيات المجلد: ونقوم بتنصيب الحزم sudo chown -R $USER:$USER /var/www/your-Next-folder ثم نقوم بتنصيب الحزم > cd to your-Next-folder > run: npm -i ثم ضمن package.json نعدل أمر تشغيل التطبيق حسب المنفذ المستخدم next start -p your-port next start -p 6060 ثم بناء وتشغيل المشروع: npm run build pm2 start "npm run start" --name Next-project ملاحظة: إن اعترضتك مشكلة في بناء npm build تكون بسبب قلة الذاكرة الافتراضية، لذلك ينصح بعمل البناء محليا على حاسوبك، في حال رفع ملفات ساكنة هنا قد نحتاج لبرنامج يخدم المشروع، تأكد من معمارية المشروع كالتالي: public_html Next_project .next src server.js package.json ... حيث أن شيفرة server.js ستكون بالشكل: const { createServer } = require("http"); const { parse } = require("url"); const next = require("next"); const dev = process.env.NODE_ENV !== "production"; const port = !dev ? process.env.PORT : 3000; // Create the Express-Next App const app = next({ dev }); const handle = app.getRequestHandler(); app .prepare() .then(() => { createServer((req, res) => { const parsedUrl = parse(req.url, true); const { pathname, query } = parsedUrl; handle(req, res, parsedUrl); console.log("pathname", pathname); }).listen(port, (err) => { if (err) throw err; console.log(`> Ready on http://localhost:${port}`); }); }) .catch((ex) => { console.error(ex.stack); process.exit(1); }); الآن التشغيل ك node server.js. npm install cross-env "scripts": { "start": "cross-env NODE_ENV=production node server.js" } كما يمكن تنفيذ أمر next export الذي ينتج ملفات ساكنة يمكن رفعها على المخدم قد تحتاج لملف .htaccess لتوجه الطلبيات نحو مخدمك، سيكون بهذه الطريقة: RewriteEngine On RewriteRule ^$ http://127.0.0.1:3000/ [P,L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ http://127.0.0.1:3000/$1 [P,L] مع تغيير المنفذ للمستخدم لديك في مثالنا 6060. أفضل استضافة هي vercel لسهولة النشر عليها كما يمكن لأداء أفضل استخدام vps1 نقطة
-
هل يمكن شرح الخطوات لرفع مشروع برمجة خلفية Back End لموقع الكتروني مبني بواسطة NodeJS، وكيفية ضبط إعدادات المخدم، وكيف أعرف متطلبات تشغيل المشروع.1 نقطة
-
يجب أولا التأكد من تنصيب بيئة NodeJS على المخدم إذا كنت تستخدم الإستضافة بواسطة CPanel يمكنك مراجعة خطوات التنصيب بالإجابة التالية: إذا كنت تستخدم مخدم خاص ولديك وصول للمستخدم root نفذ الأمر التالي لتنصيب NodeJS sudo apt install nodejs ثم تأكد من التنصيب بنجاح بتنفيذ الأمر التالي يجب أن تظهر نسخة NodeJS في الخرج node –v الان قم بنسخ ملفات مشروعك وتغيير المسار الى مجلد المشروع ونفذ الأوامر التالية لتنصيب الاعتماديات وتشغيل التطبيق كالتالي (بافتراض ملف البداية في مشروعك هو index.js) npm install & node index.js1 نقطة
-
السلام عليكم كنت عايز أبدا في الأمن السيبراني وبحثت كثير علي جوجل كل موقع يعطيني إجابة مختلفة . انا عايز اعرف اساسيات الأمن السيبراني وادخل في المجال وجزاكم الله خيرا1 نقطة
-
يمكننا المرور على جميع الجداول وعمل truncate لهم، افتح محرر الأوامر cmd أو terminal ثم اكتب أمر musql وبعد ظهور المؤشر اكتب السطر التالي: mysql -Nse 'show tables' DATABASE_NAME | while read table; do mysql -e "truncate table $table" DATABASE_NAME; done هذا الأمر سوف يجلب أسماء جميع الجداول في قاعدة بيانات ما، ثم ينفذ أمر truncate الذي يحذف بيانات الجدول دون حذف هيكلية الجدول نفسه. إذا ظهر لك مشاكل (حذف جدول مرتبط بجدول آخر) أو لتجنب حدوث أخطاء بالأساس، نضبط عدم إظهار تحذيرات عند حذف المفاتيح الثانوية Forien kyes SET FOREIGN_KEY_CHECKS=0; ثم أمر الحذف ... ثم نعيد القيد SET FOREIGN_KEY_CHECKS=1; ويمكن تجميع الأوامر السابقة في script وحيد: SET FOREIGN_KEY_CHECKS = 0; SELECT @trunc_str := CONCAT('TRUNCATE TABLE ', table_schema, '.', table_name, ';') FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_schema IN ('db_name1','db_name2'); PREPARE statement FROM @trunc_str; EXECUTE statement; DEALLOCATE PREPARE statement; SET FOREIGN_KEY_CHECKS = 1; وإن أردت استخدام shell script: # اسم قاعدة البيانات DATABASE_NAME=$1 # اسم مستخدم قاعدة البيانات read -p "DB User: " DBUSER # كلمة السسر للمستخدم read -s -p "DB Password: " DBPASSWORD echo "" # طباعة فراغ # حذف بيانات الجداول mysql -Nse 'show tables' -D $DATABASE_NAME -u$DBUSER -p$DBPASSWORD | while read table; do echo "SET FOREIGN_KEY_CHECKS = 0;truncate table \`$table\`; SET FOREIGN_KEY_CHECKS = 1;"; done | mysql $DATABASE_NAME -u$DBUSER -p$DBPASSWORD exit 0 إن كنت تستعمل phpMyAdmin يمكن من واجهة التحكم تفريغ قاعدة البيانات: Database View => Check All (tables) => Empty1 نقطة
-
أريد حذف بيانات جدول في قاعدة البيانات مع الإبقاء على هيكليته، حيث بحثت وظهر لي هذين الأمرين، ما الفرق بينهما وأي عملية أسرع.1 نقطة
-
إن التعليمة drop table تقوم بحذف الجدول وتعريفه نهائيا من القاعدة أي البيانات مع الهيكلية الخاصة به Schema أما Truncate تحذف فقط البيانات، فعليك: تجنب استخدام عبارة DELETE FORM TABLE WHERE 1 لأنها بطيئة استخدام عبارة truncate لحذف محتوى جدول مع الإبقاء عليه TRUNCATE TABLE tbl_name للتخلص من الجدول بشكل نهائي استخدم DROP: DROP TABLE IF EXISTS tbl_name; فائدة العبارة DELETE في حذف سجلات يمكن تحديدها بشرط ما: DELETE FROM People WHERE F_Name = 'wael'1 نقطة
-
إن عملية رفع مشروع React تتضمن فقط عملية نقل الملفات إلى الاستضافة حيث أن المشروع سيكون عبارة عن ملفات ساكنة static files من HTML - CSS - JS والتي - بعد اختبار تطبيق - سوف تقوم ببناء النسخة الإنتاجية منه التي ستقوم برفعها على الانترنت، فإن كنت تستخدم npm مدير الحزم، اكتب الأمر: npm run build حيث سيتم تشكيل مجلد فيه الناتج النهائي من عملية ضفط وربط ملفات مشروعك وهذا المجلد سيكون الجذر لملفات الموقع "الواجهات الأمامية" يمكن رفع تطبيقات ريأكت React على أي استضافة، ولا تحتاج لقاعدة بيانات بنفسها أو أي مخدم. أيضا يمكن استعراضها على github pages على firebase بعد إنشاء حساب في الخدمة ثم ضمن المشروع نقوم بتهئيته لرفعه npm i -g firebase firebase init firebase deploy سيتخلل إضافة بعض الإعدادات لتوافق مشروعك في Firebase لايتطلب إعدادات إضافية1 نقطة
-
يمكنك رفع مشروع react ببضع نقرات عن طريق vercel أولا قم برفع المشروع على github ثم قم بالتسجيل في موقع vercel بحساب ال github الخاص بك ثم اضغط على new project واختر المستودع الخاص بك واضغط على import وبعد لحظات سيكون مرفوعا ويمكنك زيارته وستجده في vercel dashboard وبالضغط عليه ستجد setting الخاصة به من هناك يمكنك اظافة متغيرات البيئة و اظافة دومين وكما أنك ايضا ستتمتع ب CI أي عندما تقوم ب PUSH للمستودع يتم بناء والرفع من جديد هناك تلقائيا1 نقطة
-
لإستضافة مشروع Next.js في خادم خاص VPS يمكنك إتباع الخطوات التالية: إنشاء خادم خاص من أحد شركات الإستاضفة مثل DigitalOcean أو CloudNode قبل أي شيء، نحتاج إلى إنشاء الخادم وضبطه في السحابة من خلال أحد خدمات شركات الإستضافة، يمكنك أن تشتري أي خادم ويب للتجربة، وسيتم محاسبتك بالساعة (حسب وقت إستعمالك للخادم منذ وقت الشراء)، وقد تتبع شركات إستضافة خطط أخرى غير المحاسبة بالساعة. ضبط اسم المجال Domain أيضًا ستحتاج إلى شراء نطاق / مجال Domain لكي تتمكن من تشغيل مشروعك عبر الإنترنت، حيث أن شركات الإستضافة تمنحك الخادم فقط في أغلب الأحيان، لذلك يجب أن تقوم بشراء نطاق لموقعك بنفسك من خلال أحد شركات الإستضافة مثل namechape أو GoDaddy ..إلخ ، لذلك يجب أن يكون لديك مجال يشير إلى خادم الويب الذي تم إنشاؤه حديثًا. تثبيت وضبط Nginx الآن أنت بحاجة إلى برنامج لكي يدير الطلبات التي تصل إلى خادم الويب الذي قمنا بإنشائه في السابق، يمكنك تنفيذ الأمر التالي لتثبيت Nginx: sudo apt-get update && sudo apt-get install nginx بعد ذلك يجب أن تقوم بالسماح لـ Nginx بأن يمر من خلال جدار الحماية من خلال الأمر التالي: sudo ufw allow 'Nginx HTTP' الآن يمكنك تشغيل Nginx من خلال الأمر التالي: systemctl status nginx ومن المفترض أن تظهر لك نتيجة كالتالي: ● nginx.service - A high performance web server and a reverse proxy server Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2016-04-18 16:14:00 EDT; 4min 2s ago Main PID: 12857 (nginx) CGroup: /system.slice/nginx.service ├─12857 nginx: master process /usr/sbin/nginx -g daemon on; master_process on └─12858 nginx: worker process لاحظ كلمة active في السطر الثالث، وهذا يعني أن Nginx يعمل الآن بدون مشكلة، يمكنك أن تزور عنوان الخادم من خلال المتصفح وستجد صفحة Welcome to Nginx، كما في الصورة: قم بتثبيت Node.js لنشر مشروع مبني بإستخدام Next.js (أو أي مشروع آخر مبني بإستخدام JavaScript) ستحتاج إلى تثبيت Node.js وكذلك NPM ، ويمكنك تثبيتهما من خلال الأوامر التالية: curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash - sudo apt-get install -y nodejs أيضًا توجد الكثير من الحزم التي تعتمد على حزمة build-essential والتالي نحتاج إلى تثبيتها من خلال الأمر التالي: apt-get install -y build-essential الآن يمكنك التأكد من أن كل من Node.js و NPM قد تم تثبيتهما بشكل سليم من خلال الأمر التالي: node --version npm --version وسيظهر لك إصدار كل منهما. انشر تطبيق Next.js الآن نحتاج إلى إرسال الكود إلى الخادم لكي يمكنه العمل، لذلك يمكنك أن تقوم برفع الكود إلى مستودع repo على GitHub إن لم تقم بهذا من قبل (أو يمكنك أن تستعمل بروتوكول FTP ولكن خطوات تثبيته كثيرة كما أنه بطيء للغاية مقارنة بـ GitHub)، ويمكنك تحميل الكود إلى الخادم من خلال الأمر التالي: git clone https://github.com/your_github_username/your_repository_name.git website سيقوم الأمر التالي بتحميل الكود الخاص بك من GitHub إلى الخادم ، وسيضعه في مجلد باسم website، الآن يجب تثبيت الحزم الخاصة بالمشروع عبر الأوامر التالية: cd website npm install npm run dev إن ظهر لك نص كالتالي، فأن كل شيء يعمل على ما يرام: ready - started server on http://localhost:3000 الآن يمكنك الخروج من الأمر الأخير من خلال الضغط على Ctrl + C، ثم تنفيذ الأمر التالي، لإنتاج الكود النهائي للمشروع: npm run build ستلاحظ أنه تم إنشاء مجلد باسم /.next، والآن ستحتاج إلى حزمة pm2 لكي تتأكد من أن التطبيق يعمل طوال الوقت بدون إنقطاع، ويمكنك تثبيت هذه الحزمة عبر الأمر: sudo npm install -g pm2 ثم يجب تشغيل المشروع من خلالها عبر الأمر التالي: pm2 start --name=website npm -- start قم بضبط Nginx كـ reverse proxy كل المتبقي الآن هو إتاحة الموقع للتشغيل عبر إنترنت cd /etc/nginx/sites-available sudo touch example.com sudo nano example.com بعد ذلك يمكنك إضافة الكود التالي لكي يتم تحويل الطلبات من الإنترنت إلى المنفذ 3000، server { listen 80; listen [::]:80; root /var/www/html; index index.html index.htm index.nginx-debian.html; server_name example.com www.example.com; location / { proxy_pass http://localhost:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } } تأكد من تغير example.com و www.example.com إلى نطاق الموقع الصحيح بعد ذلك ستحتاج إلى تشغيل الملف example.com السابق هذا إلى Nginx عبر الأوامر التالية: sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl restart nginx بهذا الشكل يمكنك زيارة الموقع الخاص بك من خلال متصفح الويب عبر زيارة نطاق الموقع بشكل مباشر (سواء بإستخدام www أو بدونها).1 نقطة
-
وعليكم السلام ورحمة الله وبركاته يمكنك البحث في اليوتيوب أخي ستجد كل ماتحتاجه بشأن تصميم الشعارات1 نقطة
-
1 نقطة