لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 06/10/15 في كل الموقع
-
هناك العديد من الأسباب التي تجعلك ترغب في ضغط Compression الملفّات والمجلدات على الحاسوب، واحدة من أبسط الفوائد التي تجعلك تقوم بذلك هي توفير مساحة التّخزين على القرص واستخدام عرض نطاق bandwidth أقل في اتّصالات الشّبكة. سنناقش في هذا الدّرس بعضًا من الطّرق المختلفة لضغط البيانات وسنتحدّث قليلاً عن بعض تفضيلات الطّرق المختلفة، سنتطرّق أيضًا إلى بعض العمليّات المرتبطة بذلك كالأرشفة archiving، والتي تجعل أدوات الضّغط أكثر مرونة. سنقوم باستعراض هذه الأدوات على نظام تشغيل Ubuntu 14.04 ولكنّها ستعمل تمامًا على أي توزيعة لينِكس حديثة. أساسيّات الضّغط والأرشفةقبل أن نذهب إلى الأدوات الفعلية التي سنستخدمها، يجب أن نُعرِّف مصطلحاتنا ونناقش بعضًا من المُميّزات المختلفة للضّغط والأرشفة. الضّغط هو طريقة لتقليل حجم الملف على القرص باستخدام خوارزميات وطرق حسابية مختلفة، تكون الملفّات مُنسّقة بطريقة معيّنة تجعل بنيتها الأساسية مُتوقَّعة بشكلٍ ما حتّى ولو كان محتواها مختلفاً، بل وأكثر من ذلك فإنّ المحتوى بذاته عادةً ما يكون متكرّرًا، لذلك يتيح لنا كلا هذين الأمرين فرصة لتطبيق تقنيات الضّغط. 1- الضّغط الفَقُود والضّغط غير الفَقُود Lossy and Lossless Compressionعندما نناقش موضوع الضّغط بالنّظر إلى الحواسيب وأنواع الملفّات فقد تحمل المصطلحات نفسها معاني مختلفة بحسب المحتوى، فلنأخذ كمثال ملفات الموسيقى التي تحمل صيغة MP3، حيث أنّ ملف الـ MP3 هو ملف صوتي مضغوط يتمّ استخدامُه لإنشاءِ ملفٍ ذي حجمٍ أصغر وذلك اعتماداً على ملفٍ صوتيٍّ ذي حجمٍ أكبر. يختلف هذا النّوع من الضّغط بشكلٍّ أساسيٍّ عمّا نتحدث عنه في هذا الدّرس لأنّ ملف الـ MP3 يتمُّ إنشاؤه عبر تحليل شكل الموجة الصّوتيّة من ملف الصّوت ومحاولة معرفة أيُّ البيانات يُمكنُ حذفها نهائيًا مع المحافظة على صوت الملف الأصلي. وهذا ما يُدعى طريقة الضّغط الفَقُود lossy compression لأنّه فعلًا فقدَ بيانات من الملف الأصلي، وليس بإمكانك تحويل ملف الـ MP3 مرّة أخرى إلى الملف الأصلي لاحقًا. قد لا يُلاحِظ المستخدم عمليّة الضغط ولكنَّها لا تحتوي كامل البيانات من الملف الأصلي، وكلَّما كان معدّل الضّغط أعلى كلَّما بَدأت أجزاء أكثر من الصّوت تتأثر بعمليّة الضّغط. وكمثال آخر على هذا الصّور ذات الصّيغة JPEG، فكلَّما تمَّ ضغطها بشكلٍ أكبر كلَّما تمّت خسارة المزيد من البيانات وكلَّما اتضحت عمليّة الضّغط أكثر، تُحاول أداة ضغط صيغة JPEG إيجاد الحقولِ ذاتِ الألوان المتقاربة لبعضها وتقومُ باستبدالِ الحقلِ كاملًا بلونٍ واحد، كلَّما زادَ معدَّل الضّغط المستخدم كلَّما زاد مدى الألوان الذي يتم تغطيته بهذه الطريقة. بالمقابل تقوم طريقة الضّغط غير الفَقُود lossless compression بإنشاء ملف ذي حجم أصغر من الأصل والذي يمكننا باستخدامه إعادة بناء الملف الأصلي. الضّغط غير الفَقُود هو نوع الضّغط الذي سنقوم بتغطيته في هذا الدّرس، لا يستخدم هذا النّوع من الضّغط القيم التقريبيّة لضغط البيانات، بل يستخدم بدلاً من ذلك خوارزميّات التّعرّف على الأجزاء المتكرّرة من الملف ويقومُ بإزالتها واستبدالها بماسك المكان placeholder، ويتابع ليستبدل لاحقاً حوادث النّمط بمرجعيّات references لنفس ماسك المكان. يسمح هذا للحاسوب بتخزين المعلومات على مساحة أقلّ من القرص، تُشبه هذه العمليّة كإنشاء قائمة من المتغيّرات variables والتي تُعرِّف تركيبة من البيانات ومن ثمّ استخدام هذه المتغيّرات لاحقًا لإنشاء البرنامج، تستخدم كلّ عمليّة ضغط غير فَقُود هاتين المرحلتين الفعليّتين وهما ربط القيم المتكرّرة إلى شيءٍ ما أصغر، والذي يمكن الرّجوع له بسهولة، ومن ثمّ تبديل الأحداث لكل واحدة من هذه القيم بمرجع لها. بل وأكثر من ذلك يُقال عن طرق الضّغط غير الفَقُود أنّها قابلة للتكيّف، هذا يعني أنّها لا تقوم بتحليل كامل الملف في البداية ومن ثمّ تقوم بإنشاء قاموس من البدائل المرجعيّة منه، بل تقوم بدلاً من ذلك بتحليل الملف أثناء عمليّة الضّغط ومن ثم تعيد كتابة القاموس بناءً على البيانات التي تمّ فعلياً تكرارُها، ويُصبح القاموس تدريجيًا أكثر فائدة مع استمرار العمليّة. 2- خلفيّة عن الأرشفةتعني فكرة أرشفة البيانات بشكلٍ عام عمل نسخة احتياطيّة لها وحفظها إلى مكان آمن، عادةً في صيغة مضغوطة، يحمل الأرشيف بشكل عام معنى مختلف قليلاً على نظام لينِكس، حيث عادة ما يشير إلى ملف ذو صيغة tar. تاريخيًّا كان يتمّ النّسخ الاحتياطي للبيانات على شرائط أرشفة tape archives، والتي هي عبارة عن أجهزة أشرطة ممغنطة يُمكِن استخدامها لتخزين البيانات المتتابعة، لا زالت هذه الطريقة هي المفضّلة لدى بعض المجالات، ولكي يتم عمل هذا بشكلٍ فاعل تمّ إنشاء برنامج tar حتى تستطيع التعامل مع العديد من الملفّات في نظام الملفّات بأذونات permissions وبيانات وصفية metadata سليمة كملف واحد، ومن ثم تستطيع استخراج الملف أو كامل نظام الملفّات من الأرشيف. الملف ذو اللاحقة tar بشكل أساسي هو عبارة عن صيغة ملف تقوم بإنشاء طريقة ملائمة لتوزيع وتخزين والنسخ الاحتياطي والتّعامل بمجموعة من الملفّات المرتبطة، سنقوم أيضًا في هذا الدّرس بالتحدث عن الأرشفة لأنه عادة يتم ضغط الملفّات المُؤرشفة خلال عملية الأرشفة وذلك لكي يتم تخزين البيانات بطريقة أكثر فاعلية. المقارنة بين أدوات الأرشفة المختلفةيملك لينِكس العديد من أدوات الأرشفة المختلفة، حيث يُقدّم كلًّا منها تضحيات في بعض المجالات ويملك بعضًّا من مواطن القوة، سنقوم بالميل تجاه مخطّطات الضّغط التي تعمل بالصّيغة tar لأنها أكثر مرونة من الطّرق الأخرى. 1- الضّغط بأداة gzipتمّ تصنيف أداة gzip بشكل نمطي على أنّها الطّريقة الكلاسيكية لضغط البيانات على آلة تعمل بنظام التشغيل لينِكس، فهي موجودة تقريباً منذ العام 1992م وهي لا تزال قيد التطوير ولا يزال لديها الكثير من الأمور لتسير عليها. تستخدم أداة gzip خوارزمية ضغط معروفة بـ DEFLATE، وهي خوارزمية مستخدمة أيضًا في تقنيات شائعة أخرى مثل صيغة الصورة PNG وبروتوكول الوِيب HTTP وبروتوكول القشرة الآمنة SSH secure shell protocol. إنّ السّرعة هي واحدة من أهمّ مزايا هذه الأداة، حيث يُمكن ضغط وفك ضغط البيانات بمعدّل أعلى مقارنةً بتقنيّات منافسة، خاصةً عند مقارنة معظم الصيغ المدمجة لكل أداة، وهي أيضًا أكثر فاعليّة من حيث الموارد resources بالنظر إلى استخدام الذاكرة memory usage خلال الضّغط وفك الضّغط ولا يبدو أنّها تتطلب ذاكرة أكثر عند التطلع إلى عملية الضّغط الأفضل. ونأخذ التوافقية compatibility أيضًا بعين الاعتبار، فحيث أنّ gzip هي أداة قديمة فإنّ معظم أنظمة تشغيل لينِكس بغض النظر عن عمرها ستملك الأداة لكي تتعامل مع البيانات. إنّ أكبر مساوئ هذه الأداة أنّها تضغط البيانات بشكل غير مكتمل تماماً بالمقارنة مع بعض الخيارات الأخرى، لذلك إن كنت تقوم بالكثير من عمليّات الضّغط وفك الضّغط السّريعة فإنّ هذه الصّيغة هي ملائمة بالنسبة لك، ولكن إن كنت تُخطّط لضغط الملف مرّة واحدة ومن ثمّ تخزينه حينها ستجد أنّ الخيارات الأخرى تملك مزايا أكثر. عادةً يتمّ تخزين ملفات gzip باستخدام اللاحقة .gz، تستطيع ضغط الملفّات باستخدام gzip بكتابة الأمر التالي: gzip sourcefileسيقوم هذا الأمر بضغط الملف وتغيير اسمه إلى "sourcefile.gz "على جهازك. إن كنت ترغب بضغط المجلد كاملاً عندها تستطيع تمرير العَلَم –r داخل الأمر كما يلي: gzip -r directory1سيقوم هذا الأمر بالتحرك داخل المجلد وضغط كل ملف على حدا، وهو عادةً شيء غير مفضل ويمكن الحصول على نتيجة أفضل بأرشفة المجلد ومن ثم ضغط الملف الناتج ككل، والتي سنقوم بشرح كيفية عملها قريباً. لإيجاد المزيد من المعلومات حول الملف المضغوط تستطيع تستطيع استخدام العَلَم –l والذي سيقوم بإعطائك بعض الإحصائيات: gzip -l test.gz compressed uncompressed ratio uncompressed_name 5133 14073 63.7% test إذا كنت ترغب بتمرير النّتيجة إلى أداة أخرى بإمكانك إخبار gzip أن يرسل الملف المضغوط إلى مخرج معياري باستخدامك العَلَم –c، سنقوم في هذا المثال ببساطة بتمريره مباشرة إلى ملف آخر: gzip -c test > test.gzبإمكانك ضبط إعدادات الضّغط الأمثل بتمرير علم على شكل رقم في المجال بين الـ 1 والـ 9، العَلَم -1 (يملك Alias المُسمّاة --fast) يُمثّل الطّريقة الأسرع ولكن الأقل تَعمُّقًا في الضّغط، أمّا العَلَم -9 (والـ alias الخاص به هو --best) يمثل الطريقة الأبطأ والأكثر تعمّقًا في الضّغط، إن الخيار الافتراضي هو -6 والذي يشكل أساس متوسط جيد. gzip -9 compressmeلكي تقوم بفك ضغط ملف ببساطة تمرّر العَلَم –d إلى الأمر gzip (يوجد أيضاً عدّة alias مثل gunzip ولكنها تقوم بنفس الفعل): gzip -d test.gz 2- الضّغط بأداة bzip2Bzip2 هي صيغة وأداة شائعة أخرى للضغط، وفي حين أنّها إلى حدٍّ ما أحدث من gzip، حيث تم تقديمها لأول مرة في عام 1996م، إلا أنه تم تنفيذ bzip2 بشكل واسع لتكون البديل التقليدي لـ gzip. بينما يعتمد gzip على خوارزمية "DEFLATE" فإنّ bzip2 هو تنفيذ لخوارزمية تدعى "Burrows-Wheeler algorithm"، ينتج عن هذا الاختلاف في المنهجية مجموعة من نقاط القوة والضعف والتي هي مختلفة تمامًا عن gzip، إنّ أهم شيء يجعل المستخدم يتنازل عن بعض الميزات للحصول على ميزات أخرى هي معدّل الضّغط العالي مقابل وقت أطول لعملية الضّغط، تستطيع أداة bzip2 إنشاء ملفات مدمجة بشكل كبير أكثر من gzip ولكنّها تأخذ وقتًا أطول لتحقيق هذه النتائج نظرًا لوجود خوارزمية أكثر تعقيدًا. لحسن الحظ فإنّ وقت فك الضّغط لا يتأثر بشكل كبير كوقت الضّغط، لذلك ربما يكون من المفيد توزيع الملفّات باستخدام صيغة bzip2 حيث أنّك فقط ستعاني خلال وقت عملية ضغطه وسيكون بإمكانك توزيع ملفات ذات حجم أصغر والتي يمكن فك ضغطها خلال وقت معقول، طبعاً لا يزال وقت فك الضّغط أطول بكثير من صيغة gzip ولكن ليس له تأثير كبير على عملية الضّغط. لا بدّ أيضًا أن نبقي في ذهننا أنّ استهلاك الذاكرة أكبر من gzip، لن يؤثر هذا على معظم الأجهزة ولكن على بعض الأجهزة الصغيرة المدمجة ممكن أن يؤثر هذا على خياراتك، بإمكانك أن تختار تمرير العَلَم –s والذي سينقص حجم الذاكرة المطلوبة تقريبًا إلى النصف، ولكن سيقودك هذا أيضًا إلى معدّل ضغط أقل. يتم إعطاء الملفّات المضغوطة بهذه الآلية لاحقة الملفّات .bz2 بشكل عام. لكي تقوم بإنشاء ملف مضغوط باستخدام bzip2 بإمكانك ببساطة كتابة ما يلي: bzip2 afileسيقوم هذا الأمر بضغط الملف وإعطائه الاسم "afile.bz2". وكما ذكرنا سابقًا تستطيع تمرير العَلَم –s للدلالة على أن الأداة المساعدة يجب أن تعمل في وضع الذاكرة المُخَفَضّة ، لن يقوم هذا بالضّغط بشكل جيد ولكنّه لن يتطلب الكثير من الموارد: bzip2 -s afileبينما تقوم bzip2 بتطبيق الأعلام المرقمة numbered flags إلّا أنها تعني شيئًا مختلفًا عمّا تعنيه في gzip، حيث تمثّل الأعلام المرقّمة هنا حجم الكتلة block size التي تنفّذ الأداة المساعدة ضغطها ، لذلك يعدّ هذا كوسيلة قياس للذاكرة المستخدمة مقابل حجم الملف المضغوط أكثر منه الوقت مقابل حجم الملف المضغوط، إنّ السلوك الافتراضي هو العَلَم -9 والذي يعني استخدامًا أعلى للذاكرة (نسبيًا) مع معدّل ضغط أعلى: bzip2 -1 fileلنتمكن من فك ضغط ملف مضغوط باستخدام bzip2 نقوم بتمرير العَلَم –d كما يلي: bzip2 -d file.bz2سيعطينا هذا ملفًا غير مضغوط اسمه "file". 3- الضّغط باستخدام xzآلية الضّغط باستخدام xz هي الوافد الجديد نسبيًا على الساحة ، تمّ إطلاق هذه الأداة لأول مرة عام 2009م واكتسبت متابعة بشكل ثابت منذ ذلك الحين. تستفيد أدوات الضّغط باستخدام xz من خوارزمية الضّغط المعروفة باسم "LZMA2" ، تمتلك هذه الخوارزمية معّدل ضغط عالٍ أكثر من المثالين السابقين ، والذي يجعل منها صيغة جيدة عندما تحتاج إلى تخزين البيانات على مساحة محدودة من القرص حيث تقوم بإنشاء ملفات أصغر حجمًا. طبعًا يأتي هنا موضوع التكلفة مرة أخرى في معظم نفس المجالات التي تعاني منها bzip2 ، فبينما يكون الملف الذي تنتجه طريقة xz أصغر حجمًا من الأدوات الأخرى إلّا أنّها تأخذ بشكل كبير وقتًا أطول للقيام بالضّغط ، فعلى سبيل المثال عندما نستخدم أعلام الضّغط بمعدّل عالٍ على ملف ذو حجم كبير فإنّ gzip يحتاج تقريبًا حوالي نصف دقيقة ، وbzip2 يحتاج تقريبًا حوالي دقيقة ، أمّا xz ربما تحتاج حوالي 4 أو 5 دقائق. تتلقى أدوات الضّغط باستخدام xz ضربة أيضًا في متطلبات الذاكرة التي تحتاجها ، تصل أحيانًا إلى حجم أكثر من الطرق الأخرى ، ربّما لا تكون هذه مشكلة بالنسبة لك إن كنت على نظام يملك ذاكرة وافرة ، ولكن يجب أن تأخذ هذا الموضوع بعين الاعتبار. بينما يكون وقت الضّغط أطول من المرغوب به ، فإنّ وقت فكّ الضّغط جيّد نسبيًا رغم أنّه لا يقارب gzip بالنظر إلى سرعة فك الضّغط ولكنّه أسرع عادة وبشكل كبير بفك الضّغط من bzip2 ، كما أنّ استهلاك الذاكرة لفك الضّغط ليس هائلًا أيضًا (ولكنّه يبقى مرتفعًا نسبيًا). تجعل هذه المجموعة من المزايا والعيوب من هذه الصّيغة صيغةً جيدةً لتوزيع الملفّات كالبرامج ، سيتوجب عليك مقدمًا أن تعاني في عملية ضغط هذه الملفّات ولكنّ مستهلكي البرامج سيستفيدون كثيرّا ، حيث أنّهم سيملكون ملفاً مدمجاً يتمّ فك ضغطه بسرعة. ومن العيوب غير الملاحظة أيضًا لهذه الصّيغة أنّها ربّما ليست مدعومة على الأنظمة الأقدم نظرًا لحداثة عهدها ، فإن كنت تبحث عن التوافقية العظمى ربّما ستكون مجبرًا بأن تنظر إلى أداة أخرى. تأخذ الملفّات المنشأة بهذه الصّيغة اللاحقة .xz بشكل عام. لكي تقوم بضغط ملف قم باستدعاء الأداة ببساطة من دون أيّة وسائط : xz fileسيقوم هذا الأمر بمعالجة الملف وإنتاج ملف يدعى "file.xz". لكي تعرض إحصائيات statistics عن عمليّة ضغط الملف تستطيع تمرير العَلَم –l على الملف المضغوط كما يلي: xz -l test.xz Strms Blocks Compressed Uncompressed Ratio Check Filename 1 1 5,016 B 13.7 KiB 0.356 CRC64 test.xzإن أردت إرسال خَرْج output عمليّة الضّغط إلى الخَرْج المعياري standard out فبإمكانك الإشارة إلى الأداة المساعدة بذلك عن طريق العَلَم –c، هنا في هذا المثال نستطيع إرسالها مرة أخرى مباشرة إلى ملف: xz -c test > test.xzبالنسبة للأعلام المرقّمة فإنّ xz تستخدم الأرقام الأقل لكي تشير إلى عملية ضغط أسرع، وهي تملك في الواقع العَلَم -0 كالخيار الأسرع، العَلَم -6 هو الافتراضي ويشكل أرضيّة جيدة لأغلب الحالات، أمّا إن كنت ترغب بتوجيه الضّغط إلى الملفّات الأكبر حجمًا تستطيع استخدام أعلامًا ذات أرقام أعلى والتي قد تأخذ وقتًا طويلًا جدًا ولكنّها ستظهر بعض المكاسب. وإن كنت ترغب بمعدّل ضغط أعلى ولا يهمك الوقت أو متطلبات الذاكرة إلخ..، فتستطيع استخدام العَلَم –e والذي يستخدم عملية ضغط بديلة مختلفة وشديدة الفاعلية، يمكن تعديل أداء هذا العَلَم أيضًا باستخدام الأعلام الرقمية معه : xz -e -9 large_fileستستغرق هذه العملية في النهاية وقتًا طويلًا وربّما لن تُقدّم فوائد كبيرة ولكن إن احتجت إلى هذه الوظيفة فالخيار متاح أمامك. لكي تقوم بفك الضّغط عن الملفّات مرّر العَلَم –d مرة ثانية: xz -d large_file.xzسيقوم هذا الأمر بفك ضغط البيانات إلى ملف يدعى "large_file". استخدام أرشفة Tar مع الضّغطفي حين أن أساليب الضّغط الفردية مفيدة بحدّ ذاتها إلّا أنّك في أغلب الأحيان ستجدهم مقترنين مع الصّيغة tar لضغط أرشفة الملفّات، يسمح لنا هذا بالحفاظ على بُنى المجلدات والأذونات إلخ..، للملفات التي نقوم بحزمها. إنّ الأمر tar حريص جدًا وفعليًا على هذه العلاقة، فهو يُضَّمّن أعلام في سطر الأوامر يُمكن استخدامها لاستدعاء أدوات الضّغط المرافقة تلقائيًا بعد أن تتم عمليّة الأرشفة، وكلّ ذلك في خطوة واحدة. 1- استخدام tar مع الصّيغة gzipلإنشاء أرشيف tar والذي يتم ضغطه بأداة gzip تستطيع تمرير العَلَم –z، يشير هذا العَلَم إلى أنّك ترغب باستخدام ضغط بصيغة gzip على الملف المؤرشف، لا تتطلب أعلام tar فعليًا البادئة "-" كما في معظم الأدوات الأخرى، ومن الأساليب الشائعة لإنشاء ملفات مضغوطة مؤرشفة هذا المثال: tar czvf compressed.tar.gz directory1سيقوم هذا الأمر بإنشاء أرشيف (باستخدام العَلَم –c) من المجلد الذي يُدعى "directory1"، حيثُ يُنشئ خَرْجًا مُطوّلًا ويضغط الأرشيف الناتج باستخدام gzip ومن ثُمّ يُعطي الناتج إلى ملف يُدعى "compressed.tar.gz" (وهو ملف tar تم ضغطه). حالما يتم إنشاء الملف نستطيع إلقاء نظرة على محتوياته باستخدام العَلَم –t بدلًا من علم الإنشاء (-c) : tar tzvf compressed.tar.gz drwxr-xr-x demouser/demouser 0 2014-03-19 18:31 directory1/ -rw-r--r-- demouser/demouser 5458 2014-03-19 18:31 directory1/httpd.conf.orig -rw-r--r-- demouser/demouser 2295 2014-03-19 18:31 directory1/nginx.conf.orig -rw-r--r-- demouser/demouser 5458 2014-03-19 18:21 directory1/httpd.confوللقيام بفك ضغط الملف لاحقًا وتوسيع الأرشيف تستطيع استخدام العَلَم –x كما يلي: tar xzvf compressed.tar.gzسيعيد هذا الأمر إنشاء بنية المجلّد في المجلّد الحالي. 2- استخدام tar مع bzip2لاستخدام الأرشفة مع bzip2 قُم باستبدال العَلَم –z (والذي هو خاص بالأمر gzip) بالعَلَم –j، هذا يعني أنّ أمر إنشاء الأرشيف المضغوط سيتم تعديله إلى التالي: tar cjvf bzipcompressed.tar.bz2 directory2مرةً أخرى تستطيع النظر إلى الملفّات المُحتواة في الأرشيف بتمرير العَلَم –t : tar tjvf bzipcompressed.tar.bz2 drwxr-xr-x demouser/demouser 0 2014-03-19 18:31 directory2/ -rw-r--r-- demouser/demouser 5458 2014-03-19 18:31 directory2/httpd.conf.orig -rw-r--r-- demouser/demouser 2295 2014-03-19 18:31 directory2/nginx.conf.orig -rw-r--r-- demouser/demouser 5458 2014-03-19 18:21 directory2/httpd.confتستطيع استخراج الملفّات وبنية المجلد إلى المجلد الحالي بكتابة ما يلي: tar xjvf bzipcompressed.tar.bz23- استخدام tar مع xzأضافت الإصدارات الحديثة من الأداة tar وظيفة مشابهة للضغط باستخدام xz، نستطيع القيام بذلك باستخدام العَلَم –J : tar cJvf xzcompressed.tar.xz directory3ولعرض المعلومات نستخدم نفس الآلية: tar tJvf xzcompressed.tar.xz drwxr-xr-x demouser/demouser 0 2014-03-19 18:31 directory3/ -rw-r--r-- demouser/demouser 5458 2014-03-19 18:31 directory3/httpd.conf.orig -rw-r--r-- demouser/demouser 2295 2014-03-19 18:31 directory3/nginx.conf.orig -rw-r--r-- demouser/demouser 5458 2014-03-19 18:21 directory3/httpd.confنتّبع نفس الأساليب للاستخراج : tar xJvf xzcompressed.tar.xzسيعطيك هذا الأمر بنية المجلد الكامل الخاص بك سليمة كما هي. الخاتمةآمل أنّك تملك الآن معلومات كافية لتتخذ قرارًا مستنيرًا بشأن أي وسيلة ضغط يجب أن تُفضّل في ظروفٍ مختلفة، تمتلك كل مخططات الضّغط التي ناقشناها في هذا المقال نقاط قوة جذّابة اعتمادًا على المتطلبات المحدّدة لحالتك. من الهام الانتباه إلى عيوب الأداء ومشاكل التّوافقيّة التي قد تلازم كلّ واحد من هذه الحلول، يعتمد مدى اهتمامك بهذه المخاوف كلياً على الحواسيب التي تعمل عليها وأيّ نوع من الزبائن يجب أن تدعم، لا يجب أن تعير أغلبية الحواسيب الحديثة اهتمامًا كثيرًا إلى هذه التفاصيل، ولكنّها قد تسبب مشاكل إذا قمت بتطبيق أنواع الضّغط بشكل عشوائي عند التعامل مع حواسيب أقدم. ترجمة -وبتصرّف- للمقال An Introduction to File Compression Tools on Linux Servers لصاحبه Justin Ellingwood.2 نقاط
-
هل صنعت قالب HTML وأحببته لكنّك لم تعرف كيف تُحوّله إلى قالب ووردبريس؟ ليس بعد الآن، ستتعلم في هذا الدرس كيف تقوم بذلك. هل تعلم بأنّ هناك الكثير من المُطوّرين الذين يكسبون رزقهم عن طريق إنشاء قوالب وإضافات ووردبريس (Wordpress) وبيعها؟ وهل تعلم أنّه بإمكان مطوّري ووردبريس الحصول على آلاف الدولارات سنويًَّا من خلال بيع مُنتجاتهم؟ هذا الدّرس مُخصّص لمطوّري الويب، على فرض أن القارئ على اطّلاع (ولو بشكل مُبسّط) بما يتعلّق بلغة PHP وMySQL ومعلومات عامّة عن كيفية تنصيب واستخدام ووردبريس. هذا الدرس جزء من سلسلة تعلم كيفية تطوير قوالب ووردبريس: مقدمة إلى تطوير قوالب ووردبريس: تحويل صفحة HTML إلى قالب ووردبريس (هذا الدرس) التصفيح (Pagination) في قوالب ووردبريس إضافة قوائم التنقل (Navigation Menu) إلى قالب ووردبريس صف وتسجيل ملفات Javascript و CSS في قوالب ووردبريس متطلبات التّشغيل نحتاج إلى تحميل نسخة ووردبريس من الموقع الرسمي ، سنستخدم النّسخة العربية من هذا الرّابط. تحتاج ووردبريس إلى خادوم ويب، سواء كان Apache أو Nginx أو الخادوم المُدمج مع لغة PHP (بإصدار5.4 وما فوق). وتحتاج أيضًا إلى خادوم قواعد البيانات MySQL. لنقم بإنشاء مُجلّد جديد wordpress_tutorials ونضع فيه نسخة ووردبريس النّاتجة عن فكّ ضغط الملف الذي قمنا بتحميله. ملاحظة: يمكن أن تستخدم البرامج المُجهّزة خصّيصًا بخواديم Apache و MySQL مثل MAMP ،WAMP أو XAMPP. مع مُراعاة الاختلاف بين رابط خادوم الويب ومعلومات خادوم MySQL مع ما سنستخدمه في هذا الدّرس. سنقوم باستخدام الخادوم المُدمج مع PHP لتجنّب تنصيب خادوم Apache أو Nginx وتجنب الخوض في الإعدادات الخاصّة بكل واحد منها. لتشغيل الخادوم المُدمج نتوجه باستخدام سطر اﻷوامر إلى المجلّد الذي يحوي نسخة ووردبريس. ثم نكتب أمر: php -S localhost:8000 يتمّ تشغيل خادوم الويب المُدمج مع PHP على الحاسوب، يمكن التّوجّه عن طريق المُتصفّح إلى الرّابط localhost:8000 للتّأكد من أن الخادوم يعمل. تهيئة قالب HTML سنقوم بالاعتماد على قالبٍ قمتُ بإعداده مُسبقاً، يمكن تحميله من هذا الرابط، التّصميم عبارة عن قالب عادي يحوي بضع ملفّات HTML ،CSS و JavaScript. وهو مبني اعتمادًا على إطار عمل Foundation مع بعض التّعديلات والإضافات. هذا القالب تجريبيّ فقط لرؤية كيفية ظهور الشكل العامّ له. نتوجه إلى مجلّد المشروع الذي يحوي ملفات ووردبريس، ومنه نتوجّه إلى مجلد wp-content ثم إلى مُجلّد themes. نقوم بإنشاء مُجلّد اسمه my_theme بمثابة مُجلّد القالب الذي سنقوم بإنشائه. ملفات القالب الأساسية نحتاج إلى وجود ملفّين على الأقل ضمن مجلد القالب الذي أنشأناه، وهما: - style.css - index.php وهذا أقل ما يجب توفّره في القالب ليكون قالبًا صالحًا للاستخدام. نتجه إلى صفحة تغيير القوالب من لوحة تحكم ووردبريس لنرى ما يشبه: كما تلاحظون لا نرى القالب الجديد الذي أنشأناه ضمن القوالب، وذلك ﻷن هناك شيئًا آخر علينا فعله قبل أن نرى القالب الجديد في هذه الصفحة. نحتاج إلى إضافة تعليق في ملف style.css كالتّالي (يمكن تعديل أيّ قيمة أيضًا): /* Theme Name: قالبي الجديد Author: عمار العقاد Author URI: http://aalakkad.me Description: قالب جديد، نقوم من خلاله بالتّدرّب على إنشاء قوالب WordPress. Version: 1.0 */ تقوم ووردبريس بالدخول إلى كل مجلد في مجلد القوالب، ثم تبحث عن ملف style.css بداخله تعليق يشبه التّعليق السابق، ثم تقوم بتفسير هذه التّعليقات ووضعها في صفحة القوالب التي تظهر للمُستخدم من خلالها أسماء وتوصيف القوالب. وهناك تفصيلات أخرى للتعليقات في ملف style.css يمكن الاطلاع عليها كاملة من ملفات التوثيق. يمكن التوجه إلى صفحة القوالب من خلال لوحة التحكم، لنرى شيئًا مُشابهًا لما يلي: لنقم بتفعيل هذا القالب الجديد، ثم نتوجّه إلى الصّفحة الرّئيسية للمُدوّنة (الصفحة التي تُظهر المقالات وليست صفحة لوحة التّحكم). إن كنت تستخدم الخادوم المُدمج مع PHP بالطريقة التي ذكرناها، فيكون رابط الصّفحة الرئيسية هو: localhost:8000. سنرى صفحة بيضاء دون أن تحوي أيّ شيء، وذلك ﻷن القالب ما زال فارغًا تمامًا. سيتغيّر الوضع بعد قليل. نقل قالب HTML إلى قالب ووردبريس ما سنفعله في الخطوة الأولى هو وضع قالب HTML في ملف index.php ثم نقوم بتعديل مسارات ملفات CSS و JavaScript. ستكون جميع الصفحات التي نستخدمها من ووردبريس بعد تفعيل القالب الجديد مُتطابقة، وكأنها قالب HTML نفسه. وهذا هو المطلوب في هذه المرحلة، سنقوم بإضافة التّفاصيل فيما بعد وعلى عدة مراحل. نقوم الآن بنسخ محتوى ملف index.html كاملًا من قالب HTML ونضعه في ملف index.php في قالبنا الجديد my_theme ضمن ووردبريس. ثم ننسخ مجلد assets كما هو إلى داخل مجلد قالبنا الجديد. لنرى كيف أصبح شكل الموقع بعد أن وضعنا محتوى ملف index.html في ملف index.php: يظهر الآن القالب بهذا الشّكل ﻷن ملفات CSS وJavaScript أصبحت في مسار مختلف عن المسار الذي كان موجودًا في قالب HTML. علينا الآن أن نقوم بتعديل مسارات هذه الملفات كي يُصبح شكل قالب ووردبريس الجديد مُطابقًا لشكل قالب HTML. توفّر لنا ووردبريس عددًا من الدّوالّ (functions) مهمتها تسهيل إنشاء القوالب، سنستخدم منها get_template_directory_uri()، تقوم هذه الدالّة بإرجاع قيمة نصّيّة هي رابط القالب. مثلاً، إن كان مجلد القالب هو my_theme ورابط خادوم الويب الذي نعمل عليه هو http://localhost:8000 ستكون نتيجة الدالّة هي: http://localhost:8000/wp-content/my_theme يجب أن نستخدم هذه الدالّة أو ما يشابهها لنحصل على الرّوابط، ولا نستخدم روابط نضعها بشكل يدوي، فيُمكن لرابط خادوم الويب أن يتغير، وإن كانت الروابط موضوعةً بشكل يدوي فسيظهر شكل القالب كما في الأعلى خاليًّا من ملفات CSS و .JavaScript. نقوم بتعديل ملف index.html في قسم head، نبحث عن سطر استدعاء ملفات CSS، ثم نقوم بالتّعديل عليها لتصبح بالشّكل: في قسم head أيضًا نُريد استبدال رابط استدعاء ملف modernizr.js ليستخدم دالّة get_template_directory()، فيُصبح: <script src="<?php echo get_template_directory_uri(); ?>/assets/js/modernizr.js"></script> أخيرًا نبحث في نهاية ملف index.php عن سطر استدعاء ملف JavaScript، ونقوم بالتّعديل عليه ليُصبح كما يلي: <script src="<?php echo get_template_directory_uri(); ?>/assets/js/vendor.js"></script> الآن عندما يتم طلب المُدوّنة من المُتصفّح، ستكون النّتيجة النّهائية للتعديلات الثلاثة التي قمنها بها كالتالي: <link rel="stylesheet" href="http://localhost:8000/wp-content/themes/my_theme/assets/css/main.css"> <script src="http://localhost:8000/wp-content/themes/my_theme/assets/js/modernizr.js"></script> <script src="http://localhost:8000/wp-content/themes/my_theme/assets/js/vendor.js"></script> نذهب الآن إلى الصّفحة الرّئيسية للمُدوّنة لنرى كيف أصبح القالب. في آخر فقرة من هذا الدرس سنقوم بتعديل ترويسة الموقع التي نصّها الحالي هو: "عنوان الموقع"، والذي يظهر في الجُزء العُلويّ. نريد تغيير هذا النصّ ليصبح اسم المدونة التي قمنا بإدخالها أثناء مرحلة التّنصيب، يمكنك تغيير اسم المدونة من لوحة التحكم ثم الإعدادات. لنفتح صفحة index.php في المُحرّر، ثم نبحث عن السطر الذي يحوي: <h1 class="logo">عنون الموقع</h1> ,نقوم باستبداله بما يلي بعض إضافة وسم PHP له: <h1 class="logo"><?php bloginfo('name'); ?></h1> وسم: <?php php bloginfo('name'); ?> يقوم بإظهار/طباعة نصّ يتم جلبه من قاعدة البيانات، النصّ هو اسم المُدوّنة. نلاحظ أن الدّالّة bloginfo() تقوم بالإظهار وليست الإرجاع return كما تفعل دالّة ()get_template_directory_uri. الآن عندما نتوجّه إلى الصفحة الرئيسية للمدونة تكون الترويسة شبيهة بالصورة: فصل محتوى الملفات من قواعد البرمجة الهامة إلغاء التّرابط أو الفصل (decoupling)، فنحاول فصل العناصر المُترابطة قدر الإمكان ووضعها في ملفات مُنفصلة. مثلًا سنقوم لاحقًا بإنشاء صفحة خاصّة لعرض المواضيع المُنفردة، وستحتاج تلك الصّفحة إلى وجود الترويسة (header) والتذييل (footer) كي تحوي ملفات CSS و JavaScript وتكون متناغمة مع باقي القالب. توفّر لنا ووردبريس عدة طُرق لإلغاء التّرابط في الملفات، إمّا أن يتم استخدام التّسلسل الهرمي لملفّات القالب (theme hierarchy) أو يتم استخدام قِطَع القالب (template parts). التّسلسل الهرمي لملفّات القالب (أو ملفات القالب للاختصار) هي ملفات بأسماء ثابتة، تقوم ووردبريس باستخدام الملف المُتوفّر منها حسب الطلب الذي يأتيها من المتصفح؛ مثلاً طلبتَ من المدونة رابط مقالٍ معيّن، تقوم ووردبريس بتحليل الطّلب ومعرفة أن المطلوب هو مقال، فتبحث عن ملف باسم single.php، إن كان موجودًا يتمّ استخدامه، إن لم يكن موجودًا تبحث ووردبريس عن ملف index.php. وهكذا الأمر بالنسبة لجميع الطلبات. أما قِطع القالب، فهي ملفات يقوم المستخدم بإنشائها دون أن يلتزم باستخدام أسماء مُحدّدة كما في ملفات القالب. ثم يقوم المطوّر باستخدام هذه القِطع في أي مكان يريده ضمن القالب. يقوم المُطوّر مثلًا بإنشاء قطعة مُخصّصة لعرض أزرار المُشاركة، يقوم بتسمية الملف: sharing.php، ويضع فيه الوسوم التي يُريدها. ثم يقوم باستدعاء هذا الملف في الصّفحة الرّئيسيّة index.php وصفحة المقال المُنفرد single.php على النّحو التّالي: <?php get_template_part('sharing'); ?> هناك تفصيلات حول كيفية إنشاء قطع القالب والتّعامل معها، ما سنذكره هنا فقط لإعطاء فكرة عامة عنها وليس لشرحها بالتّفصيل. سنستخدم في هذا الدرس التّسلسل الهرمي فقط لسهولته وشهرته. إن كان الاسم غريبًا بالنّسبة إليك فستألفه بمُجرد أن تشرع في استخدامه. سنقوم بإنشاء 3 ملفّات في القالب هي: - header.php - footer.php - sidebar.php ومن ثم يمكننا استخدام هذه الملفّات في أي مكان ضمن القالب عن طريق الدّوال: - get_header() - get_footer() - get_sidebar() هذه الدّوال تعمل بشكل مُشابه لـ require التّي نعرفها في لغة PHP. بهذه الطّريقة لن نحتاج إلى القيام بالنّسخ واللصق في كل مرة نريد إدراج الترويسة في ملفات القالب، وفي حال أردنا تعديل شيء في الترويسة فلن نضطرّ إلى تطبيق التعديل في جميع ملفات القالب. الخطوة التّالية هي نقل المحتوى المُناسب لكل ملفّ من الملفّات السّابقة من ملف index.php إلى الملفّات الثّلاثة الجديدة التي أنشأناها. سنقوم حرفيًا بالنّسخ واللّصق من ملف index.php إلى الملفات الثّلاثة، ثم نقوم بوضع إحدى الدّوال الثلاثة في ملف index.php بدل النصّ الذي قمنا باقتصاصه. ملف الترويسة header.php نقوم باقتصاص مُحتوى ملف index.php من بدايته وحتى نهاية وسم </header> في السطر 57. نضع ما اقتصصناه في ملف header.php. ثم نضع مكان الاقتصاص في ملف index.php ما يلي: <?php get_header(); ?> فتصبح بداية ملف index.php مشابهةً لما يلي: <?php get_header(); ?> <div class="main-content"> <div class="row"> ملف التذييل footer.php نقوم الآن باقتصاص الجزء الخاص بالتذييل من ملف index.php، في السطر 71 بدءاً من وسم: <div class="site-footer"> وحتى نهاية الملف. نقوم بوضع المُحتوى في ملف footer.php، ثم نستبدل مكان الوسوم المقصوصة في ملف index.php بما يلي: <?php get_footer(); ?> ملف الشريط الجانبي sidebar.php الوسوم الخاصّة بالشريط الجانبي ما هي إلا أربعة أسطر، تبدأ من السطر 64، المحتوى هو: <div class="large-4 columns sidebar"> <div class="card"> Sidebar </div> </div> نقوم بنقل المحتوى السّابق من ملف index.php إلى ملف sidebar.php، ونضع مكانه في ملف index.php: <?php get_sidebar(); ?> بهذا ننتهي من المرحلة الأولى من إلغاء الترابط بين الوسوم، وضعنا كل جزءٍ منها في ملفٍّ خاصٍّ به، وكلما أردنا استخدام ذلك الجزء نقوم باستدعاء الدّالّة المناسبة لذلك. أصبح ملف index.php أقصر طولًا، ويؤدّي نفس الغرض الذي كان يؤدّيه قبل أن نقوم بالتّعديلات، محتوى الملف كالتالي: <?php get_header(); ?> <div class="main-content"> <div class="row"> <div class="large-8 right columns news"> <div class="row"> <div class="medium-12 columns"> <article class="card"> <header> <h1>Post title</h1> </header> <div class="date">4 كانون الأول 2014</div> <p>خلافاَ للاعتقاد <a href="#">السائد</a> فإن لوريم إيبسوم ليس نصاَ عشوائياً، بنذ العام 45 قبل الميلاد، مما يجعله أكثر من 2000 عام في القدم. قام البروفيسور "ريتشارد ماك لينتوك" (Richard McClintock) وهو بروفيسور اللغة اللاتينية في جامعة هامبدن-سيدني في فيرجينيا بالبحث عن أصول كلمة لاتينية غامضة في نص لوريم إيبسوم وهي "consectetur"، وخلال تتبعه لهذه الكلمة في الأدب اللاتيني اكتشف المصدر الغير قابل للشك. فلقد اتضح أن كلمات نص لوريم إيبسوم تأتي من الأقسام 1.10.32 و 1.10.33 من كتاب "حول أقاصي الخير والشر" (de Finibus Bonorum et Malorum) للمفكر شيشيرون (Cicero) والذي كتبه في عام 45 قبل الميلاد. هذا الكتاب هو بمثابة مقالة علمية مطولة في نظرية الأخلاق، وكان له شعبية كبيرة في عصر النهضة. السطر الأول من لوريم إيبسوم "Lorem ipsum dolor sit amet.." يأتي من سطر في القسم 1.20.32 من هذا الكتاب.</p> <div class="read-more text-left"> <a href="#">تابع قراءة المقال »</a> </div> <footer class="tags"> <span class="label">تقني</span> <span class="label">تنمية</span> <span class="label">منوعات</span> </footer> </article> </div> <div class="medium-12 columns"> <article class="card"> <header> <h1>Post title</h1> </header> <div class="date">4 كانون الأول 2014</div> <p>خلافاَ للاعتقاد <a href="#">السائد</a> فإن لوريم إيبسوم ليس نصاَ عشوائياً، بنذ العام 45 قبل الميلاد، مما يجعله أكثر من 2000 عام في القدم. قام البروفيسور "ريتشارد ماك لينتوك" (Richard McClintock) وهو بروفيسور اللغة اللاتينية في جامعة هامبدن-سيدني في فيرجينيا بالبحث عن أصول كلمة لاتينية غامضة في نص لوريم إيبسوم وهي "consectetur"، وخلال تتبعه لهذه الكلمة في الأدب اللاتيني اكتشف المصدر الغير قابل للشك. فلقد اتضح أن كلمات نص لوريم إيبسوم تأتي من الأقسام 1.10.32 و 1.10.33 من كتاب "حول أقاصي الخير والشر" (de Finibus Bonorum et Malorum) للمفكر شيشيرون (Cicero) والذي كتبه في عام 45 قبل الميلاد. هذا الكتاب هو بمثابة مقالة علمية مطولة في نظرية الأخلاق، وكان له شعبية كبيرة في عصر النهضة. السطر الأول من لوريم إيبسوم "Lorem ipsum dolor sit amet.." يأتي من سطر في القسم 1.20.32 من هذا الكتاب.</p> <div class="read-more text-left"> <a href="#">تابع قراءة المقال »</a> </div> <footer class="tags"> <span class="label">تقني</span> <span class="label">تنمية</span> </footer> </article> </div> </div> <div class="row"> <div class="medium-12 columns"> <ul class="pagination"> <li class="arrow unavailable"><a href="">«</a></li> <li class="current"><a href="">1</a></li> <li><a href="">2</a></li> <li><a href="">3</a></li> <li><a href="">4</a></li> <li class="unavailable"><a href="">…</a></li> <li><a href="">12</a></li> <li><a href="">13</a></li> <li class="arrow"><a href="">»</a></li> </ul> </div> </div> </div> <?php get_sidebar(); ?> </div> </div> <?php get_footer(); ?> جلب المقالات من قاعدة البيانات نحتاج الآن إلى عرض المقالات المحفوظة في قاعدة البيانات (والتي يتم التّحكم فيها من لوحة التّحكم الخاصّة بووردبريس)، سنقوم بعرضها في ملف index.php وفي دروس لاحقة سنستخدم نفس طريقة عرض المقالات في باقي ملفات القالب، سواءً في ملف single.php أو في archive.php أو في غيرها. ضمن ملف index.php نجد أن كل مقال مُحاط بالوسوم: <div class="medium-12 columns"> <article class="card"> كل مقال يجب أن يبدأ بهذه الوسوم، وينتهي بإغلاق هذه الوسوم. نلاحظ أن قالب HTML يحوي مقالين شكليين، سنحذف واحدًا منها ونكتفي بالآخر لنقوم باستخدامه كمعيار لعرض المقالات مثله. نحيط وسوم بداية المقال بالحلقة الرّئيسية التي تكلّمنا عنها سابقًا، فتُصبح الوسوم كما يلي: <?php while(have_posts()) { the_post(); ?> <div class="medium-12 columns"> <article class="card"> وبعد إغلاق الوُسوم التي بدأ المقال عندها نضع نهاية الحلقة (قوس إغلاق الحلقة) كما يلي: </article> </div> <?php } ?> إن قمنا بحفظ التّعديلات والتجربة، سنجد أن المقال الشّكليّ سيتكرّر بعدد المقالات الموجودة في قاعدة بيانات ووردبريس لدينا. لكن جميع المقالات ستكون بنفس الشّكل وبنفس المُحتوى. سنقوم الآن باستبدال المُحتوى الشّكليّ بالمُحتوى المُناسب من قاعدة البيانات حسب كل مقال. تقدم ووردبريس دالّة the_title لطباعة عُنوان المقال الحالي، سنستخدمها بدل عنوان المقال الشّكلي، فتصبح الوسوم كما يلي: <h1><?php the_title();?></h1> وبنفس الطريقة نستخدم دالّة the_date لعرض تاريخ نشر المقال كما يلي: <div class="date"><?php the_date();?></div> ثم لعرض محتوى المقال نستخدم دالّة the_content بدل وسم <p></p> الذي يحوي المحتوى الشكليّ، كما يلي: <p><?php the_content();?></p> يُمكن أن نقوم بحفظ التّعديلات على الملف ومشاهدة النّتيجة في المُتصفّح لنتأكد من أن التّعديلات التي قمنا بها تم تطبيقها وتعرض النّتيجة الصّحيحة. بقي لدينا تعديلان مُشابهان لما قمنا به، الأول لتعديل رابط “تابع قراءة المقال” والثاني لعرض الوسوم الخاصّة بالمقال. لتعديل رابط المقال نستخدم دالّة the_permalink التي وظيفتها عرض رابط الويب الخاصّ بالمقال، لكن لا تقوم الدّالّة سوى بطباعة الرّابط دون وضعه في وسم <a></a> كي يصبح قابلًا للنّقر والاستخدام. علينا إذًا وضع الرّابط في مكانه المُناسب كما يلي: <a href="<?php the_permalink();?>">تابع قراءة المقال »</a> قمنا باستبدال قيمة حقل href="#" بدالّة طباعة رابط المقال. الآن أصبح بإمكاننا مُشاهدة الصّفحة الرّئيسيّة للقالب التي تعرض المقالات ويمكن الضّغط على رابط “تابع قراءة المقال” للوصول إلى المقال بعينه ضمن صفحة مُستقلّة. بقي الآن أن نعرض الوسوم الخاصّة بكل مقال. مكان الوسوم هو داخل وسم: <footer class="tags"> </footer> سنقوم باستخدام دالّة wp_get_post_tags التي مهمتها إرجاع مصفوفة تحوي جميع الوسوم الخاصّة بالمقال على شكل كائنات (Objects) وليس مُجرّد نصّ عادي. وعليه فإنه سيكون بإمكاننا الوصول إلى اسم كل وسم عن طريق: tag->name$ كما يلي: <footer class="tags"> <?php $tags = wp_get_post_tags(get_the_ID()); foreach($tags as $tag) { echo '<span class="label"> ' . $tag->name . '</span> '; } </footer> يُمكننا الآن استعراض المقالات في الصّفحة الرّئيسية للمُدوّنة والوصول إلى كل مقال عن طريق الرّابط الخاص به ورؤية الوسوم الخاصّة بكل مقال أيضًا. سنتوقف هنا في هذا الدرس كي لا تكون المعلومات كثيفة يصعب استيعابها، وسنتابع في دروس أخرى استخدام أرقام الصّفحات في الأسفل بشكل صحيح. (يمكن الآن إضافة تعليق حول وسوم الصفحات كي لا تظهر بشكل خاطئ وبدون روابط صحيحة). خلاصة تعلّمنا في هذا الدّرس كيف نقوم بتجهيز قالب HTML ليُصبح قالبَ ووردبريس، وكيف نُعدّل مسارات ملفات JavaScript وCSS لتُصبح متناغمةً مع رابط الويب الخاص بقالب ووردبريس. وفي القسم الثاني من الدرس تعلّمنا كيف نقوم بفصل المحتوى عن ملف index.php إلى ملفّات فرعية أخرى، لنقوم بإعادة استخدامها في أي ملف ضمن القالب. وفي القسم الأخير رأينا كيف يمكن جلب المقالات من قاعدة البيانات وإظهارها للمُستخدم مع عرض الوسوم الخاصّة بكل مقال. أرجو أن يكون الدرس سهلاً بسيطاً، في حال وجود أي استفسار أو مداخلة نرحّب به في التعليقات.1 نقطة
-
تحدثنا في الدرس السابق مُقدّمة إلى تطوير قوالب ووردبريس حول إنشاء قالب ووردبريس بسيط، واليوم سنقوم بإكمال العمل عليه لعرض أرقام الصفحات أو عرض رابطيّ السابق والتالي للتنقل بين الصفحات والوصول إلى جميع المقالات ضمن المدوّنة. عند وجود عدد كبير من المقالات في المدوّنة، فلن يتم عرضها جميعاً في صفحة واحدة، بل يتم تقسيمها على عدد من الصفحات، بشكل افتراضي يتم عرض 10 مقالات في الصفحة الرئيسية أو الأرشيف (تصنيف أو وسم)، ويمكن تغيير رقم المقالات في الصفحة الواحدة من لوحة التحكم. فهرس السلسلة: مقدمة إلى تطوير قوالب ووردبريس: تحويل صفحة HTML إلى قالب ووردبريس التصفيح (Pagination) في قوالب ووردبريس (هذا الدرس) إضافة قوائم التنقل (Navigation Menu) إلى قالب ووردبريس صف وتسجيل ملفات Javascript و CSS في قوالب ووردبريس Pagination تقدّم ووردبريس دالّة مخصّصة لعرض أرقام الصفحات هي ()paginate_links. سنقوم بالاطلاع على كيفية استخدامها وخياراتها، وننوه بوجود طرق أخرى لعرض أرقام الصفحات، مثل إضافة WP-PageNavi. يتم استخدام الدالّة بهذه الطريقة: <?php echo paginate_links($args);?> حيث متحول args$ هو مصفوفة تحوي إعدادات مخصصة لهذه الدالّة، يمكن أن نستخدم الإضافة دون تمرير هذا المتحول، أو يمكن أن تكون قيمة هذه المتحول هي بعض من الإعدادات الخاصة بالدالّة وليس جميعها. الإعدادات الكاملة هي كالتالي بقيمها الافتراضية: <?php $args = array( 'base' => '%_%', 'format' => '?page=%#%', 'total' => 1, 'current' => 0, 'show_all' => False, 'end_size' => 1, 'mid_size' => 2, 'prev_next' => True, 'prev_text' => __('« Previous'), 'next_text' => __('Next »'), 'type' => 'plain', 'add_args' => False, 'add_fragment' => '', 'before_page_number' => '', 'after_page_number' => '' ); ?> يمكننا أن نضع بعض هذه الإعدادات في المتحول، وتقوم ووردبريس بمعالجة الإعدادات التي نقدّمها للدالّة، بحيث تضيف للإعدادات المُدخلة ما يكملها من الإعدادات الافتراضية. سنقوم الآن باستخدام هذه الدالّة ورؤية كيف تظهر الروابط دون وجود إعدادات للدالّة، نضع ما يلي في نهاية ملف index.php فيصبح: <div class="row"> <div class="medium-12 columns"> <?php echo paginate_links(); ?> </div> </div> </div> <?php get_sidebar(); ?> عندما نقوم بزيارة الصفحة الرئيسية للمدونة، نجد أن روابط أرقام الصفحات تظهر بشكل مشابه لهذه الصورة: سنرى في الفقرة التالية كيف يمكن تخصيص ظهور هذه الروابط. إضافة Style جديد سنحتاج إلى إضافة Style جديد إلى القالب الذي نقوم باستخدامه، وذلك لكي تظهر أرقام الصفحات بشكل يتناسب مع باقي القالب. قد يتبادر للذهن في البداية أن يتم استخدام النسخ واللصق لإضافة Style جديد إلى ملف css الرئيسي. رغم أن هذا ممكن ويؤدي الغرض المطلوب، إلا أن الطريقة الأفضل هي استخدام دالّة تدعى wp_enqueue_style. 1. إضافة دالّة ()wp_head إلى ملف header.php قبل إغلاق وسم </head> نقوم بإضافة السطر التالي: <?php wp_head();?> وهي دالّة مهمة جداً في أي قالب ووردبريس، حيث تقوم ووردبريس (والعديد من الإضافات) باستخدام هذه الدالّة سواءً لإضافة ملفات الشكل (CSS) أواستدعاء ملفات جافاسكريبت أو حتى إضافة وسوم إضافية تتعلق بـ SEO. قمنا بإضافة دالّة wp_head ﻷننا نريد استخدام دالّة ()wp_enqueue_style التي ستقوم بإدراج وسم HTML لاستيراد ملف CSS جديد. 2. إضافة ملف CSS الجديد نقوم بإنشاء ملف جديد هو custom.css، وهو الذي سنقوم باستدعاءه من خلال دالّة ()wp_enqueue_style. نقوم بنسخ ولصق محتوى هذا الرابط ونضعه ضمن ملف custom.css الذي أنشأناه، وهو ما سيقوم بإضافة الشكل المناسب ﻷرقام الصفحات في القالب. 3. استخدام دالّة ()wp_enqueue_style لنقم بفتح ملف functions.php من ملفات القالب، ولنضف عليه ما يلي: // Enqueue custom style add_action('wp_enqueue_scripts', function() { wp_enqueue_style('custom-pagination', get_template_directory_uri() . '/custom.css'); }); ما قمنا بفعله هو أننا أخبرنا ووردبريس أن تنفذ دالّة ()wp_queue_style عند وصول دورة تنفيذ ووردبريس إلى الحدث (action) المُسمّى wp_enqueue_scripts وهو المسؤول عن ترتيب وتنسيق وطباعة ملفات جافاسكريبت و CSS وتحليل متطلبات كل ملف -إن وجدت له متطلبات-، وفي النهاية يتم استخدام الملف/الملفات المطلوبة بعد أن يتم طلب جميع متطلباتها. الآن إن قمنا بفتح المصدر الخاص بالصفحة الرئيسية من المتصفح، نجد أن المصدر أصبح يحوي شيئاً مشابهاً لما يلي: <link rel='stylesheet' id='custom-pagination-css' href='http://localhost:8000/wp-content/themes/my_theme/custom.css?ver=4.1' type='text/css' media='all' /> وهو استدعاء ملف CSS خاص، الذي أردنا وجوده قبل البدء بعرض إرقام الصفحات. لننظر الآن كيف تبدو أرقام الصفحات: أجمل بكثير من سابقتها أليس كذلك؟ شرح إعدادات دالّة paginate_links كما أسلفنا، يمكن أن نمرر جزءًا من الإعدادات ويمكن ألا نمرر أي شيء على الإطلاق، فتقوم ووردبريس باستخدام الإعدادات الافتراضية التي أوردناها في الأعلى. base (القيمة اختيارية)، نوعها سلسلة نصيّة. القيمة الافتراضية: %_% تُستخدم للإشارة إلى الرابط، الذي سيتم استخدامه لإنشاء روابط الصفحات. في رابط مثل: http://example.com/all_posts.php%_% يتم استبدال القيمة الافتراضية: %_% بقيمة format التي سنتحدث عنها في الفقرة التالية. format (القيمة اختيارية)، نوعها سلسلة نصيّة. القيمة الافتراضية: ?page=%#% تُستخدم كهيكل للصفحات. في حال كنا نريد أو كنا نستخدم عناوين نظيفة (pretty permalinks) ستكون القيمة هي /page/%_%، حيث تعبير %_% يتم استبداله برقم الصفحة. total (القيمة اختيارية)، نوعها رقميّ. القيمة الافتراضية: 1 مجموع عدد الصفحات، عند استخدام دالّة ()paginate_links داخل حلقة ووردبريس، تكون القيمة الافتراضية تساوي خاصّية max_num_pages$ في WP_Query. current (القيمة اختيارية)، نوعها رقميّ. القيمة الافتراضية: 0 رقم الصفحة الحالية. show_all (القيمة اختيارية)، نوعها قيمة منطقية (true أو false). القيمة الافتراضية: false إذا كانت القيمة true عندها سيتم إظهار جميع الصفحات بدلاً من قائمة قصيرة من الأرقام المجاورة لرقم الصفحات الحالية. بشكل افتراضي هذا الخيار تكون قيمته false ويتم التحكم به عن طريق الخيارين end_size و mid_size. end_size (القيمة اختيارية)، نوعها رقميّ. القيمة الافتراضية: 1 عدد الأرقام عند بداية ونهاية أطراف القائمة. mid_size (القيمة اختيارية)، نوعها رقميّ. القيمة الافتراضية: 2 عدد الأرقام على جانبيّ الصفحة الحالية، (مع ملاحظة أن الرقم لا يشمل الصفحة الحالية). prev_next (القيمة اختيارية)، نوعها قيمة منطقية (true أو false). القيمة الافتراضية: true لتحديد إن كنا نريد روابط التالي والسابق أن يتم استخدامها في القائمة أم لا. prev_text (القيمة اختيارية)، نوعها سلسلة نصّية. القيمة الافتراضية: __('« Previous') حيث __() هي دالّة مسؤولة عن الترجمة. نص رابط الصفحة السابقة، تعمل فقط إن كان الخيار السابق (prev_next) فعّالاً (قيمته true). next_text (القيمة اختيارية)، نوعها سلسلة نصّية. القيمة الافتراضية: __('Next »') حيث __() هي دالّة مسؤولة عن الترجمة. نص رابط الصفحة التاية، تعمل فقط إن كان خيار (prev_next) فعّالاً (قيمته true). type (القيمة اختيارية)، نوعها سلسلة نصّية. القيمة الافتراضية: ‘plain’ تتحكم بشكل القيمة التي تقوم الدالّة بإرجاعها. القيمة الممكنة هي: plain: تكون القيمة التي يتم ارجاعها عبارة عن سلسلة نصّية مؤلفة من روابط مفصول بينها بمحرف السطر الجديد. array: تكون القيمة التي يتم ارجاعها عبارة عن مصفوفة من روابط الصفحات لتوفّر تحكم كامل بكيفية الظهور. list: تكون القيمة التي يتم ارجاعها عبارة عن قائمة HTML غير مرتّبة (ul). add_args (القيمة اختيارية)، نوعها مصفوفة. القيمة الافتراضية: false مصفوفة اسمية من المحددات ليتم إضافتها إلى الرابط، تكون المصفوفة على شكل: اسم => قيمة. add_fragment (القيمة اختيارية)، نوعها سلسلة نصيّة. القيمة الافتراضية: لا يوجد قيمة. نص لتتم إضافته إلى نهاية كل رابط بشكل مباشر (يمكن تمرير متحولات GET عن طريق هذا الخيار، بشكل يشبه خيار add_args لكن على شكل سلسلة نصية بدلاً من مصفوفة). before_page_number (القيمة اختيارية)، نوعها سلسلة نصيّة. القيمة الافتراضية: لا يوجد قيمة. نص ليتم إظهاره قبل كل رقم صفحة (النص وليس الرابط). after_page_number (القيمة اختيارية)، نوعها سلسلة نصيّة. القيمة الافتراضية: لا يوجد قيمة. نص لتتم إضافته بعد رقم الصفحة (النص وليس الرابط). أزرار التالي والسابق قد يفضّل البعض استخدام أزرار "التالي" و"السابق" بدلاً من أرقام الصفحات، أو ربما يتطلب القالب الذي يعملون عليه هذه الأزرار. تقدّم ووردبريس دالّة واحدة لعرض الرابطين معاً (التالي - السابق) هي: posts_nav_links. لنقم بوضع هذه الدالّة بدلاً من دالّة إظهار أرقام الصفحات التي تحدثنا عنها سابقاً: <?php posts_nav_link(); ?> يصبح القالب بهذا الشكل: يمكن أن تأخذ الدالّة ثلاثة محددات كلها اختيارية، هي: sep$: (سلسلة نصية)، يمثل النصّ المعروض بين الرابطين. القيمة الافتراضية: ' — ' prelabel$: (سلسلة نصية)، اسم رابط الصفحة السابقة. القيمة الافتراضية: '« Previous Page' nxtlabel$: (سلسلة نصية)، اسم رابط الصفحة التالية. القيمة الافتراضية: 'Next Page »' لنقم معاً بتعديل هذه الإعدادات لتصبح كالتالي: <?php posts_nav_link(' - ', '« السابق', 'التالي »'); ?> تظهر لنا التعديلات في القالب كما يلي: ما رأيكم لو نختم الدرس بخدعة بسيطة، نقوم من خلالها بجعل روابط التالي السابقة تظهر بشكل مشابه لأرقام الصفحات؟ سأخبركم بتلميح: تكمن الخدعة بالاستفادة من المحدد الأول sep$. لنضع في البداية وسم ul محيطاً بدالّة ()posts_nav_links يأخذ نفس صنف CSS الموجود في أرقام الصفحات كما يلي: <ul class="page-numbers"> <?php posts_nav_link(' - ', '« السابق', 'التالي »'); ?> </ul> الآن نريد إحاطة كِلا الرابطين بوسم li لكل رابط، يمكن أن نضع داخل وسم ul بداية وسم li ونضع قبل إغلاق وسم ul وسم إغلاق وسم li، فيصبح المصدر كالتالي: <ul class="page-numbers"> <li> <?php posts_nav_link(' - ', '« السابق', 'التالي »'); ?> <li> </ul> ما فعلناه حتى الآن أننا أحطنا كلا الرابطين بوسم li واحد، لكننا نريد أن نحيط كل واحد من الرابطين بوسم مستقلّ، سنقوم باستبدال المحدد الأول $sep بـ: </li><li>. بما أن محتوى هذا المحدد سيكون بين الرابطين بشكل دائم، فسنضع فيه إغلاق وسم li الأول يليه بداية وسم li الثاني. فيصبح المصدر: <ul class="page-numbers"> <li> <?php posts_nav_link('</li><li>', '« السابق', 'التالي »'); ?> <li> </ul> يصبح شكل الروابط كالصورة التالية: خلاصة تعرّفنا خلال الدرس على كيفية إضافة أرقام الصفحات أو روابط التالي-السابق بحيث يتم استخدامها للتنقل بين صفحات الموقع. كما تعرفنا بشكل بسيط على كيفية إضافة ملف CSS جديد باستخدام دالّة ()wp_enqueue_style.1 نقطة
-
تُعتبر خاصيّة الطوفان float property من مصادر القوّة لأي مطوّر أو مُصمّم يستخدم تِقنيّات HTML وCSS. ويُؤدّي عدم الفهم الصحيح لآلية عمل هذه الخاصيّة إلى بعض التِباس في كيفية التعامُل معها. ارتبطت هذه الخاصيّة في الماضي مع أخطاء المُتصفّحات ومشاكل التوافقية، أما الآن فالتعامُل مع خاصيّة الطوفان أصبح من الأمور الأساسيّة التي لا يستطيع المُطوّر تجاهلها. سنتناولُ الموضوع بجزئيّاته الصغيرة لفهم ما تُقدمه هذه الخاصيّة واستخدامها بالشكل الأمثل. عرفنا الطوفان سابقًا من عالم الطباعة والتصميم كما في المجلات، حيثُ الصورة على أحد الجهتين اليمين أو اليسار ويتوضع نَصّ بجانبها بشكل مُتناسق وجذّاب، وفي عالم الويب ومع تقنيّات HTML/CSS، يلتف النصّ حول الصورة باستخدام خاصيّة الطوفان float property كما هو الأمر في تصاميم المجلات. استخدام الصُور مع خاصيّة الطوفان هو أحد الأمور الّتي يُمكنك استخدامها مع هذه الخاصيّة، ولكن في الحقيقة يُمكن استخدام هذه الخاصيّة أيضًا مع أي عنصر من عناصر HTML، حتّى أنّه بالإمكان استخدامها في تقسيم الصفحة page layout. التعريفتُعرّف رابطة الشبكة العالمية W3C خاصيّة الطوفان بالشكل التالي: يُمكن تحديد أربعة قيم لخاصيّة الطوفان: left, right, inherit, none، حيثُ كل قيمة تُعبّر عن دلالتها فمثلًا، تحديد قيمة الطوفان إلى اليسار لعنصر ما (float: left) سينقل العنصر إلى أقصى حافة العنصر الأب الخاص به من جهة اليسار. كما هو الحال عندما تكون القيمة المُحددة للعنصر هي float: right، حيثُ أنّ العنصر سينتقل إلى أقصى اليمين لحواف العنصر الأب الخاص به، وتجعل القيمة inherit العنصر يرثُ قيمة الطوفان من العنصر الأب الخاص به، والقيمة none هي القيمة الافتراضيّة والتي تجعل من العنصر لا يستخدم الطوفان أبدًا. img { float: right; margin: 10px; } آلية عمل الطوفانيعمل الطوفان بطريقة غير مُعقدة وليس كما يعتقد البعض، لتوضيح ذلك يجب العودة إلى أساسيات HTML لمعرفة حقيقة ما يجري قبل الخوض في التفاصيل. في عالم الويب، تتقيّد تقنية HTML بجملة قواعد، ما يتقاطع مع خاصيّة الطوفان هو قاعدة التدفّق الطبيعيّ normal flow، حيثُ تصطف العناصر مِن نوع block فوق بعضها البعض، كما في العناصر div، p، h1 من الأعلى إلى الأسفل. تتوضع العناصر المُطوفة في بادئ الأمر حسب التدفّق الطبيعيّ وتبعًا إلى تسلسلها في مُستند HTML، ومن ثُمّ تُسحب العناصر المُطوفة من التدفّق الطبيعيّ، وتُنقل إلى أقصى يمين أو يسار (على حسب القيمة المُحددة) العنصر الأب الخاصّ بالعنصر المُطوف. بمعنى آخر، تغيّر العناصر المُطوفة من طريقة عملها وتُخالف التدفّق الطبيعيّ في اصطفاف العناصر بعضها فوق بعض إلى اصطفاف العناصر بجانب بعضها البعض، وذلك في حال توفر مساحة كافية للعناصر للتتوضع بجانب بعضها البعض. فَهم هذا التسلسل في عرض العناصر هو أهمّ ما في الطوفان، وهو ما يجعل البعض مرتبكًا في تطبيق هذه الخاصيّة وحلّ مشاكلها. في المثال التالي يوجد ثلاثة صناديق مُحددة الطول والارتفاع، ومن دون تطبيق خاصيّة الطوفان وتُعرض وفقًا لتسلسلها في مُستند HTML. <div class="block pink"></div> <div class="block blue"></div> <div class="block green"></div>.block { width: 200px; height: 200px; }من المُلاحظ في المثال السابق كيف أنّ العناصر تصطف فوق بعضها البعض، ويُمثل ذلك مفهوم "التدفق الطبيعيّ". في المثال التالي نفس الصناديق ولكنها مُطوّفة باستخدام خاصيّة الطوفان float: left. .block { float: left; width: 200px; height: 200px; }تصطفُ الصناديق في المثال السابق بجانب بعضها البعض، وهو أمرٌ مُتوقع بعد معرفة عمل خاصيّة الطوفان، ويتم ذلك فقط لوجود مساحة كافية للعناصر للتتوضع بجانب بعضها البعض. لتوضيح الجزئيّة السابقة تَمّ التعديل على المثال السابق بزيادة عدد الصناديق، مع الانتباه أنّ العنصر الأب لهذه الصناديق هو جِذْعُ الصفحة . من المُلاحظ كيف أنّ تسلسل عرض هذه الصناديق يختلف بناءً على حجم نافذة المُتصفّح -بالإضافة إلى جذع الصفحة - ولذلك ستستهلك هذه الصناديق مزيدًا من الصفوف عند عدم توفر مساحة كافية لعرض هذه الصناديق بجانب بعضها البعض، حيثُ كُلّما تَمّ تصغير حجم نافذة المُتصفّح كُلّما ازداد عدد الصفوف. تحرير الطوفانتعمل خاصيّة الطوفان float جنبًا إلى جنب مع الخاصيّة clear، حيثُ تُكمّل الخاصيّتان بعضُهما البعض لتُقدّم للمُطوّر أداة تطوير أفضل وأسهل. تمّت الإشارة سابقًا إلى أن العنصر المُطوف يتوضع في التدفّق الطبيعيّ في بادئ الأمر، ثم يُزال منه. هذا يعني أنّ كُلّ عنصر يتبع هذا العنصر سوف يعمل بطريقة مُغايرة لما هو مُتوقع، هذا السلوك هو ما يُربك البعض في خاصيّة الطوفان . يوجد في المثال التالي صندوقان مُطوّفان هما الورديّ والأزرق، ومِن ثُمّ صندوقان غير مُطوّفان هما الأخضر والبرتقالي. <!-- HTML --> <div class="block pink float"></div> <div class="block blue float"></div> <div class="block green"></div> <div class="block orange"></div> /* CSS */ .block { width: 200px; height: 200px; } .float { float: left; } .pink { background: #ee3e64; } .blue { background: #44accf; } .green { background: #b7d84b; } .orange { background: #E2A741; }كُلّ شيءٍ في المثال السابق واضح ماعدا عدم ظهور الصندوق الأخضر من العرض، وتوضعه أسفل الصندوق الورديّ، حيثُ أنّ الصندوق الورديّ والصندوق الأزرق هي عناصر مُطوّفة، وتتوافق طريقة عرضها في المُتصفّح بناءً على المعلومات التي توصلنا إليها حتّى الآن، حيثُ أنّها تُسحب من تسلسل عرض التتدفّق الطبيعيّ وتصطف بجانب بعضها البعض، وهذا ما أخفى الصندوق الأخضر، ولإظهاره يجبُ استخدام الخاصيّة clear. تملك الخاصيّة clear خمس قيم هي: يسار left، يمين right، الطرفين both، مَوروث inherit ولا شيء none. تجعل القيمة left العنصر أسفل أي عنصر مُطوف إلى جهة اليسار، وتجعل القيمة right العنصر أسفل أي عنصر مُطوف إلى جهة اليمين، واستخدام القيمة both تجعل من العنصر أسفل أي عنصر مُطوف على الجهتين اليُمنة واليسرى، أما القيمة inherit فتجعل من العنصر يرث قيمة العنصر الأب للخاصيّة clear. في المثال التالي تم استخدام الخاصيّة clear بالقيمة left مع الصندوق الأخضر. <!-- HTML --> <div class="block pink float"></div> <div class="block blue float"></div> <div class="block green clear"></div> <div class="block orange"></div> /* CSS */ .block { width: 200px; height: 200px; } .float { float: left; } .clear { clear: left; } .pink { background: #ee3e64; } .blue { background: #44accf; } .green { background: #b7d84b; } .orange { background: #E2A741; }يجعل التعديل الأخير على الصندوق الأخضر من الصندوق الورديّ وكأنّه في التدفّق الطبيعيّ لمُستند HTML، على الرَغم من أنّه ليس كذلك، وهذا ما يجعل من الخاصيّة clear خاصيّة رائعة والتي تُساعد على إرجاع عنصر غير مُطوف ليُعرض بشكل مُتوافق مع التدفّق الطبيعيّ ويَظهر على المُتصفّح كما هو مُتوقع له أن يظهر. بعد فهم عمل هاتان الخاصيّتان سيكون من السهلِ ابتكارُ أساليب جديدة للتعامل مع شيفرة HTML وCSS استخدام الطوفان لتقسيم الصفحاتتبرز أهمّيّة خاصيّة الطوفان عند استخدامها في إنشاء تقسيمات الصفحة ، حيثُ بإمكاننا إنشاء صفحة بعمودين بطرق عدّة، وأغلب هذه الطُرق تستخدم عنصرًا مُطوّفًا واحدًا أوعنصرين مطوّفين. لنأخذ مثالًا بسيطًا: يحتوي موقع على عمودين، حيثُ المُحتوى على الجانب الأيسر وشريط التنقل الجانبي على الجانب الأيمن، في أعلى الصفحة يوجد ترويسة header وأسفل الصفحة يوجد ذيل الصفحة footer. #container { width: 960px; margin: 0 auto; } #content { float: left; width: 660px; background: #fff; } #navigation { float: right; width: 300px; background: #eee; } #footer { clear: both; background: #aaa; padding: 10px; } تحليل ملف التنسيق السابق يُظهر أنّ الحاوية الرئيسة والتي تُدعى container تُقيّد عناصر الصفحة المُطوفة في موضعها الذي يجب أن تكون عليه، ولو لم يكن لدينا هذه الحاوية لكانت العناصر المُطوفة مُلتصقةً على حواف نافذة المُتصفّح، وأما العناصر المُطوفة داخل الحاوية فهي content و navigation. يُمكن الحصول على تقسيمٍ ذو عمودان وذلك بأنّ نُطوّف المُحتوى content إلى جهة اليسار، وشريط التنقّل الجانبي navigation إلى جهة اليمين، ولكلٍ منهما قيمة عرض مُحددة بـ 660px للمُحتوى و300px لشريط التنقّل الجانبي، وبذلك سيستحوذ هذان العنصران عرض الحاوية بالكامل (960px). أخيرًا تم تحديد الخاصيّة clear على ذيل الصفحة footer، والتي من شأنها أنّ تُعيد العناصر التي تلي أي عناصر مُطوفة إلى التدفّق الطبيعيّ، في هذه الحالة حُددت القيمة both لذيل الصفحة footer، لجعله يصطفُ أسفل المحتوى وشريط التنقّل الجانبي. يُظهر المثال التالي كيفية عرض ذيل الصفحة footer في حال عدم استخدام الخاصيّة clear، ويُلاحظ كيف أنّ ذيل الصفحة انتقل إلى أسفل شريط التنقّل الجانبي، وذلك يحدث بسبب وجود مساحة كافية له أسفل الشريط، وأيضًا هذا السلوك هو مُتوافق مع التدفّق الطبيعيّ الذي نعمل به، ولكن هذا بالطبع ليس ما نريده. يُفترض الآن أن يكون الأمر واضحًا كيف أنّ الخاصيّتين float وclear تعملان جنبًا إلى جنب وكُل منهما يُكمّل الآخر. الطوفان أولًاحتى الآن جميع الأمثلة السابقة كانت واضحة وبعيدةً عن المشاكل، حيثُ هناك حالات دقيقة يجبُ الإشارة إليها عند استخدام خاصيّة الطوفان. واحدةٌ من أهمّ هذه الحالات هي غير مُرتبطة بشكل مُباشر مع تقنيّة CSS بل مع تقنيّة HTML نفسها، حيثُ يختلف توضع العنصر المُطوف عن ما هو مُتوقع له أنّ يكون فيه، كما في المثال التالي حيثُ لدينا صندوق صغير نوعًا ما وبداخله صورة مُطوفة إلى جهة اليمين وبجانبها نصٌّ، ويملك العنصر الأب، وهو الحاوية، مساحة عرض مُحدودة (280px) ليُحيط بالعناصر المُطوفة بداخله. #container { width: 280px; margin: 0 auto; padding: 10px; background: #aaa; border: 1px solid #999; } img { float: right; } <div id="container"> <img src="image.gif" /> <p>This is some text contained within a small-ish box. I'm using it as an example of how placing your floated elements in different orders in your HTML can affect your layouts. For example, take a look at this great photo placeholder that should be sitting on the right.</p> </div> حتى الآن لا يوجد ما هو غريب في المثال السابق، ولكن ماذا لو كان ترتيب العناصر في صفحة HTML مُختلفٌ بعض الشيء، حيث الصورة بعد النَصّ <div id="container"> <p>...</p> <img src="image.gif" /> </div> النتيجة ليست مرضية أبدًا، حيث انتقلت الصورة من أعلى الزاوية اليُمنى إلى أسفل النصّ، ليس هذا فقط بل أصبحت الصورة خارج الحاوية الخاصّة بها. إذا ما المُشكلة؟ في الحقيقة سبب المُشكلة يحتاج إلى شرحٍ والذي سنتطرّق إليه لاحقًا، ولكن الجدير بالذكر الآن أنّه من المُمكن تطبيق قاعدة "التطويف أولًا"، أيّ أنّ العناصر المُطوفة تأتي قبل العناصر غير المُطوفة في مُستند HTML، قد لا تعطي هذه القاعدة النتيجة المطلوبة دائمًا ولكن من الجيد تذكرها. أما سبب ظهور الصورة خارج حدود الحاوية الخاصّة بها فهو يعود إلى ما يُسمى بالانْطِواء collapsing. الانْطِواء Collapsingالانْطِواء هو عندما لا يتوسّع العنصر الأب الذي يحتوي على أي عدد من العناصر المطوفة بشكلٍ كامل ليُحيط بها كما لو كان سيفعل لو كانت هذه العناصر غير مُطوفة. في المثال السابق لم تكن المُشكلة في المُتصفّح نفسه والترتيب الذي ظهر عليه المُحتوى في المثال السابق هو ترتيب منطقيٌّ، حيثُ أنّه تُسحب العناصر المُطوفة من التدفّق الطبيعيّ للعناصر على الصفحة، لذلك لا تَعتبر الحاوية container العناصر المُطوفة جزءًا منها وتتعامل معها وكأنّها غير موجودة. لمزيد من التفاصيل حول هذا الموضوع يُمكن الرجوع إلى مقالة بعنوان: احتواء الطوفان. يُوضّح المثال التالي حاوية بداخلها صندوقين <!-- HTML --> <div class="container"> <div class="block pink"></div> <div class="block blue"></div> </div> /* CSS */ .container { background: rgb(168, 207, 166); width: 600px; margin: auto; } .block { width: 200px; height: 200px; margin-left: 64px; }يُلاحظ بعد إضافة الطوفان إلى الصندوقين اختفاء الحاوية من المُتصفّح، هل أصبحت تحت الصندوق الأزرق؟ أم الورديّ؟ أم ربما الأخضر الذي هو تحت الورديّ؟ في الحقيقة ما حدث هو أنّ الحاوية انطوت على نفسها بسبب عدم وجود عناصر لاحتوائها بعد الطوفان، ويبدو ذلك جليًا بعد إضافة حدودٍ للحاوية. بعد أن توضّحت المُشكلة سوف نتطرّق إلى الحلول المُتوفرة، حيثُ يوجد طُرق عدّة لحل هذه المُشكلة، تعدّد الحلول يعود إلى المُرونة في اختيار الحلّ الأنْسَب، فالحلول المطروحة قد لا تُناسب جميع الحالات. تُعتبر الطريقة التالية أقدم الطُرق في حل مُشكلة الانطواء، وهي باستخدام الخاصيّة clear بعد العنصر المُطوف، وذلك بجعل العنصر الأب مُمتدًا إلى ما بعد العنصر المُطوف، حيثُ يتم إضافة div مع تنسيق مُضمّن clear: right، والذي يجعل من الصورة المُطوفة مأخوذةً بالحسبان. يعمل هذا الحل بشكل جيّد جدًا ومع جميع المُتصفحات ومن دون أي مشاكل في التوافقية، ولكن استخدام تنسيق مُضمّن يُخالف قاعدة الفصل بين مُستند HTML و ملف التنسيق CSS لذلك لا يُحبّذ العديد من المُطوّرين هذه الطريقة. <div id="container"> <p>...</p> <img src="image.gif" /> <div style="clear: right;"></div> </div> في المثال التالي لدينا عنصر أب يحتوي على ثلاثة صور مُطوفة، من المُلاحظ كيف أن الصور الثالثة خارج الحاوية. <div id="container"> <img src="image.gif" /> <img src="image.gif" /> <img src="image.gif" /> </div> لتصحيح طريقة العرض سنستخدم CSS بدلًا من التنسيق المُضمّن، تسمح الطريقة التالية للعنصر الأب بالتوسّع ليُحيط بالعناصر المُطوفة، حيثُ يتم إضافة الخاصيّة فيضان overflow للعنصر الأب مع القيمة hidden. الجدير بالذكر هنا أنّه لم تُنشئ هذه الخاصيّة بهدف حل مُشكلة الانطواء، لذلك قد يكون لها بعض المشاكل، فمثلًا قد يختفي المُحتوى من الظهور عندما يكون أكبر من أنّ يتسع داخل الحاوية، لذلك يجب الحذر عن استخدام هذه الطريقة. #container { overflow: hidden; width: 260px; margin: 0 auto; padding: 10px 0 10px 10px; background: #aaa; border: 1px solid #999; } يُوضح المثال التالي اختفاء المحتوى من الظهور عند استخدام خاصيّة overflow. يوجد طريقة أُخرى لحل مُشكلة الانطواء والّتي تعطي نتائج جيّدة كما في الحلول السابقة، وهي استخدام شبه العناصر pseudo-elements المُسمى "بعد" after. #container:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } تقوم أوراق الأنماط المُتتالية CSS بإضافة عنصر جديد بعد الحاوية container مع بعض المُحتوى، في المثال السابق هو النقطة (.)، وإخفائه من العرض وبدون ارتفاع. يُمكن القراءة عن هذه الطريقة بمزيد من التفصيل عبر موقع: التمركز أهمّ ما في الأمر. تقوم جميع الطرق السابقة بحل مُشكلة الانطواء، والطريقة الأخيرة هي الأكثر استخدامًا في الوقت الحالي بعد تطوّر المُتصفحات ودعمها لمعايير CSS3. يقدم الموقع التالي أفضل استخدام لهذه الطريقة ويُوضح تطوّر الشيفرة الخاصة بها عبر الوقت: إصلاح الانطواء. خاتمةأصبحت الخاصيّة float من الأدوات الأساسيّة في تصميم صفحات مُتجاوبة، لذلك فهم آليّة عمل هذه الأداة والمشاكل الخاصّة بها سيقدم للمطوّر أداة عمليّة لا يستطيع الاستغناء عنها. ترجمة -وبتصرّف- للمقال: CSS Floats 101 لصاحبه Noah Stokes1 نقطة
-
لا أخفيك المراجع العربية لتعلّم لغة روبي قليلة عربيًا مقارنة مع لغة PHP مثلًا، ولكن هناك بعض الشروحات الّتي تشرح الأساسيات: دورة صوت وصورة "مدخل إلى برمجة مواقع الإنترنت باستخدام لغة Ruby" كتاب الكتروني "مقدمة في روبي" موقع "روبي عربي" دورة صوت وصورة "دورة على يوتيوب في روبي وإطار العمل Ruby on Rails" مقالات "أكاديمية حسوب"1 نقطة
-
تستخدم الشركات الكبيرة عادةً أكثر من لغة برمجة، فجميعهم يستخدمون جافا سكريبت ولغة أخرى: شركات تستخدم لغة روبي: آبل، تويتر، Github، Shopify، Groupon. شركات تستخدم لغة بايثون: Google، Mozilla، Instagram، Pinterest. شركات تستخدم لغة PHP: فيسبوك، ووردبرس. بإمكانك استخدام موقع builtwith.com لمعرفة ماذا يستخدم كل موقع من لغات وتقنيات، ويعرض الموقع أيضًا إحصائيات مفيدة حول التقنيات المُستخدمة.1 نقطة
-
نعم يُمكن ذلك عبر ضبط إعدادات كتلة Server. المثال التّالي يُقدّم خطوطًا عامّة لهذا الإعداد: server { listen 80; server_name www.domain1.com; root /var/www/domain1; } server { listen 80; server_name www.domain2.com; root /var/www/domain2; } توجد ملفّات الموقع www.domain1.com في المجلّد var/www/domain1/، أمّا الموقع www.domain2.com فتوجد ملفّاته في المجلّد var/www/domain2/. عند طلب الموقع www.domain.com فإنّ Nginx يختار كتلة Server الأولى لتتولّى التّعامل مع الطّلب، بالنّسبة لwww.domain2.com فإنّ الاختيّار يقع على الكتلة الثّانيّة. للمزيد راجع هذا المقال1 نقطة