لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 03/11/18 في كل الموقع
-
يُقدر أنّ عدد لغات البرمجة الإجمالي يتجاوز 9000 لغة برمجة، منها حوالي 50 لغة تُستخدم على نطاق واسع من قبل المبرمجين [1]. هذا العدد الهائل قد يربك المبتدئ الذي يريد دخول عالم البرمجة، بل وحتى المبرمجين الذين يرغبون في تعلم لغات برمجة أخرى. table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } إنّ أسئلة من قبيل: أيّ لغة برمجة ينبغي أن أتعلم؟ أو ما هي أفضل لغة برمجة؟ أو هل اللغة الفلانية خير من اللغة الفلانية؟ هي من الأسئلة الجدلية. يكفي أن تبحث على جوجل على مثل هذه الأسئلة وستجد ما يشبه حربا ضروسا على شبكة الإنترنت. فهذا يقول إنّ لغة البرمجة الفلانية هي أفضل اللغات، والآخر يقول بل اللغة الفلانية الأخرى خير. هناك سبب وجيه لهذا الاختلاف، ذلك أنّه لا توجد لغة برمجة تناسب الجميع، أو تتفوق على غيرها في كل المجالات. لكل لغة برمجة نقاط قوة ونقاط ضعف. سنحاول في هذه المقالة أن نساعد المبتدئ، وحتى من له خبرة سابقة في البرمجة ويريد تعلم لغات برمجة إضافية، على اختيار لغة البرمجة المناسبة ليتعلمها ويبدأ بها. سنركز في هذه المقالة على ثلاث من أشهر لغات البرمجة وأكثرها شعبية، وهي بايثون وروبي و PHP. سنوازن بين هذه اللغات ونستعرض أهم مميزات كل منها من الجوانب التالية: استخدامات اللغة وتطبيقاتها سهولة التعلم الشعبية الدعم والاستقرَار الأمان المكتبة وإطارات العمل الطلب في سوق العمل محاسن ومساوئ كل لغة باختصار سنختم هذه المقالة بخلاصة لنجيب فيها عن سؤال أيّ هذه لغات البرمجة أنسب لكي تتعلمها وتبدأ بها. استخدامات اللغة وتطبيقاتها بايثون بايثون هي لغة برمجة متعددة الأغراض، أي أنّه يمكن استخدامها لتطوير كافة أنواع التطبيقات، من تطبيقات الويب، وحتى الألعاب وتطبيقات سطح المكتب. تطوير الويب: يمكن استخدام بايثون لتطوير المواقع وتطبيقات الويب، إذ توفّر عددا من إطارات العمل المتقدمة، مثل Django و Flask. لكن شعبيتها لدى مطوري الويب أقل عموما من روبي و PHP. تطوير تطبيقات سطح المكتب: بايثون مثالية لتطبيقات سطح المكتب، إذ أنّها لغة مستقلة عن المنصات وأنظمة التشغيل، فبرامج بايثون يمكن أن تعمل دون جهد إضافي على ويندوز وأنظمة يونيكس. الذكاء الاصطناعي: نحن نعيش ثورة جديدة ستغير كل شيء من حولنا، وهي ثورة الذكاء الاصطناعي وتعلم الآلة التي أصبحت تطبيقاتها في كل مكان، في السيارات ذاتية السياقة وأجهزة التلفاز الذكية وروبوتات الدردشة والتعرف على الوجوه وغيرها من التطبيقات. تُعد بايثون أنسب لغات البرمجة للذكاء الاصطناعي كما يراها 57% من المطورين [2]. إذ توفر للباحثين في هذا المجال مكتبات متقدمة في مختلف مجالات البحث العلمي، مثل Pybrain لتعلم الآلة، وكذلك TensorFlow، وهي مكتبة يمكن استخدامها في الشبكات العصبونية والتعرف على الصور ومعالجة اللغات الطبيعية وغيرها . البحث العلمي: توفر بايثون للباحثين مكتبات عملية متقدمة تساعدهم على أبحاثهم، مثل مكتبة Numpy الخاصة بالحوسبة العلمية، و Scipy الخاصة بالتحليل العددي. بايثون تُستخدم بكثافة في القطاعات الأكاديمية والتجارية، هذه بعض المشاريع والشركات التي طُوِّرت باستخدامها: جوجل: لدى جوجل قاعدة عامة تقول: "استخدم بايثون ما أمكن، واستخدم C++ عند الضرورة". انستغرام: إحدى أكبر الشبكات الاجتماعية Netflix: أكبر منصة لبث الأفلام والمسلسلات على الشبكة Uber: أكبر تطبيق للتوصيل روبي تشبه روبي بايثون في العديد من الجوانب، من ذلك أنّها لغة برمجة متعددة الأغراض، إذ يمكن استخدامها في كافة أنواع التطبيقات. روبي هي لغة كائنية خالصة، أي أنّ كل شيء في روبي هو كائن له توابعه وخاصياته. يجعلها هذا مثالية للبرامج التي تعتمد بكثافة على نمط البرمجة الكائنية. تطبيقات الويب: روبي مثالية لتطوير تطبيقات الويب، إذ توفر إحدى أشهر وأفضل منصات تطوير الويب، وهي Ruby on Rails. والدليل على ذلك أنّ بعض أكبر المنصات والمواقع تستخدم Ruby on Rails، مثل منصة التجارة الإلكترونية Shopify. المشاريع الكبيرة: تُستخدم روبي في المشاريع الكبيرة والمعقدة والتي تستغرق مدة طويلة، وتتطلب تغييرات مستمرة. لغة نمذجة: تُستخدم روبي في تطوير نماذج أولية للبرامج ( prototypes) قبل البدء بتطويرها الفعلي. لغة سكريبتات: تُستخدم روبي (وبايثون كذلك) لبرمجة السكربتات، وهي ملفات تحتوي مجموعة من الأوامر التي يمكن تنفيذها دون الحاجة إلى تصريفها. من أكبر المشاريع والمواقع التي طُوِّرت باستخدام روبي نذكر على سبيل المثال لا الحصر: Sass: أحد أفضل امتدادات لغة CSS. Hulu: منصة لبث الأفلام والمسلسلات والوثائقيات Github : أكبر منصة لاستضافة المشاريع البرمجية PHP على خلاف روبي وبايثون، PHP ليست متعددة الأغراض، وإنما هي لغة متخصصة في برمجة الخوادم. الاستخدام الأساسي للغة PHP هو تطوير الواجهات الخلفية للمواقع وتطبيقات الويب، سواء الساكنة أو الديناميكية. تطبيقات سطح المكتب: صحيح أنّ PHP لغة متخصصة في برمجة الخوادم، إلا أنّه يمكن استخدامها لتطوير تطبيقات سطح المكتب باستخدام مكتبة PHP-GTK. لغة PHP لغة قوية، وقد طُوِّرت بها بعض أكبر المواقع على شبكة الإنترنت، مثل: فيسبوك: أكبر شبكة اجتماعية ياهو: محرك بحث ويكيبيديا: تستخدم هذه الموسوعة الضخمة PHP ضمن مجموعة من اللغات الأخرى ووردبريس: أكبر منصة لإدَارة المحتوى سهولة التعلم إحدى أهم عوامل المفاضلة بين لغات البرمجة هي سهولة تعلمها، خصوصا لدى المبتدئين. تعد بايثون على العموم أبسط وأسهل للتعلم موازنة بلغة روبي أو PHP. بايثون لغة مختصرة وبعيدة عن الإسهاب، في الحقيقة يُقدّر أنّ بايثون تختصر في المتوسط حوالي 80% من الشفرات المكتوبة موازنة بلغات البرمجة الكائنية الأخرى [3]. أضف إلى ذلك أن كتابة شيفرة برمجية بلغة بايثون أشبه بكتابة قصيدة أو قصة باللغة الإنجليزية الأمر الذي لا يجعل كتابة شيفرات بايثون عملية سهلة وممتعة، بل حتى قراءتها أيضًا. تعلم PHP أصعب عمومًا من تعلم بايثون، ذلك أنّ بايثون لغة متعددة الأغراض، أما PHP فهي لغة متخصصة تتطلب معرفة أولية بلغات أخرى، مثل HTML و CSS و Javascript. لكن إن كنت تريد تعلم PHP، فأتوقع أنك تريد أن تتعلم تطوير المواقع، ما يعني أنّك غالبا تعرف أساسيات هذه اللغات. فيما يخص روبي، فهي أصعب قليلا، وقد تحتاج إلى معرفة أولية بأساسيات البرمجة قبل تعلمها. الشعبية تحل بايثون في المرتبة الرابعة كأكثر لغات البرمجة شعبية أثناء تحديث هذا المقال، كما تتربع على عرش لغات البرمجة متعددة الأغراض، إذ يستخدمها حوالي 44% من المبرمجين. ثمّ تأتي لغة PHP في المرتبة الثامنة في قائمة أكثر لغات البرمجة شعبية، إذ يستخدمها حوالي 26% من المطورين، أما روبي فتأتي في المرتبة الرابع عشرة بنسبة استخدام تقارب 7%. لا تتمتع بايثون بالشعبية وحسب، ولكنها محبوبة أيضا لدى مجتمع المبرمجين، ففي الاستطلاع نفسه لعام 2020، جاءت بايثون في المرتبة الثالثة كأحب لغات البرمجة إلى المبرمجين، إذ أنّ أكثر من ثلثي المبرمجين المُستطلَعين قالوا أنّهم يحبونها. بالمقابل أتت كل من روبي و PHP في المرتبتين 19 و 20 على التوالي في هذه القائمة، حيث أنّ 43% من المبرمجين قالوا أنّهم يحبون روبي، و37% منهم قالوا أنهم يحبون PHP. هناك فرق واضح بين بايثون وبين PHP وروبي من حيث الشعبية وحب المبرمجين. بايثون بلا شك تتفوق في هذا الجانب تفوقا واضحا. لكن تجدر الإشارة إلى أنّ لغة PHP متخصصة، فهي تكاد تُستخدم حصرا في برمجة الخوادم، على خلاف بايثون وروبي متعدّدتي الأغراض، واللتان تُستخدمان في كل المجالات تقريبا. لذا رغم أنّ شعبية PHP أقل من بايثون، إلا أنّ هذا لا يقلل من قيمتها، ولا يعني أنّها غير مفيدة أو أنّه ليس لها مستقبل. بل على العكس، فهذا دليل على قوتها، لتتأكد من هذا حاول مقارنة شعبية PHP بلغة البرمجة ASP المتخصصة في المجال نفسه (برمجة الخوادم). لغة ASP ليست موجودة حتى في قائمة أكثر 25 لغة البرمجة استخدامًا. وهذا يعطيك فكرة عن قوة PHP وشعبيتها رغم أنّها لغة متخصصة في مجال واحد فقط. من جهة أخرى، لغتا PHP وروبي ليست محبوبتين للمبرمجين، إذ احتلّتا مرتبتين متأخرتين في قائمة أكثر اللغات المحبوبة. الدعم والاستقرار لغات بايثون وروبي PHP لغات مفتوحة المصدر، وتتمتع بمجتمع كبير من المبرمجين، وتُستخدم على نطاق واسع في المشاريع البحثية والتجارية. ظهرت هذه اللغات الثلاث في أوقات متقاربة: PHP: ظهرت سنة 1995، وهي في الإصدار 7.3 حاليا. بايثون: ظهرت سنة 1991، وهي في الإصدار 3.8 حاليا روبي: ظهرت سنة 1995، وهي في الإصدار 2.7 حاليا ما فتئت هذه اللغات تتطور منذ تأسيسها، خصوصا بايثون و PHP اللتان تُحدَّثان بوتيرة سريعة. كما تتمتع هذه اللغات بمجتمعات كبيرة وحيوية تدعمها، سواء عبر المكتبات أو المقالات أو الدروس والشروح. هناك مسألة يجدر الانتباه لها، وهي أّنه يوجد من بايثون إصداران: الإصدار 2.x والإصدار 3.x. وهما إصداران غير متوافقين، فالبرامج المكتوبة ببايثون 2.x، لن تعمل على بايثون 3.x، والعكس صحيح. هذا الأمر يمكن أن يكون مزعجا، خصوصا للمبتدئين. ولكن لا ينبغي أن تقلق من هذا، إذ أنّ دعم بايثون 2.x توقف سنة 2020، وسيبقى الإصدار بايثون 3.x وحسب. هناك ملاحظة أخرى مهمة، وهي أنّ لغة PHP انتقلت من الإصدار 5 إلى الإصدار 7 مباشرة، إذ أنّه ليس هناك إصدار سادس من هذه اللغة. السبب في ذلك هو أنّه كانت هناك خلافات كثيرة عليها، لذلك انتقل المطورون إلى الإصدار السابع مباشرة، والذي جاء بتعديلات كثيرة وجذرية على اللغة. يُفضل على العموم العمل بهذا الإصدار، لأنه الأحدث، كما أنّ بعض أنظمة إدارة المحتوى، مثل ووردبريس، تتطلب استخدام الإصدار السابع. هذه اللغات الثلاث على العموم مستقرة وتتمتع بدعم كبير وتُحدَّث باستمرار. وستبقى كذلك على الأرجح لمدة طويلة. الأمن لقد أصبح موضوع الأمن الرقمي والخصوصية من المواضيع المهمّة في الوقت الحالي. فكل يوم نسمع عن حالات اختراق وسرقة للبيانات الحساسة، حتى لدى الشركات الكبيرة مثل فيسبوك وجوجل. لهذا السبب ينبغي أن يحرص المبرمج على تأمين تطبيقاته وبرامجه وحماية خصوصيات المستخدمين وبياناتهم الحساسة. لا توجد عمومًا لغة برمجة آمنة تماما، فالأمر لا يعود إلى اللغة أو المنصة المُستخدمة، ولكن يعود إلى مدى احترام المبرمج لمعايير الأمن وكتابة شيفرات نظيفة وخالية من الثغرات الأمنية. قد تجد البعض يقول أنّ PHP أقل أمانا من بايثون وروبي، أو أنها لغة غير آمنة، وهذا أمر مردود. فلو كانت PHP غير آمنة، أنظنّ أنّ أكبر شبكة اجتماعية في العالم، وهي فيسبوك التي تخزن أكبر قاعدة بيانات للبيانات الشخصية للمستخدمين ستستخدم PHP؟ هذا غير ممكن. PHP مثلها مثل بايثون أو روبي، هي لغة مستقرة ويسهر عليها آلاف المطورين الذين يحدثونها باستمرار ويحرصون على سد أيّ ثغرة تظهر فيها. ربما كان السبب الذي يجعل البعض يقول هذا هو أنّ صياغة بايثون البسيطة تقلل من احتمال وجود ثغرات في الشفرة، وذلك على خلاف PHP التي تُعد أعقد من بايثون. قد يكون هذا الأمر صحيحا نسبيا، لكنّ الأمر يعود في النهاية إلى المبرمج، إن كان المبرمج يرتكب أخطاء ولا يحترم معايير الأمن، فلن تكون برامجه آمنة مهما كانت اللغة التي يكتب بها. الأداء والسرعة سرعة التنفيذ هي إحدى العوامل الأساسية لاختيار لغات البرمجة، خصوصا في المجالات التي تحتاج إلى إجراء حسابات مكثّفة، مثل الرسوميات وتطوير الألعاب. هناك نوعان من لغات البرمجة: لغات البرمجة المُفسّرة (interpreted): هي لغات برمجة يتم تنفيذ الشفرات المكتوبة بها مباشرة. لغات البرمجة الُمصرّفة (compiled): هي لغات برمجة تُصرّف (تُترجم) شفراتها إلى لغة المُجمّع أو أيّ لغة وسيطة قبل تنفيذها. على العموم، لغات البرمجة المصرّفة أسرع من لغات البرمجة المفسّرة. تُعد كل من بايثون وروبي لغتين مفسرتين، أما PHP فرغم أنّها مفسرة على العموم، إلا أنّ أنّ البرنامج الذي يسمح لك بتفسير تعليمات PHP مُصرَّف إلى رُقامة (bytecode) وسيطة. لهذا السبب فإنّ PHP عموما أسرع من بايثون، كما أنّ بايثون عموما أسرع من روبي. المكتبات وإطارات العمل تُقاس قوة كل لغة برمجة بالمكتبات التي توفرها. المكتبات هي حُزم من الشفرات الجاهزة والمنظمة التي تقدم دوالا وأصنافًا جاهزة لحل مشاكل معينة، أو إنشاء تطبيقات في مجال معين. أما إطارات العمل فهي منصات للبرمجة والتطوير، وعادة ما توفر أدوات تساعد على إنشاء المشاريع وإدارتها، وتنفيذ الشفرات وتنقيح الأخطاء وغيرها من المهام اليومية التي تسهل عمل المبرمجين. سوف نستعرض في هذه الفقرة بعض المكتبات وإطارات العمل الشهيرة للغات بايثون وروبي و PHP. بايثون Django: هو إطار عمل مجاني ومفتوح المصدر لتطوير المواقع. يوفر Django العديد من المزايا، مثل إدارة قواعد البيانات والمصادقة (authentication) وإدارة المستخدمين وغيرها. pycharm: هو إطار عمل لكتابة البرامج بلغة بايثون، يتولى pycharm التفاصيل الروتينية، ويتيح لك أن تركز على المهام الكبيرة والمعقدة. pycharm هو بيئة تطوير متكاملة، ويوفر العديد من المزايا، مثل الإكمال التلقائي للشفرات وفحص الأخطاء وإدارة المشاريع وغيرها. TensorFlow: هي مكتبة مجانية ومفتوحة المصدر للذكاء الاصطناعي من تطوير شركة جوجل. تُستخدم TensorFlow لكتابة وتقديم خوارزميات الذكاء الاصطناعي والتعلم الآلي والعصبونات. تُستخدم TensorFlow في العديد من مشاريع الذكاء الاصطناعي، مثل البحث الصوتي في جوجل. PyGame: مكتبة لتطوير ألعاب الفيديو، وتوفر العديد من المكتبات لمعالجة الصوت والصورة وكل الجوانب الضرورية لتطوير الألعاب. روبي Ruby on Rails: هو إطار عمل لتطوير تطبيقات الويب، ويوفر كل المزايا والوظائف التي تحتاجها لتطوير تطبيقات ومواقع ويب متقدمة. هذا الإطار مفتوح المصدر ومجاني. Bundler: هي بيئة متكاملة لإدارة مشاريع روبي تمكن من تثبيت المكتبات ومعالجة الإصدارات بسهولة. Better_errors: مكتبة لاختبار الشفرات المكتوبة بلغة روبي وتنقيح الأخطاء. PHP Laravel: أحد أشهر إطارات العمل الخاصة بلغة PHP. يُسرّع Laravel وتيرة العمل على المشاريع الكبيرة، إذ يوفر الكثير من المزايا الجاهزة، مثل المصادقة على المستخدمين وإدارة الجلسات والتخزين المؤقت وغيرها من المهام الأساسية لتطوير تطبيقات الويب. ووردبريس: ووردبريس هو أشهر نظام لإدارة المحتوى، ويُشغِّل ملايين المواقع على الشبكة. هذه المنصة مبنية على PHP. Ratchet: تمكّن هذه المكتبة من إنشاء تطبيقات ثنائية الاتجاه بين الخادم والعميل. تتوفر بايثون وروبي و PHP على المئات إن لم أقل الآلاف من المكتبات وإطارات العمل، وكل سنة تظهر مكتبات وإطارات عمل جديدة تستبدل القديمة أو تنافسها. مهما كانت اللغة التي اخترتها، ومهما كان المجال الذي تعمل فيه، فستجد حتمًا مكتبات جاهزة لمساعدتك على كتابة برامجك. الطلب في سوق العمل الطلب في سوق العمل هو أحد المؤشرات الأساسية للموازنة بين لغات البرمجة، خصوصا لمن كان يبحث عن وظيفة. بحسب استطلاع stackoverflow، فإنّ مطوري روبي يحصلون على أعلى أجر موازنة بمطوري بايثون و PHP. إذ يحصل مطور روبي في المتوسط على 71 ألف دولار سنويا، أما مطور بايثون فيحصل على 59 ألف دولار سنويا، بالمقابل لا يحصل مطور PHP إلا على 39 ألف دولار سنويا. من الواضح أنّ روبي هي الأفضل من حيث الأجور وفرص العمل، وقد يعود ذلك إلى قلة من يتقنون روبي، فقد رأينا من قبل أنّ شعبيتها بين المبرمجين قليلة موازنة ببايثون أو حتى PHP. هذه الأرقام تُحسب على صعيد عالمي، لكن قد يختلف الواقع من دولة إلى أخرى، مثلا في السعودية يحصل مطور PHP سنويا على حوالي 16 ألف دولار [4]، فيما يحص مطور بايثون على حوالي 18 ألف دولار سنويا [5]. أجور مطوّري PHP على العموم أقل من أجور مطوري بايثون وروبي، لكنّ الرواتب لا تُحدد بلغة البرمجة وحسب، إذ يمكن أن يحصل مطوّر PHP محترف وذو خبرة على أكثر مما يحصل عليه مطورو بايثون أو روبي، فالعبرة هنا بالاحترافِية وإتقان العمل. محاسن ومساوئ كل لغة بايثون محاسن مساوئ سهلة التعلم ومناسبة للمبتدئين هناك إصداران غير متوافقان منها صياغة بايثون بسيطة وقريبة من اللغة الطبيعية التعامل مع الأخطاء ليس مثاليا مختصرة وموجزة غير مناسبة لتطبيقات الجوال تتمتع بشعبية كبيرة لدى المبرمجين ليست مثالية للبرامج التي تعتمد على الاستخدام المكثف للذاكرة مكتبة ضخمة تساعد على تطوير كافة أنواع التطبيقات ليست مناسبة للبرامج المتوازية التي تعمل على المعالجات المتعددة روبي محاسن مساوئ مناسبة للبرامج الكبيرة صعبة على المبتدئين تمكن من تطوير التطبيقات بسرعة مصادر تعلم روبي على العموم أقل من بايثون و PHP مجتمع نشيط وحيوي ومكتبة كبيرة بطيئة موازنة باللغات الأخرى تتوفر على إحدى أفضل منصات تطوير تطبيقات الويب: ruby on rails التطوير والتحديث بطيئ PHP محاسن مساوئ سهلة التعلم صياغتها ليست ببساطة بايثون تدعم جميع خوادم الويب الرئيسية مثل: أباتشي ومايكروسوفت و Netscape أسماء الدوال مربكة وغير متناسقة لها شعبية كبيرة جدا لدى مطوري الويب بطيئة موازنة باللغات الأخرى مدعومة من أكبر نظام لإدارة المحتوى، وهو ووردبريس لا تدعم التطبيقات المتوازية خلاصة القول لقد استعرضنا مميزات لغات بايثون وروبي و PHP، ووازنّا بينها من عدة جوانب، وذكرنا بعض مساوئ ومحاسن كل منها. خلاصة القول أنّه لا توجد لغة مثالية تصلح للجميع. لكن إن كنت مبتدئا ولم تكن لك خبرة سابقة بالبرمجة، فإني أنصحك بأن تبدأ بلغة بايثون، فبساطتها وسهولتها ستساعدك على هضم المفاهيم البرمجية بسرعة وبعدها يمكنك أن تنتقل إلى تعلم اللغة التي تريدها بخطى ثابتة وأنت متمكن من المفاهيم البرمجية الأساسية التي تشترك بها كل لغات البرمجة. أما إن كانت لك خبرة سابقة في البرمجة وأردت أن تطور مستواك وتعمل على مشاريع كبيرة، فيمكن أن تتعلم روبي. وإن كنت تريد أن تتخصص في تطوير تطبيقات الويب أو تريد العمل بووردبريس، فالأولَى أن تتعلم PHP. اقرأ أيضًا تعرف على أبرز مميزات لغة بايثون علم البيانات Data science: الدليل الشامل1 نقطة
-
ساعدوني من فضلكم انا وصلت الهاتف ونوعه هواوي gr5 بالكمبيوتر في البدية كان يتصل لحظه توصيله واستطيع عندها تصفح ملفات الهاتف ونقلها علي الكمبيوتر الان عندي مشكله انه عند توصيل الهاتف بالكمبيوتر يقوم بالشحن فقط ولا يتيح لي خيار عرض الملفات كما بالسابق فعلت خيارات المطور وال usb debugging ولم يحدث اي شئ ويقوم بالشحن فقط تأكد ان الهاتف معرف علي الكمبيوتر من device manger الان احتاج الي نقلل بعض الملفات الضروريه من الهاتف الي الكمبيوتر ولا استطيع ارجو ان تساعدوني وجزاكم الله كل الخير1 نقطة
-
بعد أن تطرّقنا في هذه السّلسلة حول أساسيات تطوير قوالب ووردبريس إلى تحويل صفحة HTML إلى قالب ووردبريس ثم إلى كيفية إضافة Pagination (أو ما يُعرف بالتّصفيح) إليها، سنتطرّق اليوم إلى خاصّيّة أخرى لا تقل أهمّية. قوائم التنقّل (Navigation Menu) هي إحدى ميزات القوالب، توفّر ووردبريس طريقة سهلة للتحكم بالقوائم المخصصة للقالب من داخل لوحة تحكم ووردبريس، وكل ما تحتاجه هو إضافة بضعة أسطر برمجية لتضيف دعم القوائم في قالبك. فهرس السلسلة: مقدمة إلى تطوير قوالب ووردبريس: تحويل صفحة HTML إلى قالب ووردبريس التصفيح (Pagination) في قوالب ووردبريس إضافة قوائم التنقل (Navigation Menu) إلى قالب ووردبريس (هذا الدرس) صف وتسجيل ملفات Javascript و CSS في قوالب ووردبريس تسجيل القوائم بدايةً في ملف functions.php ضمن ملفات القالب نحتاج لإضافة دالّة تقوم بتسجيل أسماء القائمة (أو القوائم) التي تريد إضافتها. كالتالي: add_action('init', function() { register_nav_menu('our-custom-menu', 'القائمة الرئيسية'); }); بعد ذلك يمكن التأكد من صحة إضافة القائمة عن طريق الذهاب من لوحة التحكم إلى المظهر (Appearance) ثم القوائم (Menus)، ستظهر لدينا قائمة باسم القائمة الرئيسية في تبويب إدارة موضع القوائم. تأخذ دالّة register_nav_menu محدّدين هما: المكان (Location) والوصف (Description). محدّد المكان يستخدم كمعرّف للقائمة، حيث يتم طلب محتوى القائمة ضمن ملفات القالب عن طريق محدّد المكان (location) الذي قمنا بتعيينه أثناء تسجيل القائمة. في حالتنا قمنا بوضع قيمة المحدد هي: our-custom-menu. والوصف يتم استخدامه عند عرض القائمة في لوحة التحكم ليكون أنسب وأسهل للقراءة من محدد المكان، في حالتنا قمنا بوضع قيمة الوصف هي: القائمة الرئيسية. يمكننا تسجيل أكثر من قائمة في آن واحد عن طريق استخدام دالّة register_nav_menus التي تستخدم بشكل مشابه لدالّة register_nav_menu لكن المحدّدات تكون على شكل مصفوفة اسميّة (Associative Array)، كل عنصر في المصفوفة يمثّل قائمة واحدة بحيث يكون مفتاح العنصر هو محدّد المكان وقيمة العنصر هي محدّد الوصف. في قالبنا لا نحتاج سوى لقائمة واحدة، في ما يلي كيفية تسجيل أكثر من قائمة معًا: add_action('init', function() { register_nav_menus([ 'our-custom-menu' => 'القائمة الرئيسية', 'our-second-menu' => 'القائمة الفرعية', ]); }); كما ننوه إلى وجود دالّة معاكسة لدالّة تسجيل القوائم هي unregister_nav_menu لكننا لن نتطرّق إليها الآن. إظهار القائمة في القالب الخطوة الأخيرة ضمن القالب هي عرضه في المكان المناسب. في القالب الذي نستعمله نجد أن موقع القوائم أصبح في ملف header.php، في السطر 30 من الملف نجد وسم <section class="top-bar-section">، نريد أن نضع القائمة بدلاً من وسم <ul> الموجود بداخله. نقوم بحذف وسم <ul> مع محتواه، ثم نستخدم السطر البرمجيّ التالي لعرض القائمة: <?php wp_nav_menu(['theme_location' => 'our-custom-menu']); ?> تقبل دالّة wp_nav_menu مُحدداً واحداً هو مصفوفة تحوي عددًا من الإعدادات، الإعداد الوحيد الضروري هو theme_location ويتم استخدامه كما في السطر البرمجي السابق. يمثل هذا المحدّد قيمة محدّد المكان السابقة التي استخدمناها أثناء تسجيل قائمة جديدة والتي كانت: our-custom-menu. في حال لم يتم إدخال هذا المحدّد تقوم ووردبريس باستخدام قيمة إعداد menu (سنأتي إليه في الفقرة التالية)، وإن لم تجد قيمة فسيتم عرض أول قائمة غير فارغة تجدها ووردبريس، وفي حال عدم وجود أي قوائم غير فارغة وعدم تمرير محدّد المكان فلا يتم عرض شيء. إن ألقينا نظرة على القالب من المتصفح سنجد أن شكل عناصر القائمة أصبح مختلف قليلاً عن الشكل الذي كان عليه، وذلك ﻷن الدالّة تقوم بإضافة وسم <div> محيط بوسوم القائمة. في الفقرة التالية سنتعرف على بقية الإعدادات التي يمكن أن نستخدمها مع دالّة wp_nav_menu والتي ستمكننا من إظهار القائمة على الشكل الأنسب. إعدادات دالة wp_nav_menu كما قلنا من قبل فإن دالّة wp_nav_menu تأخذ محدّداً واحداً هو مصفوفة تحوي مجموعة إعدادات، المبرمج ليس مضطراً لإدخال جميع الإعدادات، يمكنه إدخال بعضها والباقي ستقوم ووردبريس بمعالجته وإسناد قيمته الافتراضية. الإعدادات بشكل كامل هي: <?php $defaults = array( 'theme_location' => '', 'menu' => '', 'container' => 'div', 'container_class' => '', 'container_id' => '', 'menu_class' => 'menu', 'menu_id' => '', 'echo' => true, 'fallback_cb' => 'wp_page_menu', 'before' => '', 'after' => '', 'link_before' => '', 'link_after' => '', 'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>', 'depth' => 0, 'walker' => '' ); wp_nav_menu( $defaults ); ?> theme_location مكان القائمة ضمن القالب، كما تم تحديده أثناء تسجيل القائمة باستخدام دالّة register_nav_menu، ليكون بإمكان المستخدم تحديد القائمة المطلوبة للمكان الذي تم تسجيله (دون تقييد المستخدم بقائمة واحدة). القيمة الافتراضية: '' (سلسلة نصية فارغة) menu القائمة المطلوب عرضها، تقبل قيمة المعرّف الرقمي (ID)، أو الاسم اللطيف (slug)، أو الاسم الخاص بالقائمة (وليس مكان القائمة ضمن القالب). القيمة الافتراضية: '' (سلسلة نصية فارغة) container لتحديد إن كان مطلوبًا من ووردبريس إحاطة وسم <ul> بوسم آخر أم لا، القيمة المسموحة هي div أو nav، وفي حال عدم الرغبة بإحاطة القائمة بوسم نجعل القيمة false. القيمة الافتراضية: 'div' container_class الصنف الخاص بوسم html المحيط بالقائمة، بشكل افتراضي يأخذ الصنف الشكل: menu-{menu slug}-container حيث يكون {menu slug} هو الاسم اللطيف للقائمة. القيمة الافتراضية: '' (سلسلة نصية فارغة) container_id معرّف CSS (ID) الذي يتم تطبيقه على الوسم المحيط (container). القيمة الافتراضية: '' (سلسلة نصية فارغة) menu_class الصنف الذي يتم تطبيقه على وسم القائمة <ul>، يمكن أن يتم وضع أكثر من صنف يتم الفصل بينهم بفراغات (space). القيمة الافتراضية: 'menu' menu_id معرّف (ID) CSS الذي يتم تطبيقه على وسم القائمة <ul>. بشكل افتراضي تكون قيمته: menu-{menu slug} حيث {menu slug} هو الاسم اللطيف للقائمة؛ في حال حدوث تكرار بالاسم يتم إضافة إشارة - مع رقم مميز يبدأ من 1 ويزيد عند كل تكرار، مثلًا: menu-{menu slug}-1، menu-{menu slug}-2، إلخ. القيمة الافتراضية: '' (سلسلة نصية فارغة) echo فيما إن كنا نريد إظهار القائمة مباشرة في مكان استخدام دالّة wp_nav_menu أو نريد إرجاعها (return). القيمة الافتراضية: true fallback_cb دالّة ليتم استخدامها في حال لم تكن القائمة موجودة، نضع قيمتها false في حال لم نكن نريد استخدام دالّة. ويتم تمرير محدّد $args للدالّة التي يتم استخدامها. القيمة الافتراضية: 'wp_page_menu' before إظهار نصّ قبل وسم <a>. القيمة الافتراضية: '' (سلسلة نصية فارغة) after إظهار نصّ بعد وسم </a>. القيمة الافتراضية: '' (سلسلة نصية فارغة) link_before إظهار نصّ قبل نصّ الرابط. القيمة الافتراضية: '' (سلسلة نصية فارغة) link_after إظهار نصّ بعد نصّ الرابط. القيمة الافتراضية: '' (سلسلة نصية فارغة) items_wrap يتم تفسيرها بنفس الطريقة التي يتم تفسير محدّد الهيئة (format) لدالّة sprintf. يحدث تعاون بين المحددات الأخرى عن طريق رموز رقمية. %1$s تُستبدل بقيمة محدد menu_id، %2$s تُستبدل بقيمة محدد menu_class، و %3$s تُستبدل بقيمة عناصر القائمة (وسوم <li>). إن تم استبعاد أي رمز رقمي من هذا المحدّد، سيتم استبعاد المحدّد المرتبط به من وسوم القائمة. القيمة الافتراضية: '<ul id="%1$s" class="%2$s">%3$s</ul>' depth يمثل عدد المستويات الهرمية التي سيتم استخدامها، حيث رقم 0 يعني جميع المستويات. ويتم استخدام قيمة -1 لتحويل جميع المستويات إلى مستوى واحد فقط. القيمة الافتراضية: 0 walker يتم تمرير عنصر هو نسخة من صنف Walker_Nav_Menu أو من صنف يرث من ذلك الصنف. الهدف من هذا المحدد هو التحكم بشكل كامل بالأصناف (classes) والمحدّدات (IDs) ووسوم HTML للقائمة. يمكن العودة لتوثيق WordPress للاطلاع على المثال المقدم القيمة الافتراضية: '' (سلسلة نصية فارغة) تحسين ظهور القائمة في القالب بعد أن تعرّفنا على إعدادات إظهار القائمة، دعونا نقوم بتعديلها في قالبنا لتصبح مناسبة أكثر. إن شاهدنا مصدر HTML للصفحة الرئيسية من المتصفح، نجد أننا نحتاج لإزالة الوسم المحيط بالقائمة (container)، ونحتاج لإضافة صنف right لوسم <ul> المحيط بعناصر القائمة. يمكننا تعديل السطر البرمجي في ملف header.php ليصبح: <?php wp_nav_menu([ 'theme_location' => 'our-custom-menu', 'container' => false, 'menu_class' => 'right', ]); ?> قمنا بجعل قيمة الوسم المحيط (container) تساوي false ﻷننا لا نريد إحاطة القائمة بأي وسم، فنحن من البداية نقوم بإحاطة القائمة بوسم <section> في قالب HTML الذي نستخدمه. وقمنا أيضًا بإضافة قيمة محدد menu_class لتساوي: right، ليتم إضافة صنف right لوسم القائمة <ul> ليظهر بشكل جيّد. بهذا نكون قد جعلنا القائمة تظهر بشكل مرن، ونعطي المستخدم إمكانية أكبر لاختيار ما يناسبه من عناصر للقائمة من خلال لوحة التحكم، وبنفس الوقت جعلنا القائمة التي يختارها المستخدم تظهر بأفضل شكل ضمن القالب الذي نعمل عليه. الشريط الجانبي الأشرطة الجانبية (Sidebars) هي إحدى ميزات القوالب، هو بشكل بسيط عمود شاقولي يقوم القالب بتزويده لعرض معلومات مختلفة عن المحتوى الأساسي للموقع، تقوم الأشرطة الجانبية بعرض ودجات/مربعات (widgets) يقوم مدير المدونة بالتحكم بها. التعامل مع الشريط الجانبي يشبه إلى حدّ كبير التعامل مع القوائم. تسجيل شريط جانبي لنقم معاً بإضافة ما يلي إلى ملف functions.php لتعريف شريط جانبيّ جديد: add_action('widgets_init', function() { register_sidebar(); }); إن قمنا بزيارة لوحة التحكم، نجد أن هناك عنصراً جديداً في قائمة المظهر (Appearance) هو الودجات (Widgets)، بداخله يظهر لنا الشريط الجانبي الجديد بعنوان الشريط الجانبي 1، إن قمنا بإضافة شريط جانبي آخر سيأخذ نفس الاسم لكن بزيادة الرقم بمقدار واحد. والسبب أننا عندما قمنا بتسجيل الشريط الجانبي لم نحدد له اسماً أو معرّفاً. سنقوم بهذا الآن بعد أن نتعرف على إعدادات هذه الدالّة. إعدادات دالّة register_sidebar الإعدادات الافتراضية: $args = array( 'name' => sprintf( __( 'Sidebar %d' ), $i ), 'id' => "sidebar-$i", 'description' => '', 'class' => '', 'before_widget' => '<li id="%1$s" class="widget %2$s">', 'after_widget' => "</li>\n", 'before_title' => '<h2 class="widgettitle">', 'after_title' => "</h2>\n", ); شرح الإعدادات: name اسم الشريط الجانبي (القيمة الافتراضية هي ترجمة كلمة ‘Sidebar’ مع معرّف رقميّ). id معرّف الشريط الجانبي - يجب أن يكون بأحرف صغيرة (lowercase), دون فراغات (القيمة الافتراضية هي معرّف رقمية يتم زيادته تلقائياً ). description وصف نصّي لماهيّة/مكان الشريط الجانبي. يظهر في واجهة إدارجة الودجات في لوحة التحكم. (القيمة الافتراضية: فارغة) class صنف CSS ليتم إسناده للشريط الجانبي في صفحة إدارة الودجات، ولن يتم استخدام هذا الصنف في القالب. ملاحظة: سيتم إضافة كلمة “sidebar” إلى قيمة الصنف. مثلاً: إن وضعنا اسم الصنف: tal ستكون قيمة الصنف هي: sidebar-tal. (القيمة الافتراضية: فارغة). before_widget وسم/وسوم HTML ليتم وضعها قبل كل واحد من الودجات (widget) (القيمة الافتراضية: ‘<li id="%1$s" class="widget %2$s">‘). ملاحظة: يتم استخدام دالّة sprintf لاستبدال المتحولات. after_widget وسم/وسوم HTML ليتم وضعها بعد كل واحد من الودجات (widget) (القيمة الافتراضية: '\n'). before_title وسم/وسوم HTML ليتم وضعها قبل كل عنوان (القيمة الافتراضية: <h2 class="widgettitle">). after_title وسم/وسوم HTML ليتم وضعها بعد كل عنوان (القيمة الافتراضية: “</h2>\n“). عرض الشريط الجانبي في القالب نتوجه إلى ملف sidebar.php، ونقوم بتعديله ليصبح كالتالي: <div class="large-4 columns sidebar"> <?php dynamic_sidebar(); ?> </div> قمنا باستبدال النصّ الموجود مسبقاً “Sidebar” بدالّة ()dynamic_sidebar التي وظيفتها عرض محتويات الشريط الجانبي في المكان المحدد. يمكن أن نمرّر قيمة واحدة لتلك الدالّة إما أن تكون اسم (name) أو معرّف (ID) الشريط الجانبي. وفي حال عدم تمرير أي قيمة يتم عرض الشريط الجانبي الأول. تخصيص الشريط الجانبي كما لاحظنا فشكل ودجات الشريط الجانبي غير مقبولة، لنقم معًا بتحسين مظهرها عن طريق إحاطة كل واحدة من الودجات (widgets) بوسم <div class="card"> الذي كان موجودًا في ملف sidebar.php قبل استخدام دالّة عرض الشريط الجانبي. لنقم باستخدام إعدادات دالّة ()register_sidebar التي مرّت معنا في الفقرات السابقة، في ملف functions.php نقوم بتعديل الدالّة لتصبح: register_sidebar(['before_widget' => '<div class="card">', 'after_widget' => '</div>']); قمنا بتمرير إعدادَين فقط لإضافة وسم div قبل واحدة من الودجات وإضافة إغلاق الوسم بعد كل واحدة منها. بهذا نكون قد انتهينا من إضافة قائمة رئيسية وشريط جانبي إلى القالب، وتعلمنا معاً كيف يمكن تخصيص شكل القائمة والشريط الجانبي ليتناسب مع القالب بأفضل شكل ممكن.1 نقطة
-
يُتيح نظام تشغيل أندرويد طريقة محددة وبسيطة للتنقل بين المكونات الأساسية للتطبيقات والتي ذكرناها سابقًا وذلك عن طريق استخدام الـ Intents. Intents يُعتبر الـ Intent طريقة التواصل بين مكونات التطبيق المختلفة من أجل القيام بشيء ما، فهو يسمح لمكونات التطبيق (كالأنشطة Activities ، الخدمات Services وغيرها) من التفاعل مع بعضها البعض والقيام بإحدى المهام، فباستخدام الـ Intent يمكننا التنقل بين شاشات التطبيق المختلفة أو التطبيقات الأخرى فمثلًا عند الضغط على زر يقوم بفتح نشاط Activity جديد داخل نفس التطبيق وعرض صورة به، كما يسمح بتفاعل التطبيقات الأخرى المتواجدة على الهاتف مع تطبيقك، فيمكن عرض الصورة في تطبيق خارجي كتطبيق المعرض (Gallery). وعند استخدام الـ Intent في التنقل بين مكونات نفس التطبيق يسمى بالـ Explicit Intent، لذا يستخدم Explicit Intent في ربط مكونات التطبيق الداخلية ببعضها وسنتعرف من خلال الأمثلة القادمة على كيفية استخدام الـ Explicit Intents في التنقل بين الأنشطة وإرسال واستقبال البيانات بينهم. وعند استخدامه للتنقل إلى التطبيقات الخارجية يسمى بالـ Implicit Intent. المثال الأول الآن قم بفتح Android Studio وقم بعمل تطبيق جديد اسمه "Explicit Intent Example"، في هذا المثال سنقوم باستخدام زر للتنقل إلى نشاط جديد. أولًا نقوم بصنع واجهة المستخدم الخاصة بالنشاط الأول والرئيسي في الملف activity_main.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Welcome to The First Activity" android:textSize="21sp"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="GO!" android:id="@+id/gobtn"/> </LinearLayout> ثانيًا للاستجابة للزر عند الضغط عليه نقوم باستخدام onClickListener. package apps.noby.explicitintentexample; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.Button; public class MainActivity extends Activity { Button go; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); go =(Button) findViewById(R.id.gobtn); go.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //Create your Intent Here } }); } } وبداخلها سنقوم بكتابة الـ Intent المناسب ولكن قبل ذلك ينبغي أن نقوم بعمل نشاط جديد وربطه بواجهة استخدام جديدة ولعمل ذلك نضغط بالزر الأيمن على المجلد المسمى باسم الحزمة ثم اختر: New > Activity > Empty Activity قم بكتابة اسم النشاط الجديد وتأكد من وجود اسم الحزمة في المكان المخصص لها كما بالصورة التالية: بعد أن يقوم البرنامج بصنع ملفات النشاط الجديد من ملف activity_second.xml سنقوم بصنع واجهة المستخدم الخاصة بالنشاط الثاني. وسنضع بداخلها TextView يعرض النص "Welcome to The Second Activity": <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Welcome to The Second Activity" android:textSize="21sp"/> </LinearLayout> والآن نعود مرة أخرى للنشاط الأول لنكمل التابع ()onClick، ولصنع Intent نقوم بعمل كائن من الصنف Intent وتمرير لدالة البناء الخاصة به النشاط الذي سننتقل منه وهو MainActivity.this وتمرير النشاط الذي نريد الانتقال إليه وهو SecondActivity.class. Intent i = new Intent(MainActivity.this,SecondActivity.class); بهذا السطر نكون قد صنعنا الهدف ولكن يتبقى أن نقوم بتفعيل هذا الهدف ليستجيب له التطبيق وذلك عن طريق التابع ()startActivity وتمرير الـ Intent الذي قمنا بصناعته إليه. لتصبح الشيفرة النهائية هي: package apps.noby.explicitintentexample; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; public class MainActivity extends Activity { Button go; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); go =(Button) findViewById(R.id.gobtn); go.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //Create your Intent Here Intent i = new Intent(MainActivity.this,SecondActivity.class); startActivity(i); } }); } } والآن نقوم بتجربة التطبيق على المحاكي والتأكد من قيامه بالوظيفة المطلوبة. عند النظر إلى ملف AndroidManifest.xml نجد أنه تم إضافة تعريف لعنصر جديد من النوع Activity، ولاحظ أن بدون تعريف العنصر الجديد لن يعمل التطبيق بشكل سليم ولن يتعرف نظام التشغيل عليه. <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".SecondActivity"></activity> </application> … المثال الثاني سنقوم في هذا المثال بإرسال بيانات من نشاط وعرضها في نشاط آخر. أولًا نقوم بصنع النشاط الجديد الذي سيتم عرض البيانات بداخله. ثانيا نبدأ بصنع واجهة المستخدم في ملف activity_main.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Your Name" android:textSize="21sp" android:id="@+id/editt"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Send" android:id="@+id/sendbtn"/> </LinearLayout> ثم سنقوم بالاستجابة لضغط الزر كما سبق وبداخل التابع ()onClick يتم تعريف الـ Intent وحفظ البيانات المكتوبة في الـ EditText بداخله ثم استدعاء النشاط الجديد. ولإرسال البيانات داخل الـ Intent يتم ذلك عن طريق التابع ()putExtra ونمرر له عنصرين وهما المفتاح و القيمة. المفتاح هو نص نميز به القيمة التي يتم إرسالها عبر الـ Intent ويُستخدم مرة أخرى لاستعادة البيانات التي أرسلناها. والقيمة هي البيانات التي نرغب في إرسالها. package apps.noby.explicitintentexample; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; public class MainActivity extends Activity { final public static String NAME_TAG = "name"; private Button send; private EditText et; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); send =(Button) findViewById(R.id.sendbtn); et = (EditText)findViewById(R.id.editt); send.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //Create your Intent Here Intent i = new Intent(MainActivity.this, SecondActivity.class); String name = et.getText().toString(); i.putExtra(NAME_TAG,name); startActivity(i); } }); } } قمنا بتعريف المفتاح على هيئة نص ثابت وذلك لتسهيل استخدام المفتاح مرة أخرى عند استعادة البيانات في النشاط الآخر. ثم بعد ذلك نقوم بصنع واجهة المستخدم الخاصة بالنشاط الثاني: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, " android:textSize="21sp" android:id="@+id/hellotxt"/> </LinearLayout> ولاستقبال النص الذي أرسلناه بداخل الـ Intent يجب علينا أولًا أن نستعيد الـ Intent الذي قام بفتح النشاط باستخدام التابع ()getIntent. Intent actIntent = getIntent(); ولاستعادة النص الذي حفظناه نستخدم ()getText().toString ونمرر لها المفتاح الذي قمنا بحفظ البيانات به، ثم بعد ذلك نعرض هذا النص بداخل TextView. package apps.noby.explicitintentexample; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.TextView; public class SecondActivity extends AppCompatActivity { private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); tv =(TextView) findViewById(R.id.hellotxt); Intent actIntent = getIntent(); String name = actIntent.getExtras().getString(MainActivity.NAME_TAG); tv.setText("Hello, " + name); } } ثم نقوم بتجربة التطبيق على المحاكي. المثال الثالث سنقوم في هذا المثال بإعادة البيانات من النشاط الثاني إلى النشاط الأول عند الانتهاء من التفاعل مع النشاط الثاني. أولًا نُنشئ تطبيقًا جديدًا به نشاطان كما في الأمثلة السابقة ونبدأ بصنع واجهة المستخدم الخاصة بالنشاط الأول. <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Register" android:id="@+id/regbtn"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="NO Name" android:textSize="30sp" android:id="@+id/regtxt"/> </LinearLayout> وبداخل النشاط الأول نقوم باستدعاء النشاط الثاني عند الضغط على الزر المتواجد بالواجهة ولكن في هذا المثال لإخبار نظام التشغيل بأننا ننتظر بيانات من النشاط الآخر سنقوم بفتح النشاط الآخر بالتابع ()startActivityForResult بدلًا من التابع ()startActivity. private static final int ACTIVITY_REQUEST_CODE = 6 ; private Button reg; private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); reg =(Button) findViewById(R.id.regbtn); tv = (TextView)findViewById(R.id.regtxt); reg.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //Create your Intent Here Intent i = new Intent(MainActivity.this, SecondActivity.class); startActivityForResult(i,ACTIVITY_REQUEST_CODE); } }); } ونمرر للتابع ()startActivityForResult الـ Intent كالمعتاد والرقم الخاص بالطلب وهذا الرقم هو أي رقم صحيح، وفائدته عند رجوع البيانات للنشاط مرة أخرى التمييز بين أي الأنشطة التي قامت بإرسال هذه البيانات. وفي هذا المثال قمنا بتعريف رقم ثابت وتمريره للتابع وعند عودة البيانات سنقوم بالتأكد من هذا الرقم مرة أخرى. والآن نقوم بصنع الواجهة الخاصة بالنشاط الآخر في ملف activity_second.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Enter Your Name" android:textSize="21sp" android:id="@+id/edttxt"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Enter" android:id="@+id/entbtn" android:layout_gravity="right"/> </LinearLayout> بعد ذلك نكتب شيفرة التحكم الخاصة بهذا النشاط. package apps.noby.explicitintentexample; import android.content.Intent; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; public class SecondActivity extends Activity { public static final String REG_NAME_TAG ="name" ; private EditText et; private Button enter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); et =(EditText) findViewById(R.id.edttxt); enter = (Button) findViewById(R.id.entbtn); enter.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String str = et.getText().toString(); Intent in = new Intent(); in.putExtra(REG_NAME_TAG,str); setResult(RESULT_OK,in); finish(); } }); } } فعند الضغط على الزر Enter نقوم بتسجيل النص المتواجد بداخل العنصر EditText، إنشاء Intent جديد وحفظ النص بداخله ثم استدعاء التابع ()setResult والذي يمكننا من إرسال البيانات التي قمنا بتخزينها داخل Intent إلى من قام باستدعاء هذا النشاط. ونمرر للتابع ()setResult الثابت RESULT_OK والمعرّف داخل الـ (API (android.app.Activity كما نمرر لها الـ Intent الذي قمنا بإنشائه وحفظ البيانات بداخله. أخيرًا نستخدم التابع ()finish وهو المسؤول عن غلق النشاط. لاستقبال هذه البيانات في النشاط الأول نقوم بتضمين التابع ()onActivityResult في النشاط كما يلي. package apps.noby.explicitintentexample; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class MainActivity extends Activity { private static final int ACTIVITY_REQUEST_CODE = 6 ; private Button reg; private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); reg =(Button) findViewById(R.id.regbtn); tv = (TextView)findViewById(R.id.regtxt); reg.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //Create your Intent Here Intent i = new Intent(MainActivity.this, SecondActivity.class); startActivityForResult(i,ACTIVITY_REQUEST_CODE); } }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if ( (resultCode == RESULT_OK) && (requestCode == ACTIVITY_REQUEST_CODE)){ String name = data.getExtras().getString(SecondActivity.REG_NAME_TAG); tv.setText(name); } } } وبداخل هذا التابع نتأكد من أن النشاط السابق تم إغلاقه بشكل صحيح ولم يحدث له مشكلة عن طريق التأكد من أن المتغير resultCode يساوي RESULT_OK التي قمنا بتمريرها للتابع ()setResult ثم نتأكد أيضًا من أن النشاط الذي يُعيد هذه البيانات له رقم طلب يساوي رقم الطلب الذي قمنا باستخدامه مسبقًا، بعد ذلك نبدأ في استقبال البيانات. ثم نقوم بتشغيل التطبيق على المحاكي. الأمثلة السابقة كانت باستخدام Explicit Intent للقيام بالوظيفة المطلوبة ولربط مكونات التطبيق المختلفة ببعضها فيمكنك من صنع تطبيق متعدد الأنشطة، في الأمثلة القادمة سنقوم باستخدام الـ Implicit Intents والتعامل معها. المثال الرابع في هذا المثال سنقوم بفتح موقع أكاديمية حسوب في تطبيق المتصفح، وبنفس الطريقة يمكن فتح الروابط الأخرى خارج التطبيق. قم بإنشاء تطبيق جديد يُدعى "Implicit Intent Example" ثم نبدأ بصنع واجهة المستخدم في ملف activity_main.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Open Hsoub Academy" android:id="@+id/opnbtn"/> </LinearLayout> وعند الضغط على الزر نقوم بفتح الرابط. Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse("http://academy.hsoub.com")); startActivity(i); ونمرر لدالة البناء الخاصة بالـ Intent نوع الفعل الذي نريده من التطبيق الخارجي وفي هذا المثال نريد تطبيق يستطيع عرض البيانات بداخله، ثم نمرر له نوع البيانات المراد عرضها وهي الرابط الخاص بموقع أكاديمية حسوب. لتصبح الشيفرة النهائية الخاصة بالبرنامج كما يلي: package apps.noby.explicitintentexample; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity { private Button open; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); open = (Button) findViewById(R.id.opnbtn); open.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //Create your Intent Here Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse("http://academy.hsoub.com")); startActivity(i); } }); } } ثم نقوم بتجربة التطبيق النهائي على المحاكي. المثال الخامس في هذا التطبيق سنقوم بالاتصال من خلال فتح تطبيق الاتصال من داخل التطبيق الخاص بنا. نبدأ أولًا بصنع واجهة المستخدم في ملف activity_main.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Dial Number" android:id="@+id/dialbtn"/> </LinearLayout> وعند الضغط على الزر نقوم بالاتصال بالرقم التالي: Intent i = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:0123456789")); startActivity(i); ونمرر لدالة البناء الخاصة بالـ Intent نوع الفعل الذي نريده وهو الاتصال بالرقم، ثم نمرر له الرقم. ثم نقوم بتجربة التطبيق النهائي على المحاكي. بهذا نكون قد وصلنا إلى نهاية هذا الدرس، في انتظار تجربتكم وآرائكم.1 نقطة
-
طيب يا ريت توضحي بعض المعلومات شو نوع قاعدة البيانات المستخدمة؟ mysql, mongoDB, etc... ماهي لغة البرمجة المستخدمة؟ php, ruby, python, etc...1 نقطة
-
اختي الكريمة تحتاجين في هذه الحالة إلى استخدام jQuery وجافا سكربت اضافة إلى ال PHP مثال: ملف ال HTML يكون هكذا <html> <head> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> </head> <body> <select name="first" id="first" onchange="fillSecond()"> <option value="0" >الرجاء الإختيار</option> <option value="1">برمجة</option> <option value="2">تصميم</option> </select> <select name="second" id="second"> <option value="0" >الرجاء الإختيار</option> </select> <script type="text/javascript"> function fillSecond() { var first = document.getElementById("first"); var firstSelected = first.options[first.selectedIndex].value; $("#second").load("load.php", { Id: firstSelected }); } </script> </body> </html> ملف ال PHP يكون هكذا واحرصي على تسميته load.php <?php $id = $_POST['Id']; if( $id == 1 ): ?> <option>PHP</option> <option>HTML</option> <option>Javascript</option> <?php elseif( $id == 2 ): ?> <option>تصميم داخلي</option> <option>تصميم بوسترات</option> <option>تصميم مواقع</option> <?php endif; ?> اذا اردتي في ال select الثاني ان تستدعي بيانات من قاعدج البيانات تقومين بتعديل ملف load.php بحيث تضعين while loop او foreach loop لاستدعاء البيانات من قاعدة البيانات وداخلها تضعين ال option مع المتغيرات داخل الحلقة while او foreach1 نقطة
-
اذا كنت محتفظ بأي معلومات تسجيل دخول داخل البرنامج, فيجب عليك التخلص منها وإتخاذ طريقة اخرى لعملها. لان هذا يعتبر خطأ برمجي حاد, فأي شخص يستطيع الوصول لها بكل سهولة. لذلك مايتوجب عليك عمله هو اولاً ضبط طريقة الاتصال بالـ SQL Server وذلك عن طريق التعديل على ConnectionString للإتصال وجعله يعتمد على حساب المستخدم المسجل بالنظام Windows Account Login .. والـ ConnectionString سيكون شبيه بالتالي : connectionString="Data Source=ServerName;Initial Catalog=DatabaseName;Integrated Security=True" فقط تقوم بتغيير الـ ServerName و DatabaseName .. وسيكون الاتصال بقواعد البيانات مبني على تصاريح حساب المستخدم الذي يستخدمه على النظام نفسه Windows .. ومن الممكن ان يتم عمل متغيرات لها حتى يتمكن المستخدم من تغيير اسم ServerName و DatabaseName اذا كان سير عمل البرنامج يسمح بذلك. اما عن معلومات تسجيل الدخول الاخرى او اي معلومات قد تكون حساسة , يجب عليك تشفيرها وعدم حفظها بدون تشفير, وجعل البرنامج يقرأها بالتشفير. واذا كنت لاتعرف كيف ذلك, انصحك بالبحث والقراءة ثم تطبيقها على مشروع جديد (تجريبي) وعندما تكون جاهزة , يمكن تطبيقها على البرنامج وعمل التغييرات اللازمة لها. يمكن ايضاً حفظها بملف اعدادات البرنامج Settings وذلك عن طريق الضغط على اسم المشروع الزر الايمن ثم اختيار Properties ثم الذهاب الى Settings .. اذا لم يكن هنالك ملف اعدادات قم بإنشاءه (في Visual Studio سيكون هنالك رسالة لذلك عند فتح نافذة Settings فقط اضغط عليها وسيتم انشائها تلقائياً). فائدة ملف الاعدادات هذا هو حفظ اي بيانات تمكن البرنامج من قرائتها باستمرار بما فيها معلومات الـ ConnectionString مثل DatabaseName و ServerName .. ويمكن ايضاً حفظ معلومات الدخول فيها ولكن كما ذكرت ليست الحل الامثل لها ولكنها ستعمل خارج نطاق البرنامج. ويمكن ايضاً وضع متغيرات بداخلها يقوم البرنامج بقرائتها او الحفظ فوقها في كل مره يعمل (مثل عدد مرات تشغيل البرنامج) .. اما بداخل البرنامج فيتم استدعائها عن طريق : String someString = Properties.Settings.Default.MySavedSettingString; اما اذا كنت قد استخدمت خصائص DataSet و Data Models وقمت بإستيراد schema من الـ VisualStudio فالـ ConnectionString سيكون استدعائه مشابه للمثال الآتي : String db = ConfigurationManager.ConnectionStrings["ProjectName.Properties.Settings.db"].ConnectionString; اتمنى ان تكون الامور اوضح الآن1 نقطة
-
فقط قم بالذهاب الى قائمة Build ثم اختار Publish وحدد مكان حفظ البرنامج .. واستخدم هذه النسخة مع الزبائن .. مايقوم به الـ Publish هو عمل نسخة Complied للبرنامج ويقوم بحفظ حزمة الملفات داخل ملف exe حتى يمكن للشخص تنصيب البرنامج على جهازه.1 نقطة
-
توفِّر JavaScript إمكانية بناء كائن Date جديد، وإذا أمعنت النظر في المعاملات التي يقبلها هذا الكائن، فستلاحظ أنَّ مجال «اليوم» بين 1 إلى 31. لاحظ أنَّه عند استدعاء الدالة البانية Date مع أكثر من وسيط، وكانت القيم أكبر من مجالها المنطقي (مثلًا: استخدمنا 13 مكان الشهر أو 70 مكان الدقائق أو 0 مكان «اليوم») فستُعدّل قيمة التاريخ بما يوافق ذلك. لذا سنستعمل 0 مكان «اليوم» عند بناء الكائن كما يلي: var dateNow = new Date(); var lastDayOfMonth = new Date(dateNow.getFullYear(), dateNow.getMonth() + 1, 0).getDate(); console.log(lastDayOfMonth); ما سبق سيُنشِئ كائن Date جديد للسنة الحالية، وللشهر القادم، ولليوم 0، ولمّا كان أول يوم في الشهر هو 1 وليس 0، فسيؤخذ آخر يوم من الشهر الذي يسبق الشهر الماضي (أي الشهر الحالي). راجع توثيق الدالة البانية Date والدالة getFullYear والدالة getMonth والدالة getDate في موسوعة حسوب للمزيد من المعلومات.1 نقطة
-
الدالة explode في PHP تستقبل متغيرين كباراميتر والاثنين يجب ان يكونا نصين والرسالة تقول انك قمت باعطائها مصفوفة في الباراميتر الثاني وهذا خطأ . الدالة مهمتها هي تحويل نص الي مصفوفة حسب محدد انت تعطيه للدالة في الباراميتر الاول يكون هذا المحدد يوجد في النص . مثلا الكود التالي متغير نصي ولكن الكلمات يتم التفرقة بينهم بالرمز "," ستعطي للدالة الرمز "," في المتغير الاول والثاني تعطيها النص او الكلمات التي تريد تحويلها الي مصفوفة : $names = "one, two, three"; $names_as_arr = explode(',', $names); print_r($names_as_arr); // النتيجة // Array ( [0] => one [1] => two [2] => three ) ارجو ان يكون واضحا السبب انك اعطيت للدالة في الباراميتر الثاني مصفوفة بينما هي تتوقع نص .1 نقطة
-
قد تفشل المشاريع في بعض الأحيان. إنّه أمر يعلمه جميع المستقلّون وروّاد الأعمال –عددٌ قليلٌ جدًّا من الناس استطاع الإقلاع في عمله بنجاحٍ من المرّة الأولى. إن لم تكن راضيًا عن أداء مدوّنتك بعد فترة من الوقت، ليس هناك عارٌ في أنْ تعلن إغلاقها. إنْ كنت تفكّر في إغلاق مدوّنتك، فلا بدّ أنْ تفعل ذلك لأسبابٍ وجيهةٍ. على سبيل المثال، إنْ لم يكن قد مضى على إطلاقك لمدوّنتك سوى أسبوعين ولم يكن هناك أيّة زياراتٍ لها، فمن السابق لأوانه اتخاذ قرارٍ متهورٍ كهذا. من ناحية أخرى، إنْ كنت قد أطلقتها منذ أكثر من نصف عامٍ وكنت لا تزال مراوحًا في المكان، عندها قد تحتاج إلى القيام ببعض التقييمات الجدّية. في هذا المقال، سأحدّثكم حول ثلاثة سيناريوهات يكون من المنطقيّ عندها حذف مدوّنتك والبدء من جديد، أو التركيز على مشروعٍ آخر. دعونا نذكرها بدءًا من الأهمّ. وقت الإغلاق رقم 1: ليس لديك عددٌ كافٍ من الزيارات إنْ كان عدد زيارات مدوّنتك بالآلاف في الشهر، فذلك أكثر من جيّد. تستغرق أيّ مدوّنة وقتًا طويلاً للوصول إلى عدد زياراتٍ مقبول. حتى لو كان موقعك الإلكترونيّ من أفضل المواقع الموجودة، لا يمكنك أنْ تتوقع نجاحًا كبيرًا بين عشيّةٍ وضحاها. وبخبرتي، هناك عاملان يحدّدان مدى شعبيّة المدوّنة: كميّة المحتوى الذي تضيفه للمدوّنة. إذا كنت تنشر مقالاتٍ جديدةً بشكلٍ أسبوعيّ، على سبيل المثال، يجب ألّا تستغرق مدونتك وقتًا طويلاً حتّى تكتسب بعض الجاذبية. استراتيجيّتك في تحسين الظهور في محرّكات البحث (SEO). حتّى لو كانت مقالاتك ممتازة، يجب عليك انتقاء الكلمات المفتاحيّة المناسبة لها وتحسينها. وإلّا، قد لا يجد الناس المحتوى الخاصّ بك مطلقًا. إنْ كنت تتناول هذين الجانبين وكانت مدوّنتك نشطة منذ ما لا يقلّ عن نصف عام، فربّما ليس لديك البيئة الملائمة لتوفير عدد زياراتٍ يضمن الجهد المبذول. قد يكون ذلك بسبب المنافسة الشديدة، وفي هذه الحالة تحتاج إلى التفكير مليًّا وبشكلٍ جديٍّ حول كميّة الوقت المستعدّ لقضائه قبل أنْ ترى بعض النتائج الجيّدة. أمّا الآن، فتذكّر أنّه لا يوجد مقياس عالمي ل “عدد الزيارات المقبول”. إنْ كنت تحصل على 1,000 مشاهدة يوميًّا، فهذا ممتاز، ولكن المدوّنة التي تستقبل 100 زائر فقط قد تجني نفس المبلغ من المال. وبشكل عامّ، كلّما زاد عدد زيارات مدوّنتك، ازداد مردودك. مع أخذ ذلك في الاعتبار، إذا كان موقعك الإلكتروني لا يزال في مراحله الأولى، وكنت لم تصل بعد إلى مرحلة الستّ أشهرٍ، فاعمل بجدٍّ واستمرارٍ –فمن المبكر جدًا إغلاقها! وقت الإغلاق رقم 2: التحويلات ليست بالحجم الذي تريده تعد الدعوات إلى الإجراء “Calls to action” وسيلةً بسيطةً، وفعّالةً لزيادة التحويلات. في معظم الحالات، تتناسب التحويلات مع مقدار الزيارات التي تحصل عليها مدوّنتك. ومع ذلك، قد تكون مدونتك شائعة بما فيه الكفاية، ولكنّك لا تكسب المال الكثير الذي كنت تتوقّعه. لحسن الحظّ، هناك الكثير من الطرق التي تمكّنك من تغيير الأمور. وفيما يلي بعض الأمثلة على ذلك: تغيير تصميم مدوّنتك أو نسخها. إذا كنت تريد أنْ يحصل موقعك الإلكتروني على مزيدٍ من التحويلات، فيجب أن توجّه الزوار إلى المكان الذي تريدهم أن يذهبوا إليه. أَجْرِ اختبار المقارنة لصفحاتك “A/B testing”. مع عددٍ كافٍ من الزيارات، يمكنك إنشاء أشكالٍ مختلفةٍ من صفحاتك وزيادة عدد زياراتها، لاختبار أيّ منها هي الأفضل. استخدام القوائم البريدية للترويج للتحويلات. إذا اشترك شخصٌ ما في القائمة البريديّة لمدوّنتك ، فمن المحتمل أنْ يكون مستعدًّا لتقبّل العروض الخاصّة أو العروض الترويجيّة. إذا كان موقعك يحصل على كميّةٍ مناسبةٍ من الزيارات، فقد ربحت الجولة الأولى. كل ما عليك فعله الآن هو أنْ تجد وسيلةً للوصول إلى المزيد من هؤلاء المستخدمين وتحويلهم لمدوّنتك. يجب أنْ يكون هدفك الأساسيّ هو الحصول على المزيد من الأموال مع الحفاظ على متطلّبات موقعك الإلكترونيّ. وبعبارةٍ أخرى، فإنّك تحتاج إلى معدّلٍ إيجابيّ لعائد الاستثمار (ROI). تحديد كميّة المال “الكافية” متروك لكم. ومع ذلك، إذا لم تصل مدونتك إلى هذا الهدف المتوسّط بعد تحسينها باستخدام الطرق المذكورة أعلاه (ومنحها الوقت الكافي لتحدث تغييرًا)، فالوقت قد حان للبحث عن استثمار أفضل. من ناحية أخرى، إذا لاحظت تحسنًا في عائد الاستثمار، فعندها لن تكون بحاجةٍ إلى إغلاق مدوّنتك بينما هي في طور التحسّن. وقت الإغلاق رقم 3: أنت تروّج لنفسك بشكلٍ بسيطٍ بسبب إدارتك لعدّة مدوّنات معًا. تحتاج كل مدوّنةٍ إلى تحديثاتٍ مستمرّةٍ حتّى تزدهر، وإدارة مدوّناتٍ متعددةٍ بنفس الوقت قد يؤثّر عليك سلبًا. إذا كنت تعمل على مشاريعٍ متعددةٍ في وقتٍ واحدٍ، فمن المنطقيّ إغلاق مدوّنتك إنْ كان لديك واحدةٌ أكثر نجاحًا، لتركيز جهودك عليها. في الواقع، هناك ذكاءٌ مطلقٌ في أنْ تبدأ العمل على مدوناتٍ متعدّدةٍ في آن واحد، في حال كنت قادرًا على تحمّل أعباء العمل. وبهذه الطريقة، يمكنك تقليل احتمالات فشلك والحصول على معرفة مباشرة تساعدك في تحديد الأشياء النافعة لك من الضارة منها. ومع ذلك، يُرجَّح أن تكون كميّة العمل اللازمة لإدارة مدوّنتين أو أكثر بدقّةٍ تامةٍ أصعب من أنْ يقدر أيّ شخصٍ على تحمّلها. أؤمن وبشدة بالمبدأ القائل ألّا تجهد نفسك بالعمل، لذلك فمن الأفضل أنْ تركّز جهودك على مدوّنة واحدة للأسباب التالية: يجب أنْ يكون لديك المزيد من وقت الفراغ. فوقت الراحة يجب أن يكون ضروريًا ومضاعفًا حتى إنْ كنت تعمل من المنزل. إنْ لم تضعْ حدودًا، سينتهي بك الأمر بالردّ على رسائل العمل الإلكترونيّة عند الساعة الثالثة صباحًا. يجب أن تكون أقلّ إجهادًا. كَمًّا أقلّ من العمل يعني إجهادًا أقلّ، وهذا ما سيمكّنك من إنشاء مدوّناتٍ أفضل. يحتاج المحتوى الناجح لمدوّنتك المزيد من الوقت. في ظلّ غياب أعباء العمل الإضافيّة، ستتمكّن من زيادة كميّة المحتوى الذي تنشره في المدوّنة التي تلتزم بها. وبالطبع، يعمل هذا السيناريو فقط إنْ كان لديك مشروعٌ آخر أكثر نجاحًا تحتاج لتركيز جهودك عليه بشكل أكبر. ومع ذلك، إنْ لم تكن أيٌّ من مدوّناتك تبلي بلاءً حسنًا بعد مضيّ فترة من الزمن، فإنّه لا يزال من المنطقي أنْ تغلق المدوّنة ذات الأداء الأسوأ. إنْ كان قدْ مضى على إنشاء مدوّنتك فترة من الزمن، فقد تتمكّن من بيعها لاسترداد جزءٍ من رأس المال المُنفَق عليها. ومع ذلك، إنْ لم يكن لديك مشروعٌ آخرٌ لصبّ جهودك فيه، يمكنك دائماً بدء مدوّنةٍ جديدةٍ توظّف فيها خبراتك المكتسبة. خُلاصة إنْ كنت تمتلك نفس طريقة التفكير التي أفكّر بها، لن ترغب أبدًا بإغلاق المدوّنة. ومع ذلك، هناك بعض الحالات التي يُستحسن فيها إغلاقها لخفض خسائرك، وتركيز جهودك على مشاريعٍ جديدة وأفضل. إذا كانت مدونتك لا تزال ضعيفة الأداء على الرغم من فعلك لكلّ شيءٍ بالشكل الصحيح، فقد يكون حذفها الخيار الأمثل لك. ومن أجل التوضيح فقط، يمكنك أن تعيد هيكلة مدونتك في معظم الأحيان، لذا أريد أنْ أوصيك ألّا تخطُ خطوة الإغلاق إلا في إحدى الحالات الثلاث التالية: في حال عدم حصولك على عدد كافٍ من الزيارات بعد مضيّ نصف عامٍ من العمل أو أكثر. في حال لم تكن التحويلات كافيةً لتغطية نفقاتك أو تبرير جهدك حتى مع وجود محتوى متين واستراتيجيات SEO سليمة. في حال كان لديك كميّة عملٍ كبيرةٍ، ومن الأفضل أن تبذل جهدك على مشروعٍ آخرٍ. ترجمة -وبتصرّف- للمقال When Is the Right Time to Quit Your Blog and Start a New One لصاحبه Alexander Cordova1 نقطة
-
قد تصبح عملية التسويق لخدمتك أو مشروعك التجاري عملية مكلفة، وبالرغم من أن ذلك استثمار سيعود عليك بنتائج ممتازة على المدى الطويل، إلا أن الحصول على التمويل اللازم لتغطية التكاليف أمرٌ لا يخلو من الصعوبة، خصوصًا في الأيام الأولى من عمر الشركة. تحتاج معظم عمليات التسويق إلى ميزانية متوسطة على الأقل، ولكن هناك بعض الطرق الفعّالة التي يمكنك اتّباعها في الترويج لمشروعك التجاري دون أن يكلِّفك ذلك شيئًا على الإطلاق؛ إذ يمكن الاستعانة بقوة وسائل التواصل الاجتماعي في الترويج لخدمتك أو مشروعك التجاري، وفي تثقيف الناس حول ما تقدّمه والطريقة التي يمكنك مساعدتهم بها، وكلّ ذلك بالمجّان. لنلقِ نظرة على أفضل طرق التسويق للخدمات والمشاريع التجارية عبر وسائل التواصل الاجتماعي والتي لا تكلّف درهمًا واحدًا. 1. اشترك في Twitter Chats تعدّ محادثات تويتر (Twitter Chats) وسيلة ممتازة لجمع الأفراد المهتمّين بموضوع أو صنعة أو شركة معيّنة. ولما كان الجميع مرتبطين بوسم (hastag) معين فيمكن حينئذٍ استخدام محادثات تويتر لجذب عملاء جدد من الجمهور المستهدف. بصورة عامة، يبدأ المدير أو قائد الشركة بمحادثة في تويتر وذلك بتغريد سؤال واحد أو أكثر وتتضمن هذه التغريدات وسمًا خاصًّا بها، ويمكن للمشتركين الإجابة عن هذه الأسئلة باستخدام الوسم نفسه، وهكذا تكون جميع التغريدات ذات الصلة مرتبطةً بعضها ببعض. يمكن للمشتركين تقديم أفكارهم الخاصة، وعرض آراء متباينة، والتفاعل مع بعضهم البعض، وعادة ما تُنظَّم محادثات تويتر في الوقت نفسه كل أسبوع وتُطرَح مواضيع جديدة للنقاش في كل مرة. تخضع كل محادثة إلى قواعد وقوانين خاصة يضعها مُنشئ تلك المحادثة، ولكن ترويج المنتجات والخدمات بصورة مباشرة أمرٌ غير محبّذٍ على اﻹطلاق. ومع هذا، تشجع محادثات تويتر على إجراء المحاورات بين الأعضاء المهتمين بمواضيع متشابهة، لذا ستزداد فرصك في التواصل مع بعض الأشخاص من الجمهور المستهدف. يمكنك مثلًا إضافة روابط للمحتوى أو المنتج أو الخدمة التي تقدمها والتي تمثّل في نظرك حلًّا للمشاكل التي يواجهونها وذلك بعد إجراء محادثة بسيطة معهم في البداية. احرص فقط أن تكون المحادثة عفوية وطبيعية قدر الإمكان. تتنوع المواضيح المطروحة في محادثات تويتر تنوّعًا كبيرًا، وعليك أن تعرف المواضيع الملائمة لعملك. حاول التواصل مع بعض الروّاد في مجال عملك لتتعرّف عن طريقهم على بعض المحادثات المعروفة، وتابع على الدوام الأوسمة المرتبطة بمجال عملك، مع التذكير بأنّك قادر على إنشاء محادثة خاصّة بك. تذكّر عند المشاركة في المحادثات بأنّها تتحرّك وتتغير بسرعة؛ لذا حافظ على تركيزك وحاول التواصل مع أكبر قدر ممكن من الأشخاص، حتى لو لم تكن متأكّدًا من كونّهم جزءًا من جمهورك المستهدف. 2. كن نشطًا في مجموعات فيسبوك مجموعات فيسبوك هي طريقة أخرى لجمع الأشخاص المهتمّين بموضوع أو فكرة أو صنعة معيّنة عبر وسائل التواصل الاجتماعي. ولكن، على العكس من محادثات تويتر، فإن مجموعات فيسبوك تكون دائمية، ويمكن للأشخاص الانضمام إلى هذه المجموعات والخروج منها حسب رغبتهم، ويمكنهم كذلك ترك الرسائل وإضافة التعليقات وطرح الأسئلة في أي وقت يشاؤون. يمكن تشبيه مجموعات فيسبوك بالمنتديات، حيث هناك مدراء للمجموعات يضعون القواعد التي من شأنها تنظيم المجموعة وضمان التزام جميع أعضاءها بمواضعيها العامة، ويمكن للأعضاء إنشاء المحادثات وطرح الأسئلة والإجابة على المنشورات بكل حرية. تعتمد القواعد المفروضة في المجموعة - كما هو الحال في محادثات تويتر - على مؤسّسي المجموعة ومديريها، ولكن ليس من المحبّذ بصورة عامّة الترويج لمشروعك التجاري بصورة مباشرة في أيِّ مكان. يتطلب الترويج الفعال لمشروعك التجاري عبر مجموعات فيسبوك الحضور الدائم والفعّال، ومشاركة المحتوى الذي يقدّم حلولًا للمشاكل التي يواجهها أعضاء المجموعة وإجاباتٍ مفيدة للأسئلة التي يطرحونها. في بعض الأحيان تُطرح أسئلة معينة وبصورة متكرّرة في المجموعة دون أن يتمكّن أحدٌ من اﻹجابة عنها، وفي هذه الحالة عليك أن تستغلّ الفرصة وتُجري الأبحاث اللازمة لتقدّم محتوىً جديدًا يملأ هذه الفجوة. يمكن العثور على مجموعات فيسبوك - كما هو الحال مع محادثات تويتر - عن طريق البحث بالكلمات المفتاحية المرتبطة بمجال عملك، أو التركيز على الأماكن التي يتواجد فيها جمهورك المستهدف. احرص على أن تكون فعّالًا بعد الانضمام إلى المجموعة، إذ كلّما تعرّف أعضاء المجموعة عليك وعلى علامتك التجارية بصورة أكبر، ازدادت فرصة زيارتهم لموقعك الإلكترونيّ وربّما شراء منتجاتك. 3. تبنّى المحادثات ثنائية الأطراف تستخدم معظم المشاريع التجارية الصغيرة منصّات التواصل الاجتماعي لإرسال روابط للمحتوى والموقع الإلكتروني والمنتجات والخدمات التي تقدّمها. ولكن عادة ما يتجاهل الناس هذه الروابط عندما تُرسل في السياق الخاطئ، ومع أنّ الكثير من العملاء المحتملين إضافة إلى الجمهور المستهدف يرغبون في التفاعل والتواصل مع علاماتهم التجارية المفضّلة، فقد يؤدي أسلوب التواصل هذا والذي يكون من طرف واحد فقط إلى نفور هؤلاء الأشخاص وقد تكون النتائج سلبية. من الضرورة بمكان إدراك الطريقة الفعّالة لترويج الخدمات والمحتوى الذي تقدّمه على صفحات التواصل الاجتماعي، فالبدء بالمحادثة من الأمور المهمّة لجذب الانتباه إليك، ولا تتوقع أبدًا أن تحوز اهتمام المجتمع حينما لا تكون منتبهًا إلى السياق العام عند إرسال الروابط الخاصّة بك، وبطبيعة الحال فإن عدم حصولك على اهتمام الناس يعني أنّهم لن يتوجّهوا إلى موقعك اﻹلكتروني لشراء منتجاتك. هذا لا يعني عدم استخدام الروابط في وسائل التواصل الاجتماعي على الإطلاق، ولكن يجب عليك الانتباه إلى عدم الإلحاح في هذه المسألة، فالروابط وسيلة مهمّة لإيصال جمهورك المستهدف إلى موقعك الإلكتروني للتواصل معك أو لشراء المنتجات التي تقدّمها، ولكن عليك أن تحرص على استخدام الروابط في الجزء المناسب من المحادثة لتحفّز القرّاء على الاستجابة أو لتُطْلِعَهم على المزيد من المعلومات. الهدف الرئيسي هنا هو أن تكون المحادثة ثنائية الأطراف، ما يعني أنّ عليك أن تكون الطرف الفعّال في المحادثة، وإن استجاب أحد الأشخاص لمنشوراتك فعليك أن تردّ عليه من غير إبطاء لكي لا تتوقف المحادثة عند هذا الحدّ. أنصت دائمًا لما يطلبه جمهورك المستهدف، وقدّم إليهم المحتوى أو المعلومات أو المنتجات أو الخدمات التي تساعدهم في تحقيق طلباتهم وحلّ مشاكلهم. 4. تواصل مع الأشخاص المؤثرين يجب أن لا يقتصر التواصل على العملاء المحتملين فقط، فإلى جانب الجمهور المستهدف يجب عليك الاستفادة من منصّات التواصل الاجتماعي في التواصل مع الأشخاص المؤثّرين في مجال عملك، والمقصود بالأشخاص المؤثُرين هم الصحفيون والمدونون والروّاد في مجال عملك، بل وحتّى العلامات التجارية الأخرى التي لا تكون مُنافسةً لك بصورة مباشرة. يمكن أن لا يكون الأشخاص المؤثرون من عملائك، ولكنّهم يمتلكون على الأرجح قاعدة جماهيرية عريضة تضمّ جزءًا كبيرًا من الجمهور المستهدف والذي يمتلك ثقة كبيرة في اختيارات هؤلاء المؤثرين وفي آرائهم. إن تمكّنت من التواصل مع الأشخاص المؤثرين وكسب صداقتهم، فسيتعرّف عليك العديد من الأشخاص الجدد حينئذ وقد يفكّر هؤلاء في أن يصبحوا عملائك في المستقبل. يكفيك مثلًا أن يذكرك أحد الأشخاص المؤثرين في صفحته أو أن يعيد نشر إحدى منشوراتك وستحصل على عدد من العملاء الجدد لعلامتك التجارية. يمكنك بناء مثل هذه العلاقات بالتحاور مع أحد الأشخاص المؤثرين في مجال عملك، ويمكنك مثلًا الرد على منشوراتهم، أو مشاركة المحتوى الذي يقدّمونه لمتابعيهم، أو التواصل معهم عبر محادثات تويتر أو مجموعات فيسبوك، وسيساعد ذلك على توطيد العلاقة التي تربطك بهم وبنفس الطريقة التي تتبعها في حياتك الشخصية، وكلما ازداد التواصل أصبحت العلاقة أقوى وأقوى. احرص كذلك على أن تكون علاقتك بالأشخاص المؤثّرين علاقةً متبادلةً، بمعنى أن تشارك أنت أيضًا ما يقدّمونه من محتوى مع متابعيك، وأن توضّح لهم مدى قدرتك على مساعدتهم في تحقيق أهدافهم. الخلاصة يرتبط نجاح مشروعك التجاري ارتباطًا وثيقًا باتّباع الأسلوب الملائم في التسويق، غير أن هذا لا يعني أنّك بحاجة إلى إنفاق أموال طائلة لجذب العملاء المحتملين. إن كنت غير قادرٍ على إنفاق الكثير من المال أو كنت تبحث عن طريقة لتوفيره، فيمكنك الاستفادة من وسائل التواصل الاجتماعي في الترويج لخدماتك ومنتجاتك وبصورة فعّالة دون أن تنفق قرشًا واحدًا. لنراجع معًا الوسائل الأربعة التي يمكنك اﻻستفادة منها في الترويج لخدمات مشروعك التجاري عبر وسائل التواصل الاجتماعي وبالمجان: شارك في محادثات تويتر لتتواصل مع أفراد جدد في الجمهور المستهدف. كن نشطًا في مجموعات فيسبوك لتقديم الأفكار القيمة والمفيدة. ابدأ محادثات ثنائية الأطراف، وشارك المحتوى المفيد عندما يحتاج الجمهور المستهدف ذلك. احرص على تكوين علاقات مع الصحفيين والمدوّنين والرواد في مجال عملك. ما هي الوسيلة التي ستتبعها الآن من هذه الوسائل الأربعة المجانية؟ أخبرنا بذلك في التعليقات. ترجمة - وبتصرّف - للمقال 4 Free Ways to Find Clients Using Social Media Marketing لصاحبه Tom Ewer. حقوق الصورة البارزة محفوظة لـ Freepik1 نقطة