البحث في الموقع
المحتوى عن 'ملفات'.
-
بعد أن تعرّفنا على ماهية التصميم وعناصره ومبادئه، وألقينا نظرة على برامجه وتطبيقاته الأكثر شهرة، يمكننا البدء بالعمل على تصاميم مختلفة بناء على تعلمناه في المقالات السابقة في هذه السلسلة، يبقى لدينا فقط أن نعلم ما هي القواعد الأهم والمتبعة في التصميم وذلك تبعًا للمشروع الذي سنعمل عليه، دون أن ننسى استخدام العناصر بالطريقة الأمثل والالتزام بالمبادئ وإتقان استخدام برامج التصميم. وتتضمن هذه المقالة أهم القواعد الواجب اتباعها لتصميم كل من الأيقونات (الرموز) والشعارات نظرًا للتشابه الكبير من حيث المبدأ في قواعد تصميم هذين العنصرين، وسنبدأ أولًا بتعلم قواعد تصميم الأيقونات. قواعد تصميم الأيقونات الأيقونات هي الرموز المستخدمة للدلالة على أمر ما، حيث تستخدم الأيقونات كرموز للبرمجيات في أجهزة الحاسوب وأيضًا للتطبيقات في الهواتف المحمولة، فتلك الرموز المميزة لتطبيقات الهاتف المحمول ليست شعارات بل أيقونات، ولكن من الممكن أن يستخدم الشعار كأيقونة للتطبيق مثل أن نستخدم شعار أحد البنوك كأيقونة لتطبيق البنك على الهواتف المحمولة. كما نستخدم الأيقونات المصممة داخل صفحات الويب للدلالة على الخدمات أو الفئات أو الميزات أو أي شيء آخر. ومثالًا على تلك النوعية من الأيقونات تلك المستخدمة على فئات الدروس والمقالات في أكاديمية حسوب. يمكن تصميم الأيقونات بخطوط وأشكال سوداء أو بلون واحد أو بطريقة التصاميم المسطحة Flat Design (وهي تصاميم ثنائية الأبعاد تتميز بالبساطة وبدون عناصر معقدة كالظلال والقوام والتدرجات اللونية وغيرها) أو حيوية بتدرجات لونية أو حتى ثلاثية الأبعاد. وتعد أيقونات التطبيقات من أبرز وأهم أنواع الأيقونات حيث أن الأيقونة المميزة ستجذب اهتمام الناس وتدفعهم لتحميل التطبيق وتجربته، قد يكون هناك تطبيق جيد للغاية وأداؤه ممتاز ولكن أيقونته سيئة وغير مثيرة للاهتمام، بينما تطبيق آخر يؤدي نفس الغرض ولكنه سيء وأداؤه تشوبه الأخطاء والمشاكل التقنية إلا أن أيقونته مذهلة ومثيرة للاهتمام، بالتأكيد سيتم تحميل التطبيق السيء ذو الأيقونة الجيدة أكثر من الآخر إلى أن تطغى التقييمات السلبية على جمالية أيقونة التطبيق السيء، لكن ذلك سيستغرق وقتًا طويلًا كما أن العديد من الناس لا تنتبه للتقييم بل تنظر للأيقونة فحسب. فما هي أهم قواعد تصميم الأيقونات؟ سنتعرف عليها الآن. تحديد الهدف يجب أن نحدد الهدف من الأيقونة التي سنصممها، إن أيقونات التطبيقات عادة ما تكون زاهية الألوان ومفعمة بالحيوية وقد تكون ثلاثية الأبعاد أيضًا، بينما أيقونات مواقع الإنترنت عادة ما تكون مسطحة وبسيطة، إذ تستخدم للدلالة على أمور معينة فحسب. ومن هذا المنطلق يجب أن نفهم الهدف من الأيقونة ومكان استخدامها لنتمكن من تحديد الطريقة التي سنصمم بها الأيقونة. قابلية تبديل الحجم قد تستخدم الأيقونة في أكثر من موقع تمامًا مثل الشعارات، لذا يجب أن تكون إما قابلة للتكبير والتصغير ولذلك يجب أن نصممها بالرسومات الشعاعية Vector وليس النقطية حتى لا تتأثر وتتشوه بعد تغيير حجمها، أو قد نضطر إلى تصميم حزمة كاملة من الأيقونات لجميع القياسات حيث أن بعض التصاميم قد تحمل تفاصيل أكثر من اللازم وعند تصغير حجمها فإن هذه الأيقونات لن تكون واضحة أو مفهومة، فهناك أيقونات ستظهر في قوائم صغيرة الحجم أو في رموز المواقع الإلكترونية، لذلك سيتعيّن علينا أن نصمم أيقونات لمختلف القياسات بحيث نراعي وضوح فكرة الأيقونة مهما صغر حجمها. لاحظ أن الأيقونات الأصغر حجمًا هي ليست نفس الأيقونة الكبيرة، بل هي تصميم جديد مشابه ولكنه واضح ضمن الحجم الصغير. اتباع الهوية البصرية عندما نصمم أيقونة لعلامة تجارية أو أي مؤسسة لديها هوية بصرية معدة مسبقًا، فيجب أن ننتهج نهج الهوية البصرية في التصميم من حيث الأسلوب والألوان والخطوط وغيرها، فمن غير المنطقي أن تكون الأيقونة مختلفة كليًا عن باقي عناصر الهوية البصرية. لذلك عندما يطلب منك تصميم أيقونة لمؤسسة تمتلك هوية بصرية، عليك اتباع نهج تلك الهوية، واطلب منهم كتيب إرشادات الهوية البصرية، وإن لم يكن لديهم كتيب فاطلب منهم تزويدك بنسخة عن عناصر الهوية البصرية لتلقي نظرة فاحصة عليها وتتبع نهجها. لاحظ الأيقونات أسفل صفحة الويب الخاصة بشركة تويوتا للسيارات تتبع نهج الهوية البصرية للشركة. البساطة والوضوح هذا الأمر ينطبق على الأيقونات والشعارات معًا، فالهدف من الأيقونة هو التعريف والدلالة إلى شيء ما مثل تطبيق أو خدمة أو فئة أو غير ذلك، لذلك يجب أن تكون الأيقونة بسيطة وواضحة لتكون مفهومة، ويجب أن تكفي النظرة الأولى إليها لفهم ما ترمز إليه. في المثال التالي لأحد المواقع استُخدمت أيقونات دلالية إلى ميزات معينة متوفرة في خدماتهم، ولكنك ستلاحظ بسهولة أن الأيقونات غير مفهومة، بل وتسبب الارباك لمشاهدها ولو اعتمد أصحاب الموقع على النصوص فحسب لكان ذلك أفضل. بينما تبدو الأيقونات في المثال التالي واضحة وتدل بوضوح على معنى الميزة المشار إليها. اتباع الارشادات في بعض المواضع كتطبيقات سطح المكتب أو تطبيقات الهواتف المحمولة أو غيرها يكون هناك إرشادات معينة لتصميم الأيقونات بحيث يجب اتباعها للحصول على أفضل النتائج وللتوافق والتناسق مع موضع استخدام الأيقونة، لذلك يجب دائمًا البحث عن أية إرشادات متوفرة قبل البدء بالتصميم، وعلى سبيل المثال يجب اتباع الارشادات عند تصميم أيقونات تطبيقات الأندرويد وكذلك أيقونات تطبيقات أنظمة iOS. تناسق الوزن البصري في معظم الأحيان نصمم مجموعة من الأيقونات وليس أيقونة واحدة، تستخدم في مواقع الويب أو تطبيقات الهاتف المحمول أو في قوائم البرامج وغير ذلك، ولذلك يجب أن تكون جميع الأيقونات بوزن بصري واحد تقريبًا، وذلك فيما يتعلق بالخطوط والألوان والحجم، والأهم أن يكون وزنها البصري متناسقًا مع التصميم العام للهوية البصرية وواجهة الموقع وواجهة الاستخدام للتطبيق وغيرها. لاحظ أن هذه الأيقونات متطابقة في الدلالات والمعاني ولكنها تختلف من ناحية التصميم والوزن البصري. نوعية ملفات الأيقونات توجد عدة أنواع لملفات الأيقونات ولعل أشهرها هي GIF وPNG وSVG. وتُعَدّ GIF أقدم تنسيق استُخدم لتصميم الأيقونات في الماضي كما تستخدم ICO لملفات أيقونات برامج أنظمة الويندوز، واستُخدم GIF نظرًا لصغر حجمه وإمكانية إدراج الشفافية فيه عكس JPG و BMP الشائعة في ذلك الوقت، إلا أن من سلبياتها عدم إمكانية استخدام حزمة ألوان واسعة حيث تعتمد نظامًا مؤلفًا من 256 لونًا فقط، ومع مرور الوقت تطورت الأدوات والتطبيقات وأصبح بالإمكان استخدام تنسيق PNG لصناعة الأيقونات والذي يتميز بمجال طيف واسع من الألوان بالإضافة إلى إمكانية تضمين الشفافية فيه، ولكن PNG هو تنسيق للرسومات النقطية وعند محاولة تكبير التصميم من أجل بعض الواجهات و التطبيقات فسوف تظهر التشوهات والعيوب. لذلك بدأ المصممون يعتمدون أكثر على SVG الذي يعتمد الرسومات الشعاعية والتي لا تتأثر بتغيير الحجم وتحافظ على دقة التصميم إضافة إلى استخدامه طيفًا واسعًا من الألوان وتضمين الشفافية فيه، والأكثر من ذلك أن ملفاته تتميز بصغر حجمها وهو الأصغر بين بقية التنسيقات، ما جعله الخيار الأمثل لتصميم الأيقونات حاليًا. وعلى الرغم من إمكانية استخدام هذه الملفات مباشرة في بعض التصاميم إلا أن العديد من التطبيقات والواجهات لا تزال لا تدعم هذه النوعية من الملفات، لذلك يجب تحويله إلى تنسيقات أخرى مثل PNG، وبناء عليه يجب أن نحدد المقاس المطلوب بحسب التصميم الذي نعمل عليه. فالخيار الأفضل هو تصميم الأيقونة بتنسيق SVG ومن ثم تصدير جميع المقاسات والتنسيقات التي تحتاجها بتنسيقات يمكن استخدامها مثل PNG. الأيقونات والشعارات مثل أي نوع من أنواع التصاميم فإن تصميم الأيقونات جزء من فن تصميم الرسوميات (التصميم الجرافيكي) ولهذا يجب استخدام العناصر وتطبيق المبادئ الخاصة بتصميم الرسوميات لإنجاز تصاميم احترافية خالية من الأخطاء ومثيرة للاهتمام. ويتشابه تصميم الشعارات من حيث المبدأ مع تصميم الأيقونات حيث أن كليهما يجب أن يحدد الهدف والغرض من هذا العنصر (الأيقونة أو الشعار) والجمهور المستهدف ويجب أن يصمم بأحجام مختلفة بحسب موضع الاستخدام ويجب أن يكون متناسقًا ومتكاملًا مع بقية عناصر الهوية البصرية، ويجب أن يُصمم الشعار كأول عنصر من عناصر الهوية البصرية ومن ثم يتم استخراج لوحات الألوان وباقي عناصر الهوية البصرية بناءً على نموذج الشعار، كما أن تنسيق ملفات تصميم الشعار عادة ما تكون أيضًا SVG أو PNG بحسب موقع استخدامه. الشعارات ليست أيقونات، ولكن يمكن أن تشتق الأيقونات من الشعارات تمامًا مثل أيقونات تطبيقات الهاتف المحمول. ليس بالضرورة أن يكون الشعار بسيطًا بعكس الأيقونة، إلا أن البساطة في التصميم تجعل الشعار أكثر أناقة واحترافية، وأسهل للفهم والملاحظة، حيث أن الغالبية العظمى من العلامات العالمية الشهيرة اتجهت في السنوات الماضية إلى تعديل شعاراتها لجعلها أكثر بساطة وأناقة عكس شعاراتها القديمة، وهذه بعض الأمثلة بحيث نعرض الشعار القديم وآخر شعار مستخدم الآن بغض النظر عن مراحل التطور التي مر بها الشعار. قواعد تصميم الشعار ما هو الشعار؟ هو واجهة أي علامة تجارية وهو الانطباع الأول الذي يتكون لدى الجمهور بمجرد رؤيته، لذا فإن تصميمه مهم للغاية. وبما أن تصميم الشعارات والأيقونات تعتمد قواعد ومبادئ مشتركة، إذ يجب تحديد الهدف والغرض من الشعار كما يجب مراعاة قابلية التكبير والتصغير بحسب موضع الاستخدام ويفضّل الالتزام بمبدأ البساطة والوضوح في تصميمه لضمان وصول فكرته ورسالته للجمهور، وعلى عكس الأيقونات فإن الشعار هو العنصر الأول في تصميم الهوية البصرية، وتتبع الهوية البصرية تصميم الشعار في تحديد شكل وأسلوب التصميم العام، كما يفضل استخدام تنسيق SVG لملفات الشعار مع تصديرها إلى PNG بالمقاس المناسب عند الحاجة. تجنب التقليد من الطبيعي أن تتشابه الأيقونات التي تصممها مع أيقونات كثيرة متوفرة على الإنترنت نظرًا لأن مواضيعها مكررة أساسًا، ولكن من غير المقبول تكرار أو تقليد الشعارات الأخرى، فلو طُلب منك مثلًا أن تصمم شعارًا لمطعم برجر، أول ما سيخطر ببالك تصميم شكل قطعة البرجر وبعد بحث بسيط على الإنترنت ستكتشف وجود العشرات وربما المئات من الشعارات التي تشبه تصميمك وربما يكون بعضها شبه مطابق له أيضًا، الأمر الذي سيجعل العميل يعتقد أنك نسخت الشعار من مكان آخر وقدمته له ولم تبذل أي مجهود في تصميمه، حصل ذلك معي في بدايات مشواري في التصميم لذلك اعتمدت طريقة جديدة في التحضير للتصميم قبيل البدء فعليًا، وهو أن أبحث عن تصاميم متعلقة بما أنوي القيام به ثم أحاول تجنبها جميعها وأسعى إلى إيجاد فكرة جديدة تجعل تصميمي مميزًا ولا شبيه له، وهو ما سيقدّم للعميل بدوره شعارًا مذهلًا يميّزه عنه منافسيه. اكتب في بحث الصور على جوجل (شعار برجر) وستحصل على العديد من شعارات البرجر، لذا حاول تجنب إنشاء تصميم مطابق أو مشابه لأي منها، وليكن تصميمك فريدًا من نوعه. ابدأ برسم المخطط يدويًا حتى وإن لم يكن لديك موهبة في الرسم اليدوي باستخدام القلم والورق، إلا أن الرسم باستخدام الورقة وقلم الرصاص له تأثير السحر على تدفق الأفكار وتعديلها بطريقة فورية. جميع الشعارات العظيمة بدأت بخربشة بسيطة على الورق، ثم أصبحت نموذجًا أوليًا يتطور كل لحظة إلى أن يصبح فكرة مميزة ثم تُنقل هذه الفكرة إلى الحاسوب عبر رسم الخطوط الأساسية لها على برنامج التصميم ومن ثم تطويرها برسم الأشكال الأساسية ثم تتدفق الألوان على التصميم لمنحه الحيوية والهوية الخاصة به، وهكذا إلى أن تصبح الفكرة شعارًا حقيقيًا مميزًا. الصورة بوساطة rawpixel.com من موقع Freepik. الأبيض والأسود يجب علينا كمصممين أن نضع في الحسبان مسألة التصميم بالأبيض والأسود، في بعض الحالات قد يكون الشعار بطبيعة الحال بالأبيض والأسود وبالتالي لا حاجة للقلق بشأن ذلك، ولكن في معظم الأحيان يكون الشعار ملونًا ومع ذلك تضطر الشركات وخصوصًا التجارية منها إلى استخدام نسخة بالأبيض والأسود من الشعار لأجل المطبوعات والتعليب والتغليف والتطريز والنقش وغيرها، لهذا يجب أن يكون الشعار واضحًا ومفهومًا بالأبيض والأسود كما هو كذلك بالألوان في تلك الحالة. إن نظرت إلى النمط الأبيض والأسود لبعض الشعارات فإنك لن تعرف الشعار بسهولة من النظرة الأولى وأحيانًا قد لا تعرفه أبدًا بدون الألوان، ولعل السبب في أن معظم الشعارات في المثال الذي حضّرته لك لا تحتاج إلى الشعار الأبيض والأسود بطبيعة الحال، ولكنني أردت توضيح الفكرة. في الشكل التوضيحي التالي ستشاهد شعارات بالأبيض والأسود ومن ثم ستشاهد الشعارات الملونة الأصلية في الشكل التالي، لاحظ كيف من الصعب التعرف على الشعار من النظرة الأولى في الشكل الأول. لاحظ صعوبة تحديد هوية هذه الشعارات. لاحظ كيف يمكن التعرف على الشعارات بسهولة من خلال الألوان وهي شعارات MasterCard، PayPal، Tommy Hilfiger، Flickr، Microsoft وTarget. الألوان بعد دراستنا وتعرّفنا على الألوان ونماذجها ونظريتها ومخططاتها من مقال الألوان في تصميم الرسوميات ونظرية اللون فإن أكثر وأول عنصر تصميمي يطبّق عليه نظرية الألوان وكل ما يتعلق به هو الشعار. يجب التركيز على تأثير الألوان على الجمهور المستهدف، ويجب أن يكون تأثيرها إيجابيًا، وفي حال استخدام أكثر من لون فيجب تطبيق قواعد المخططات اللونية لتوفير التوازن اللوني للشعار ولا يكون نشازًا أو غير مريح للنظر. كما نستطيع استخراج لوحة الألوان للهوية البصرية للعلامة التجارية من تصميم الشعار، أو قد يحضّر المصمم لوحة الألوان مسبقًا بناءً على نهج سابق متبع من قبل العلامة التجارية أو معطيات أخرى. أحيانًا قد يكون لاسم العلامة التجارية دلالة أو تعبير يدل على الألوان التي يجب أن تتواجد في الشعار، وذلك يجعله منطقيًا ومتناسقًا مع الاسم وراسخًا أكثر في الأذهان. شعار متصفح الانترنت فاير فوكس (الثعلب الناري) بتدرجات لون النار. مراعاة نماذج الألوان من المهم أن تعلم إذا ما كان الشعار سيستخدم للشاشات فقط أم للطباعة فقط أم لكلاهما، حيث يجب أن تصمم الشعار بنموذج ألوان RGB الخاص بالشاشات وبنموذج ألوان CMYK في حالة الطباعة، وفي هذه الحالة ستلاحظ تغيرًا على الألوان بين الشعارين وهذا طبيعي نظرًا لاختلاف نظام مزج الألوان بين النموذجين. في المثال التالي قسّمت شعار إنستجرام إلى نصفين بشكل قطري (مائل) وطبّقت على كل شطر نموذجًا لونيًا مختلفًا، الاختلاف بسيط للغاية ولكنك ستلاحظه إن دققت النظر. الشعارات النصية في حال استخدام النص في الشعار أو ربما بضعة حروف أو حتى حرف واحد فمن المهم أن تكون تلك الخطوط مميزة، وقد تضطر أحيانًا إلى تحريفها للحصول على تصميم شعار نصي مميز بشكل مختلف عن النص العادي. يلجأ المصممون في بعض الأحيان إلى الخطاطين لتصميم النص أو الحروف بخطوط عربية استثنائية إلا إن امتلك المصمم القدرة على التصميم بالخط العربي (مثال: شعار قناة الجزيرة الإخبارية). وأحيانًا أخرى قد يضطر المصمم إلى تصميم خط كامل فريد من نوعه لكتابة الشعار به (مثال: شعار قناة العربية الإخبارية). ولكن في أغلب الأحيان يتخذ المصمم من أحد الخطوط المتوفرة على الحاسوب أساسًا للتصميم ويحرّفه قليلًا للوصول إلى شعار فريد ومميز. شعارات قناتي الجزيرة والعربية. مجموعة من الشعارات النصية العربية مصممة من قبل عبدالرحمن ممدوح على موقع Behance. مجموعة من الشعارات النصية العربية لمختلف المصممين العرب. مجموعة من أشهر الشعارات النصية العالمية. تنظيم عملية التصميم إذا ما نظّمت عملية التصميم من البداية إلى النهاية فإنك ستوفّر على نفسك وعلى عميلك الكثير من الوقت في محاولة معرفة ما الذي يجب أن تفعله تاليًا، الموضوع بسيط ارسم مخططًا للخطوات الواجب اتباعها وطبّقه بحذافيره وستكون على ما يرام. وليكن مخطط سير عملك كالتالي: تلقي الطلب من العميل. فهم كافة جوانب الشعار المطلوب تصميمه ابتداءً بالهدف ودراسة الجمهور المستهدف والمنطقة المستهدفة والألوان المطلوبة وهوية العميل البصرية والخطوط وغير ذلك. ليس من الضروري أن تتوافر كل هذه المعلومات من قبل العميل ولكن حاول الحصول على أكبر قدر منها لتختصر الكثير من الوقت في تعديلات كثيرة لا داعي لها عبر فهم رؤية العميل وتطلعاته. البحث عن كل ما يتعلق بالشعار من أفكار وأمثلة وشعارات مشابهة. اجلس مع نفسك وفكّر في كيفية تصميم الشعار وفي كيفية تجنب تصميم شعار مشابه لما هو موجود مسبقًا. أمسك بالورقة والقلم وابدأ برسم النماذج الأولية وطورها على الورقة إلى أن تصل لفكرة مبهرة. انقل فكرتك من الورقة إلى برنامج التصميم على الحاسوب واحرص على رسم الشعار بالرسومات الشعاعية Vector لسهولة تعديلها والتلاعب بحجمها. أرسل تصميمك إلى العميل. أجرِ جميع التعديلات المطلوبة التي سيقترحها العميل. أنهِ التصميم وسلّمه للعميل. بهذه الطريقة يمكنك أن تصمم شعارًا دون إرباك أو قلق على ما يجب أن تفعله تاليًا. خاتمة يعد تصميم الشعار المجال الأكثر انتشارًا في عالم تصميم الرسوميات حيث تجد آلافًا من الخدمات المتمثلة بتصميم الشعارات في مختلف مواقع العمل الحر، حيث يحتاج الجميع إلى شعار مثل شعار قناة يوتيوب، صفحة فيس بوك، حساب تويتر، موقع إنترنت، تطبيق هاتف محمول، متجر، مصنع، شركة، منظمة أو أي شيء تقريبًا، لذلك يجب تطوير المهارات واكتساب الخبرة اللازمة لتصميم الشعارات فهي أكثر ما يملأ مخزونك من التصاميم لوضعها في معرض أعمالك. لا يختلف تصميم الأيقونة كثيرًا عن تصميم الشعار إلا أن الاستخدامات تختلف، ويظل الشعار هو الأساس في تصميم الرسوميات حيث تتبعه تصاميم بقية العناصر وهذا ما سنكتشفه في مقال قواعد تصميم الهوية البصرية الذي سينشر لاحقًا.
-
إدارة الصور هي واحدة من الأشياء التي غالبا ما أجدها صعبة، فأنا معتاد على التعامل مع النماذج وجداول قواعد البيانات، لكن التعامل مع الملفات ليس سهلا بالنسبة لي، فإذا كنت قد بدأت للتو مع Laravel وبدأت تشعر بالصعوبة والضيق، فأنا أشعر بألمك. لحسن الحظ، أساسيات إدارة الصور في Laravel لن تكون صعبة إذا فهمت بعض الأمور الأساسية. ملاحظة: إذا كنت جديدا في Laravel، فلا أنصحك بالبدء بهذا الدرس، أنصحك بقراءة بعض الدروس والدورات حول Laravel قبل المتابعة. سوف تلاحظ أن الدرس طويل لذلك قمت بتقسيمه إلى 3 أجزاء، وسوف تلاحظ أيضا أنني لست بارعا في تصميم الواجهة الأمامية (front-end)، فلذلك فالواجهات التي سنقوم بعملها لن تكون جميلة جدا، يمكنك تزيينها بنفسك لاحقا، فالهدف الأساسي هنا هو تعلم أساسيات إدارة الصور. لذلك على أية حال، ماهي هذه الأساسيات ؟ فكرتُ بالمتطلبات التي قد تحتاجها في تطبيقك وكتبتها في هذه القائمة: إنشاء الصورتخزين الصورتعديل الصورتحديث الصورإنشاء صور مصغرةتعديل صور مصغرةإنشاء وتعديل صور الهواتف بشكل منفصلبالنسبة للذين اعتادوا على إجراءات المتحكِّمات (controller actions) المريحة، ستظهر الاستمارات عند إجراءات (actions) الإنشاء create والتعديل edit وأما إجراءات التخزين store والتحديث update فوظيفتهم إنشاء وتعديل السجلات والملفات. سنتعامل مع شيئين مهمين عند تعاملنا مع الصور، الشيء الأول هو النموذج الذي يعمل على البيانات مثل اسم الصورة و مسارها، وأما الشيء الثاني فهو ملف الصورة نفسه الذي سوف يتم تخزينه في مجلد الذي سنقوم بإسناده له. تثبيت Interventionسوف نبدأ بتثبيت حزمة Intervention/image، فإذا لم تقُم بذلك، عدل على ملف composer.json وأضف التعليمة التالية في جزء الاستدعاء (require) : "intervention/image": "~2.2"ثم أضف السطر التالي ضمن مصفوفة Providers في ملف app\config\app.php (انتبه للفواصل) : Intervention\Image\ImageServiceProvider::class,في نفس الملف أضف السطرين التاليين لمصفوفة Aliases: Intervention\Image\ImageServiceProvider::class,أنصحك بالإطلاع على صفحة Intervention للتأكد من الإصدار الأخير للحزمة. في آخر مرة تأكدتُ فيها،كانت تعليمات التَدَخّل تستخدم النمط القديم للإشارة إلى المرجع: 'Intervention\Image\ImageServiceProvider'يمكنك أن تلاحظ في الأعلى أننا في كلتا الحالتين استخدمنا ::class والتي هي ممارسة جيدة تعلمتها من Laracasts.com، فإذا كنت تستخدم على سبيل المثال PHP Storm، فسيكون باستطاعتك الوصول إلى الفئة class الأساسية. إن حزمة Intervention تقوم بإعطائنا صياغة (syntax) وطريقة سهلة لصناعة الصور المصغرة بالإضافة إلى الكثير من التوابع (method) الأخرى الرائعة، لذلك سوف نستخدمها في هذا الدرس، ولمزيد من المعلومات حول هذه الحزمة أنصحك بالإطلاع على التوثيق الرسمي. لاحظ أيضا أننا سنقوم باستخدام حزمة laravelcollective/html وحزمة patricktalmadge/bootstrapper، ولذلك قم بتثبيتهم قبل أن تتابع الدرس. إنشاء نموذجسوف نبدأ بإنشاء نموذج Marketingimage، يمكننا فعل ذلك عن طريق artisan من سطر الأوامر بكتابة السطر التالي: php artisan make:model Marketingimage -mسوف تلاحظ علم m- الذي سيخبر Laravel أنك تريد إنشاء تهجير migration في نفس الوقت، لذلك فهذه الميزة مفيدة للغاية. حسنا، قم بتنفيذ الأمر السابق وستحصل على ملف النموذج والمسمى Marketingimage.php مباشرة تحت دليل تطبيقك وستحصل أيضا على ملف التهجير في مجلد database/migrations. دعونا نقوم بتعديل التابع في أعلى ملف التهجير إلى ما يلي: public function up() { Schema::create('marketing_images', function(Blueprint $table) { $table->increments('id'); $table->boolean('is_active')->default(false); $table->boolean('is_featured')->default(false); $table->string('image_name')->unique(); $table->string('image_path'); $table->string('image_extension', 10); $table->string('mobile_image_name')->unique(); $table->string('mobile_image_path'); $table->string('mobile_extension', 10); $table->timestamps(); }); }أول شيئ يمكنك رؤيته أنني قد غيرت اسم الجدول، فأنا افضل فصل الكلمات في جدول الأسماء بسطر سفلي underscore. أنت حر في اختيار الطريقة التي تعجبك، لكن يجب أن نختار صيغة الجمع لإتباع قواعد Laravel بشكل صحيح. ففي Laravel، النموذج يكتب بصيغة المفرد وأما اسم الجدول فيكتب بصيغة الجمع. بعد عمود المعرف الرقمي، قمنا باستخدام عمودين من نوع المنطقي boolean والتي سوف تسمح لنا بمعرفة هل الصورة نشطة أو مميزة، هذه القيود المفيدة سوف تساعد على العمل مع الصور في وقت لاحق. ثم قمنا بإضافة أعمدة الاسم، المسار والامتدادات للصور وصور الهاتف، وهذا سيسمح لنا بالمرونة الكافية إذا أردت حفظ صورة مختلفة للهاتف، وهذا الأمر ضروري لأن تغيير حجم الصورة قد لا ينتج لنا النتائج المرجوة. وبما أننا سوف نقوم بإنشاء صور مصغرة من الصور الأصلية، لن نحتاج إلى حفظ أية بيانات لذلك. عن طريق حفظ مسار وإمتداد الصورة، سيكون لدينا مرجع سهل نستطيع استخدامه لإظهار الصورة في تطبيقنا، بالإضافة إدارة الصورة في قائمة الصور. عدل على التابع ليبدو على النحو التالي: public function down() { Schema::drop('marketing_images'); }بمجرد أن تقوم بذلك، قم بتنفيذ أمر php artisan migrate من سطر الأوامر وتأكد من أن الجدول قد تم إنشاءه. بعد هذا، سوف نقوم بتعديل نموذج Marketingimage كما يلي: <?php namespace App; use Illuminate\Database\Eloquent\Model; class Marketingimage extends Model { protected $table = 'marketing_images'; protected $fillable = ['is_active', 'is_featured', 'image_name', 'image_path', 'image_extension', 'mobile_image_name', 'mobile_image_path', 'mobile_extension' ]; }سوف تلاحظ أننا قمنا بإخبار النموذج الجدول الذي سيتخذه كمرجع، بالإضافة إلى توفير أعمدة مملوءة تلقائيا، حتى لا نواجه مشكلة الإحالة الكتلية mass-assignment. المتحكمجيد، نحن الآن مستعدين للاستمرار للخطوة القادمة، سنقوم بإنشاء المتحكِّم بإستخدام artisan: php artisan make:controller MarketingImageControllerوبهذا سوف تحصل على متحكِّم في app/Http/Controllers مع التوابع التالية: indexcreatestoreshoweditupdatedestroyوسوف نستخدم جميع هذه التوابع. وكنصيحة مفيدة للمبتدئين، قُم بوضع السطر التالي في تابع index: return 'Here is the index method.';فهذا سوف يعطيك فرصة لتجربة هذا الطريق route. (يستطيع بقية المبرمجين المحترفين تجاوز هذه الخطوة إذا أرادوا) وبعد ذلك، سنقوم بتثبيت الطرق routes. عدل على ملف app/Http/routes.php وأضف التعليمة التالية: Route::resource('marketingimage', 'MarketingImageController');سوف ترى أننا قد قمنا بإضافة مورد resource، والذي سوف يقوم بإعطائنا الطرق routes لجميع الإجراءات actions بطريقة مريحة للغاية. حسنا، سوف تستطيع الآن الذهاب إلى yourproject.com/marketingimage وسوف تحصل على النتيجة التالية: Here is the index method.الخطوة المنطقية التالية هي إعداد العروض views، أنشئ مجلدا باسم marketingimage أسفل resources/views، ثم أنشئ الملفات الفارغة التالية داخل مجلد marketingimages: create.blade.phpedit.blade.phpindex.blade.phpshow.blade.phpإعداد المجلداتسوف نعود إلى تلك الملفات في وقت لاحق، في الوقت الحالي، سنقوم بإنشاء مكان لتخزين صورنا الحالية، سوف أجعل هذا الأمر سهلا، أنشئ مجلدا باسم imgs مباشرة تحت مجلدك العام (public folder)، وبداخل مجلد imgs، أنشئ مجلد marketing، وبداخله أنشئ مجلدا باسم mobile وآخر بإسم thumbnails. الآن قمنا بإنشاء جميع المجلدات للصور. عرض الإنشاء The Create Viewحسنا، دعونا الآن نتعامل مع عرض الإنشاء The Create View. أضف الأسطر التالية داخل ملف `create.blade.php`: @extends('layouts.master') @section('content') {!! Breadcrumb::withLinks(['Home' => '/', 'marketing images' => '/marketingimage', 'create']) !!} <h1>Upload a Photo </h1> <hr/> @if (count($errors) > 0) <div class="alert alert-danger"> <strong>Whoops! </strong> There were some problems with your input. <br> <br> <ul> @foreach ($errors->all() as $error) <li>{{ $error }} </li> @endforeach </ul> </div> @endif {!! Form::open(array('route' => 'marketingimage.store', 'class' => 'form', 'files' => true)) !!} <!-- image name Form Input --> <div class="form-group"> {!! Form::label('image name', 'Image name:') !!} {!! Form::text('image_name', null, ['class' => 'form-control']) !!} </div> <!-- mobile_image_name Form Input --> <div class="form-group"> {!! Form::label('mobile_image_name', 'Mobile Image Name:') !!} {!! Form::text('mobile_image_name', null, ['class' => 'form-control']) !!} </div> <!-- is_something Form Input --> <div class="form-group"> {!! Form::label('is_active', 'Is Active:') !!} {!! Form::checkbox('is_active') !!} </div> <!-- is_featured Form Input --> <div class="form-group"> {!! Form::label('is_featured', 'Is Featured:') !!} {!! Form::checkbox('is_featured') !!} </div> <!-- form field for file --> <div class="form-group"> {!! Form::label('image', 'Primary Image') !!} {!! Form::file('image', null, array('required', 'class'=>'form-control')) !!} </div> <!-- form field for file --> <div class="form-group"> {!! Form::label('mobile_image', 'Mobile Image') !!} {!! Form::file('mobile_image', null, array('required', 'class'=>'form-control')) !!} </div> <div class="form-group"> {!! Form::submit('Upload Photo', array('class'=>'btn btn-primary')) !!} </div> {!! Form::close() !!} @endsectionلاحظ أن الشيفرة في الأعلى ليست صعبة ويمكنك فهمها بسهولة دون أن تضطر إلى قراءة الشرح، ولاحظ أيضا أننا نقوم بتوسيع صفحتنا الرئيسية master page، التي بداخلها مجلد المخططات في مجلد العروض. والتي قمنا باستدعائها عن طريق هذه التعليمة: @extends('layouts.master')إذا كانت لديك صفحة رئيسية أخرى أو أنها موجودة في مكان مختلف، قم بتعديل ذلك حسب الحاجة، وإذا كنت لا تعرف مفهوم الصفحة الرئيسية master page، قُم بالبحث عن دروس حوله وتعلمه قبل أن تتابع الدرس. إذا كنت لا تستخدم حزمة `Bootstrapper`، قم بحذف السطر التالي: {!! Breadcrumb::withLinks(['Home' => '/', 'marketing images' => '/marketingimage', 'create']) !!}لاحظ أيضا، لهذا الدرس، قمت بتضمين `if` لطباعة أخطاء الإدخال، لكن في العادة، يجب وضع هذا الجزء في جزئية العرض view partial ومن ثم الإشارة إليه بشيء مثل هذا: @include('errors.errors')يمكنك أيضا ملاحظة أننا نستخدم مساعد الاستمارة Form helper من حزمة `laravelcollective/html`، فلقد وجدت أن مساعد الاستمارة مفيد جدا خاصة عند استخدامه لفتح الاستمارة: {!! Form::open(array('route' => 'marketingimage.store', 'class' => 'form', 'files' => true)) !!}تستطيع أن ترى أننا قمنا بتضمين 'files => 'true والتي تسمح لنا برفع ملفات متعددة. إذا كنت جديدا في استخدام مساعد الاستمارة، فيمكنك ملاحظة أننا لا نحتاج إلى استخدام POST خاصة وأننا لا نحتاج إلى استدعاء رمز CSFR لأنه يتم ذلك تلقائيا. ثم لدينا مدخلات المختلفة للاستمارة، لا شيء مجنون للغاية هنا، ولدينا أيضا `Form::submit` والتي نستخدمها كزر، بالإضافة إلى `Form::close()`. يمكنك أن ترى من مساعد الاستمارة أن الطريق route تم تعيينه إلى `marketingimage.store`، لذلك سوف نعرف من مورد الطريق في `routes.php` أن هذا سوف يأخذنا إلى تابع `store` في `MarketingImageController.php` والذي هو دليل المتحكِّمات. نُكمل في الجزء الثاني من الدرس. ترجمة -وبتصرّف- للمقال Basic Image Management Part 1 لصاحبه Bill Keck. حقوق الصورة البارزة: Designed by Freepik.
-
تعلمنا إلى الآن مُعظم أساسيات لغة بايثون، تعلمنا كيفية التعامل مع أنواع البيانات المُختلفة، الحصول على مُدخلات من المُستخدم، التعابير الشرطية، حلقات التكرار واستعمال الدوال في برنامجنا لمرونة أكثر. وسنتعلم اليوم كيفيّة التعامل مع الملفات النّصية في لغة بايثون، كيفية الكتابة على ملف، وكيفية قراءة مُحتويات ملف مُعيّن. ما معنى Files I/O؟ ترجمة File هي "ملف" أما I/O فهو اختصار لـكلمتي Input و Output اللتان تعنيان المُدخل والمُخرج على التوالي. تعرفنا إلى الآن على دالتين للقيام بهاتين العمليتين الأولى هي الدالة print للإخراج والدالة raw_input للإدخال. لكنّ هذه الدوال لا تعمل إلا أثناء تشغيل البرنامج، فبعد انتهاء تنفيذه سيعود كل شيء إلى طبيعته وستفقد البيانات التي طبعتها أو التي حصلت عليها من المُستخدم. ماذا لو أردت أن تحتفظ بالبيانات في ملف ما؟ هذا بالضبط ما سنتعلمه اليوم. وإليك مُخطّطا لهذا الدرس: فتح ملف في لغة بايثون. أنماط الوصول Access modes. الكتابة على الملف. قراءة الملف. الدوال المُساعدة عند فتح ملف. إغلاق الملف. الجملة format سأستعمل في هذا الدّرس جملة جديدة لم يسبق لنا أن تحدّثنا عنها في الدروس السابقة وهي جملة format التي تُعتبر بمثابة مُحوّل لأنواع القيم المُختلفة إلى قيمة نصيّة، وتُساعد على دمج أي نوع داخل سلسلة نصّية دون الحاجة إلى تحويله بالدالة str. انظر المثال التالي: >>> '{0}, {1}, {2}'.format('a', 'b', 'c') 'a, b, c' يُمكن تبسيط الشيفرة أعلاه لتكون كالتّالي: >>> '{}, {}, {}'.format('a', 'b', 'c') إليك مثالا لطريقة الاستفادة منها في الواقع: >>> print 'Hello {} : {} : {} : {}'.format('Abdelhadi', 4, 22.4, True) Hello Abdelhadi : 4 : 22.4 : True لاحظ أنّ المُعاملات المُمرّرة للدالة قد أخذت مكان العلامات {} رغم أنّ كلّ قيمة ذات نوع مُختلف عن الأخرى. الطّريقة أعلاه أفضل بكثير من الطّريقة التّقليدية: >>> print 'Hello', 'Abdelhadi', ':', str(4), ':', str(22.4), ':', str(True) Hello Abdelhadi : 4 : 22.4 : True ويُمكنك أيضا أن تؤدي أغراضا أخرى بهذه الجملة، مثلا يُمكنك أن توزع سلسلة نصيّة على أماكن مُعيّنة في السّلسلة كالتالي: >>> '{0}, {1}, {2}'.format(*'abc') 'a, b, c' تستطيع تغيير ترتيب العناصر ببساطة: >>> '{2}, {1}, {0}'.format(*'abc') 'c, b, a' ويُمكنك أيضا أن تدمج عناصر القواميس في السلاسل النّصيّة بسهولة وذلك بالطّريقة التالية: >>> table = {'Abdelhadi': 1929, 'Ahmed': 1222, 'Omar': 1320} >>> print 'Ahmed: {Ahmed:d}; Abdelhadi: {Abdelhadi:d}; Omar: {Omar:d}'.format(**table) Ahmed: 1222; Abdelhadi: 1929; Omar: 1320 لاحظ النّجمتين ** قبل الاسم table. فتح ملف في لغة بايثون قبل أن نتعامل مع أي ملف يجب علينا أولا أن نفتحه، تماما كما تفتح أي ملف نصي للتعديل عليه بمُحرّر النّصوص. لكننا في هذا الدرس سنستعمل لغة بايثون للقيام بذلك. وتوفر لغة بايثون دالة open لفتح الملفات، والتي يُمكنك أن تستخدمها بالشكل التالي: open('filename.txt', 'Access mode') المعامل الأول المُعامل الأول هو اسم الملف، لاحظ أنّك تستطيع استبدال filename بأي اسم تريده ويُمكنك حتى أن تستبدل الامتداد، فمثلا يُمكنك أن تستعمل امتداد ملفات بايثون py بحيث تُصبح الدالة كالتالي: open('python_file.py', 'Access mode') الملف يجب أن يكون في مُجلّد العمل، إذا كنت تستعمل نظام GNU/Linux أو نظام Mac وفتحت مُفسر بايثون أو نفّذت ملفا بامتداد py فالملف يجب أن يكون في المجلد الذي قمت بالعملية منه (في الغالب يكون مجلّد المنزل home). أما إذا كنت تستخدم مُفسر لغة بايثون على نظام Windows فسيكون الملف داخل مجلّد تنصيب حزمة Python والذي غالبا ما يكون في القرص C ومجلد باسم PythonNN مع استبدال NN برقم الإصدار الخاص بلغة بايثون، فمثلا لو قمت بتنصيب الإصدار 2.7 فسيكون مسار المُجلد التالي: C:\Python27 إذا واجهت مشاكل في إيجاد مجلّد العمل يُمكنك تنفيذ الشيفرة التالية للحصول على مسار المُجلّد: >>> import os >>> os.getcwd() المُخرجات ستكون كالتالي (حسب نظام التّشغيل واسم المُستخدم لديك): '/home/dyouri' يُمكنك حفظ المُخرج في مُتغير إذا أردت ذلك. ولا تقلق إذا لم تفهم الأسطر السابقة، إذ سنتحدّث عنها في درس لاحق. المعامل الثاني بالنّسبة للمعامل الثاني (Access mode ) فهو نمط الوصول الذي ترغب بفتح الملف به وهو إما للكتابة أو للقراءة أو كليهما. انظر الفقرة التالية. أنماط الوصول Access modes عند فتح ملف في لغة بايثون، تكون مطالبا بتوفير معاملين للدالة open المُعامل الأول هو اسم الملف، والمعامل الثاني هو نمط الوصول، أي السبب الذي فتحت الملف من أجله، وهناك العديد من الخيارات لذلك، وإليك أهم الخيارات التي يجب عليك أخذها بعين الاعتبار حسب هدفك من فتح الملف: فتح الملف للقراءة r: هذا هو النمط الافتراضي إذا لم تحدد المُعامل الثاني في دالة open ويُمكنك من قراءة ملف بأحد الدوال المُتاحة لذلك (انظر فصل قراءة الملف). مثال: open('file.txt', 'r') r+: يُفتح الملف في هذا النمط للقراءة والكتابة معا، مع وضع مؤشّر الفأرة في بداية الملف. مثال: open('file.txt', 'r+') فتح الملف للكتابة w: يُفتح الملف فقط للكتابة، إذا كان الملف موجودا فإنّه يكتب عليه (Overwrite) أي أنّك ستفقد البيانات الأصلية. إذا لم يكن الملف موجودا فإنّ الدالة تنشئ ملفا جديدا للكتابة. مثال: open('file.txt', 'w') w+: فتح الملف لكل من الكتابة والقراءة، إذا كان الملف موجودا فستتم الكتابة عليه (Overwrite). إذا لم يكن الملف موجودا فإنّ الدالة تنشئ ملفا جديدا للكتابة والقراءة. مثال: open('file.txt', 'w+') a: إذا كان الملف موجودا أصلا، فسيُفتح للإلحاق Appending، أي أنّ مُكونات الملف تبقى كما هي، إذا أضفت أي نصّ فسيُضاف في آخر الملف. إذا لم يكن الملف موجودا فسيتم إنشاء ملف جديد. مثال: open('file.txt', 'a') a+: إذا كان الملف موجودا فإنّه يُفتح لكل من الإلحاق والقراءة، إذا لم يكن موجودا فسيتم إنشاء ملف جديد. مثال: open('file.txt', 'a+') الكتابة على الملف بعد فتح الملف سواء أكان موجودا من قبل أو أنّك أنشأته بالدالة نفسها، ستستطيع الكتابة على الملف وإضافة نصوصك الخاصّة، وذلك بالدالة write مع مُعامل عبارة عن سلسلة نصية، انظر المثال التالي: >>> file = open('file.txt', 'w') # فتح الملف وإسناده إلى مُتغير >>> file.write('Hello World!') # الكتابة بالملف >>> file.close() # إغلاق الملف ملاحظة: إذا كنت تستعمل المُفسّر، فلحفظ التعديلات عليك الخروج من المفسّر أو إغلاق الملف والذي يُمكنك القيام به بالدالة close، مع ملاحظة أنّك لن تتمكن من تعديل الملف بعد إغلاقه، أي أنّك ستحتاج إلى فتحه من جديد بالدالة open. لن تُلاحظ أي مُخرجات عند تنفيذك لأي أمر أعلاه، ولكن رغم ذلك فإنّك إذا فتحت الملف file.txt بأي مُحرّر للنّصوص (Notepad مثلا)، فإنّك ستُلاحظ الجملة !Hello World في بداية الملف. لاحظ بأنّنا فتحنا الملف بنمط الكتابة فقط (w)، إذا فتحت الملف بنفس النّمط مُجدّدا فإنّ التغييرات التي ستكتبها ستُغطّي محتويات الملف. أي أنّك إذا نفّذت الأوامر التاليّة فإنّ مُحتويات الملف ستُصبح الجملة !Hello Python عوضا عن جملة !Hello World # -*- coding: utf-8 -*- >>> file = open('file.txt', 'w') # فتح الملف وإسناده إلى مُتغير >>> file.write('Hello Python!') # الكتابة بالملف >>> file.close() # إغلاق الملف يُمكنك إضافة أكثر من مُدخل في كلّ مرّة، المهم أن تكتب على الملف قبل إغلاقه: >>> file = open('file.txt', 'w') >>> file.write('Abdelhadi Dyouri!') >>> file.write('Hsoub Academy!') >>> file.close() بعد تنفيذ الشيفرة أعلاه، ستكون مُحتويات الملف كالتالي: Abdelhadi Dyouri!Hsoub Academy! لاحظ بأنّ لغة بايثون لا يعود إلى سطر جديد في كل مرة، ولكي تحلّ هذه المسألة فيُمكنك ببساطة إضافة الرّمز n\ بين كل سطر، انظر المثال التّالي: >>> file = open('file.txt', 'w') >>> file.write('Abdelhadi Dyouri!\nHsoub Academy!') >>> file.close() مُحتويات الملفّ بعد تقسيم الأسطر بالرّمز n\ هي كالتالي: Abdelhadi Dyouri! Hsoub Academy! لاحظ بأنّ الشيفرة أعلاه لها نفس تأثير ما يلي: >>> file = open('file.txt', 'w') >>> file.write('Abdelhadi Dyouri!\n') >>> file.write('Hsoub Academy!') >>> file.close() كلّ ما تعلمناه إلى الآن هو كيفية إعادة كتابة الملف، ولكن ماذا لو أردت أن تُبقي على محتويات الملف وترغب بإضافة نصوص له؟ يُمكنك ذلك عن طريق تغيير نمط الوصول إلى نمط الإلحاق عوضا عن نمط الكتابة، لنضف المزيد من النّصوص إلى الملف السابق، إلى الآن مُحتوياته هي كالتالي: Abdelhadi Dyouri! Hsoub Academy! لنضف أقسام الأكاديمية إلى آخر الملف، انظر المثال التالي: >>> file = open('file.txt', 'a') >>> file.write('\nFreelance\nEntrepreneurship\nDesign\nApps\nCertificates\nDevops\nMarketing') >>> file.close() لاحظ تغيير المُعامل الثاني في دالة open من w إلى a. بعد تنفيذ الشيفرة أعلاه ستكون مُحتويات الملفّ كالتالي: Abdelhadi Dyouri! Hsoub Academy! Freelance Entrepreneurship Design Apps Certificates Devops Marketing لنُطبّق ما تعلمناه في الدّروس السابقة ولنضع لكلّ قسم عنوان Url الخاص به: افتح ملفا باسم links.py وضع فيه ما يلي: links = [] list = '\nFreelance\nEntrepreneurship\nDesign\nApps\nCertificates\nDevops\nMarketing' list = list.lower().split('\n') for item in list: list = item.replace(item , 'https://academy.hsoub.com/{}'.format(item)) links.append(list) file = open('file.txt', 'w') file.write('Academy: {}'.format(links[0])) file.write('\nFreelance: {}'.format(links[1])) file.write('\nEntrepreneurship: {}'.format(links[2])) file.write('\nDesign: {}'.format(links[3])) file.write('\nApps: {}'.format(links[4])) file.write('\nCertificates: {}'.format(links[5])) file.write('\nDevops: {}'.format(links[6])) file.write('\nMarketing: {}'.format(links[7])) file.close() أولا عرّفنا قائمة روابط فارغة باسم links بعدها أسندنا الأقسام إلى مُتغيّر باسم list ثمّ حولنا الأحرف إلى أحرف صغيرة و قسّمنا السّلسلة النّصية، بعدها استعملنا الحلقة for للدوران على عناصر القائمة، وفي كلّ مرّة نستبدل قيمة القسم برابطه ونُلحق العنصر النّاتج إلى القائمة links وبعدها فتحنا الملف ووضعنا لكل قسم رابطه الخاص وأخيرا أغلقنا الملف. بعد تنفيذ الشيفرة أعلاه ستكون مُحتويات الملف file.txt كالتالي: Academy: https://academy.hsoub.com/ Freelance: https://academy.hsoub.com/freelance Entrepreneurship: https://academy.hsoub.com/entrepreneurship Design: https://academy.hsoub.com/design Apps: https://academy.hsoub.com/apps Certificates: https://academy.hsoub.com/certificates Devops: https://academy.hsoub.com/devops Marketing: https://academy.hsoub.com/marketing يُمكنك أن تجعل البرنامج أكثر ذكاء وذلك باستبدال قائمة الأقسام بمُدخل من المُستخدم وتُضيف رابط القسم إلى الملف، على سبيل المثال سيعمل البرنامج كالتالي: Enter the name of the category: مثلا لنُدخل programming للحصول على رابط قسم البرمجة، يجب أن تكون المُخرجات شيئا كالتالي: Enter the name of the category: programming Ok! Added https://academy.hsoub.com/programming to file.txt هل رأيت حلاوة البرمجة؟ تذكّر بأنّ خيالك هو حدود ما تستطيع القيام به. قراءة الملف الدالة read بعد الكتابة على الملف سيتوجّب علينا قراءته، كما الكتابة تُوفّر لنا لغة بايثون دالة خاصة بالقراءة وهي الدالة read التي يُمكننا أن نستعملها كالتالي: file = open('file.txt', 'r') file.read() لاحظ أنّنا غيّرنا المُعامل الثاني من w إلى r وذلك لأنّنا نرغب بفتح الملفّ للقراءة. بعد تنفيذ الشيفرة أعلاه ستكون المُخرجات كالتالي: 'Academy: https://academy.hsoub.com/\nFreelance: https://academy.hsoub.com/freelance\nEntrepreneurship: https://academy.hsoub.com/entrepreneurship\nDesign: https://academy.hsoub.com/design\nApps: https://academy.hsoub.com/apps\nCertificates: https://academy.hsoub.com/certificates\nDevops: https://academy.hsoub.com/devops\nMarketing: https://academy.hsoub.com/marketing\n' إذا عاودت تنفيذ الدالة read من جديد فإنّ المُخرج سيكون سلسلة نصيّة فارغة'' وهذا يدلّ على أنّنا وصلنا إلى نهاية الملفّ، ولكي تعود إلى بداية الملف من جديد فعليك فتحه مُجدّدا بالدالة open. كما تُلاحظ فإنّ المُخرجات لا تبدو جميلة أبدا، يُمكنك أن تقرأ أسطر الملف باستخدام جملة for عوضا عن الدالة read وستكون المُخرجات نظيفة هذه المرّة. file = open('file.txt', 'r') for line in file: print line ستكون المُخرجات كالتالي: Academy: https://academy.hsoub.com/ Freelance: https://academy.hsoub.com/freelance Entrepreneurship: https://academy.hsoub.com/entrepreneurship Design: https://academy.hsoub.com/design Apps: https://academy.hsoub.com/apps Certificates: https://academy.hsoub.com/certificates Devops: https://academy.hsoub.com/devops Marketing: https://academy.hsoub.com/marketing يُمكنك أيضا تحديد كم من بايت Byte ترغب بقراءته من بداية الملف. فمثلا إذا كنت ترغب بقراءة أول 8 بايت من مُحتويات الملف، فيُمكنك تمرير العدد 8 إلى الدالة read كمُعامل: >>> file = open('file.txt', 'r') >>> file.read(8) 'Academy:' >>> file.close() المُخرجات ستكون كالتالي (أول 8 أحرف من الملف): 'Academy:' لاحظ بأنّ البايت الواحد لا يعني دائما الحرف الواحد إذ أنّ هناك استثناءات عديدة، فمثلا في اللغة العربية الحرف الواحد يشغل حوالي 2 بايت أما الأحرف الصينية فتشغل حوالي 3 بايت. في الأحرف الإنجليزية عادة ما يُساوي الحرف الواحد 1 بايت فقط. الدالة readline يُمكنك أن تقرأ سطرا واحدا من الملف في كلّ مرّة، وذلك بالاعتماد على جُملة readline عوضا عن جملة read. >>> file = open('file.txt', 'r') >>> file.readline() 'Academy: https://academy.hsoub.com/\n' >>> file.readline() 'Freelance: https://academy.hsoub.com/freelance\n' >>> file.readline() 'Entrepreneurship: https://academy.hsoub.com/entrepreneurship\n' لاحظ بأنّ المُخرج يكون مُختلفا في كلّ مرّة تُستَدعَى فيها الدالة readline إذ أنّ المُخرج يكون سطرا واحدا في كل مرة، وفي المرّة التالية تكون النّتيجة السّطر التالي إلى نهاية الملفّ. في النّهاية سيكون المخرج سلسلة نصيّة فارغة: >>> file.readline() 'Marketing: https://academy.hsoub.com/marketing\n' >>> file.readline() '' إذا أردت العودة إلى بداية الملفّ من جديد فيُمكنك ذلك إما بإغلاق الملف وفتحه من جديد أو باستعمال الدالةّ seek مع تمرير عدد البايتات الذي ترغب بتخطّيه، (أي صفرا للعودة إلى بداية الملف). >>> file.readline() '' >>> file.seek(0) >>> file.readline() 'Academy: https://academy.hsoub.com/\n' يُمكن مثلا العودة إلى أول 8 بايت من الملف بالطّريقة التالية: >>> file.seek(8) >>> file.readline() ' https://academy.hsoub.com/\n' يُمكنك أن تعتمد على الدالة tell لتعرف مركز القراءة الحالي. >>> file.seek(66) >>> file.tell() 66 تقبل الدّالة readline مُعاملا لتحديد عدد البايتات المرغوب قراءتها (تماما مثل شقيقتها read). >>> file.seek(0) # للعودة إلى بداية الملف >>> file.readline(8) 'Academy:' الدالة readlines تُعتبر الدالة readlines طريقة أخرى لقراءة الملف، وتُرجع قائمة بجميع الأسطر التي يحتويها الملف: >>> file = open('file.txt', 'r') >>> file.readlines() ['Academy: https://academy.hsoub.com/\n', 'Freelance: https://academy.hsoub.com/freelance\n', 'Entrepreneurship: https://academy.hsoub.com/entrepreneurship\n', 'Design: https://academy.hsoub.com/design\n', 'Apps: https://academy.hsoub.com/apps\n', 'Certificates: https://academy.hsoub.com/certificates\n', 'Devops: https://academy.hsoub.com/devops\n', 'Marketing: https://academy.hsoub.com/marketing'] يُمكنك مثلا حساب عدد أسطر ملفّ ما بحساب عدد عناصر القائمة بالدالة len: >>> file = open('file.txt', 'r') >>> len(file.readlines()) 8 إغلاق الملف رغم أنّ عمليّة إغلاق الملف ليست ضرورية لحفظ التّغييرات، إلّا أنّ القيام بالأمر منصوح به بشدّة، لذلك يجب عليك أن تتأكّد من أنّ الملفّ قد أُغلق بعد انتهائك من إجراء العمليّات على الملف. لقد تعرّفنا من قبل على كيفيّة إغلاق الملف: >>> file = open('file.txt') >>> file.close() للتحقق من أنّ الملف مُغلق يُمكن أن تستعين بالجملة closed والتي تُرجع قيمة منطقية (إما True أو False). إذا كان الملف مُغلقا فسترجع الجملة True أما إذا لم يكن مغلقا فستُرجع الجملة False. >>> file = open('file.txt') # فتح الملف >>> file.closed # التحقق من أنّ الملف مُغلق False >>> file.close() # إغلاق الملف >>> file.closed # التحقق من جديد True يُمكن كذلك الاستعانة بالجملة with as لفتح ملف والقيام بعمليات ثم إغلاقه آليا. with open('file.txt', 'r') as file: file.read() الملف يُغلق ذاتيا بعد انتهاء الجزء المُزاحِ (ذو الإزاحة) من الشيفرة، ويُمكنك التأكّد من الأمر بالجملة closed. الدوال المساعدة بعد فتح الملف يُمكنك الحصول على معلومات حول الملف ببعض الدوال المبنية مُسبقا Built-in functions وهي كالتالي: closed: التحقق من ما إذا كان الملف مُغلقا أو لا (انظر الفصل السابق). name: الحصول على اسم الملفّ. >>> file = open('file.txt') >>> file.name 'file.txt' mode: الحصول على نمط الوصول. >>> file = open('file.txt', 'w+') >>> file.mode 'w+' تمارين تمرين 1 اكتب برنامجا للحصول على قيم من المُستخدم وأدخلها إلى ملف نصي. تمرين 2 صحّح الخطأ في ما يلي: file = open('file.txt', 'r') file.write('Hello World!') تمرين 3 صحّح الخطأ في ما يلي: file = open('file.txt', 'w') file.write('Hello World!') file.close() file.write('Hello!') تمرين 4 اكتب برنامج تسجيل الدخول في الدروس السابقة ليقبل ملفّا كقاعدة بيانات. (احفظ اسم المُستخدم وكلمة المرور في الملف عوضا عن الذاكرة.) المصادر المعتمدة التوثيق الرّسمي للغة بايثون، فصل الدوال المبنية مُسبقا، الدالة open كتاب Python Practice Book لكاتبه Anand Chitipothu التوثيق الرّسمي للغة بايثون، فصل السلاسل النّصيّة
-
هل وجدتَ موقعك الذي يعتمد على ووردبريس معطلًا وكل ما يمكنك قوله هو «لم أفعل شيئًا! صدقًا!» ومع ذلك سترى رسائل الخطأ التي تقول أنَّ ملفاتك ناقصة أو قاعدة بياناتك تالفة… لا تقلق في حال اختفت المنشورات والتصنيفات فجأةً، أو ظهرت رسائل خطأ مثل: “Warning: require_once(path/to/file.php) [function.require-once]: failed to open stream: No such file or directory in…” أو “Cannot establish database connection.” فسأشرح كيف تحدث مختلف أنواع رسائل الخطأ السابقة، وكيفية حل تلك المشاكل؛ وسأبيّن لك كيف أنَّه من غير المرجّح أن تكون أنت سبب المشكلة. حسنًا، ما هي الفكرة الرئيسية هنا؟ يصعب عادةً معرفة المُسبِّب الرئيسي لأيٍّ من الأخطاء السابقة لوجود عدد كبير (نسبيًا) من المسببات. هذه هي الأسباب الرئيسية التي تؤدي إلى تلف في قاعدة البيانات، أو فقدانها: لم توضَع معلومات الدخول بشكلٍ صحيحٍ في ملف wp-confing.php. حدثت مشكلة في نظام التشغيل. تعطلت إحدى القطع العتادية في الخادوم. حدثت علّة في خادوم MySQL أو مفسر PHP أو في القوالب والإضافات التي تستعملها. استهلاكك للموارد أصبح كبيرًا مما أدى إلى إيقاف محاولة الوصول إلى قاعدة البيانات (مثل PHP memory limit). ربما تعرضتَ إلى هجومٍ إلكتروني، وتم اختراق موقعك. هنالك قائمةٌ أطول للأسباب المحتملة لفقدان ملفاتك: أذونات الملفات غير مضبوطة ضبطًا صحيحًا. الجدار الناري (أو برمجيات الحماية الأخرى) لخادومك يمنع الوصول إلى بعض أجزاء موقعك. أدخلتَ رابط URL للموقع بشكلٍ خاطئ في صفحة «Settings > General» (الإعدادات > عام). الإضافات الخارجية حذفت أحد الملفات أو سببت مشكلةً في المسارات. ثبّتت شهادة SSL ونسيت استبدال روابط الصور. الروابط الدائمة غير مضبوطة ضبطًا صحيحًا. هنالك أخطاء في ملف .htaccess. رُفعِتَ الصور في مجلدٍ خاطئ. تمت مقاطعة عملية رفع المحتوى. هنالك علّة في إضافة أو سكربت أو قالب تستعمله في موقعك. ربما حدثت مشكلة في الخادوم. ربما تعرضتَ إلى هجومٍ إلكتروني، وتم اختراق موقعك. بغض النظر عن المسبب الرئيسي، فهنالك بضع طرائق لإصلاح مشاكل الملفات وقاعدة البيانات. النسخ الاحتياطي والاستعادة منه أسهل طريقة لحل مشكلة تتعلق بقواعد البيانات أو فقدان الملفات هي استعادة نسخة احتياطية من موقعك؛ أما لو لم يكن لديك نسخةٌ احتياطيةٌ لتستعيدها، فهنالك حلولٌ أخرى يمكنك تجربتها. لكن قبل أن تجرِّب الحلول الأخرى، فأنصحك بأخذ نسخة احتياطية لكامل موقعك، حتى لو لم يكن يعمل، لأنَّه قد تسوء بعض الأمور ومن الأفضل أن تكون لديك نسخةٌ أساسيةٌ (حتى لو كانت معطلةً) عوضًا أن تكون خالي الوفاض. ألق نظرة على هذا المقال للمزيد من التفاصيل عن النسخ الاحتياطي: الحماية وإضافات النسخ الاحتياطي في ووردبريس وبعد أن تأخذ نسخةً احتياطيةً من موقعك لتستعملها في حال وقوع كارثة، فأنت جاهزٌ لتبدأ بإصلاح الموقع. إصلاح مشكلة في قاعدة البيانات هنالك عدِّة طرائق يمكنك فيها إصلاح قاعدة البيانات. يمكنك أن تجرب الطريقة الآتية التي تحل أغلبية المشاكل التي تواجه قواعد البيانات. يمكنك إضافة السطر الآتي إلى ملف wp-config.php والموجود في المجلد الجذر لموقعك: define( 'WP_ALLOW_REPAIR', true ); يمكنك إضافة السطر السابق في أي مكان في الملف لكن لا تضفه داخل دالة (على سبيل المثال). أنصحك بوضعه قبل السطر الآتي مباشرةً: /* That's all, stop editing! Happy blogging. */ لتفاصيلٍ إضافيةٍ حول طريقة تعديل ملف wp-config.php فراجع درس «كيف تستخدم FTP لنقل ملفات مدونة ووردبريس الخاص بك؟». بعد أن أضفتَ السطر السابق، فيمكنك زيادة صفحة إصلاح قاعدة البيانات من الرابط الآتي: http://your-site.com/wp-admin/maint/repair.php أو عليك زيارة https://your-site.com/wp-admin/maint/repair.php إذا كانت عندك شهادة SSL. لا تنسَ وضع اسم نطاق موقعك بدلًا من your-site.com. ابقِ في ذهنك أنَّه ليس من الضروري أن تسجِّل دخولك لرؤية هذه الصفحة، لذا بعد انتهاءك من إصلاح قاعدة البيانات، فاحرص على حذف السطر السابق، وإلا فسيستطيع أيُّ شخصٍ الوصولَ إلى تلك الصفحة. عندما تزور الصفحة السابقة، تستطيع أن تضغط على زر «Repair Database» لإصلاح قاعدة البيانات، أو يمكنك إصلاح قاعدة البيانات وتحسينها عبر الضغط على زر «Repair and Optimize Database». بعد إنهاء العملية السابقة، يجب أن يكون موقعك قد أُصلِحَ وأصبحَ جاهزًا للاستعمال. لكن إذا لم تفلح محاولتنا السابقة، فيمكننا إصلاح قاعدة البيانات عبر phpMyAdmin. بعد تسجيل الدخول إلى phpMyAdmin، فاضغط على اسم قاعدة البيانات الموجود في القائمة على يسار الشاشة، ثم بعد ظهور جداول قاعدة البيانات في الصفحة، فمرِّر إلى الأسفل ثم اضغط على مربع الاختيار المُعَنوَن Check All، ثم اختر «Repair table» من القائمة المنسدلة الموجودة بجوار مربع الاختيار. سيتم إصلاح جداول قاعدة البيانات تلقائيًا ويجب أن يعمل موقعك مجددًا. إصلاح الملفات التالفة أو المفقودة لكن ماذا لو كانت ملفاتك هي الناقصة أو التالفة؟ يمكنك إصلاحها أيضًا. إذا ثبّتتَ شهادة SSL في الآونة الأخيرة في موقعك، فقد يبدو أنَّ الصور أمست مفقودةً، ولحلّ هذه المشكلة عليك استبدال روابط الصور لكي تُضمِّن فيها السابقة https. لتفاصيل عن كيفية فعل ذلك، فراجع الدرس «استبدال روابط الصور على مواقع ووردبريس بعد تثبيت شهادة SSL». أما للغالبية العظمى من المشاكل الأخرى، فوضع نسخة جديدة من الملف المعطوب يجب أن يحل المشكلة. يمكنك استخدام FTP للوصول إلى موقعك واستبدال الملفات المعطوبة ووضع أخرى جديدة بدلًا منها، التي يمكنك أن تعثر عليها بتنزيل نسخة من برمجية ووردبريس من موقع WordPress.org. بعد فك ضغط ملف ZIP، يمكنك أن تنقل الملفات الجديدة إلى خادومك، لكن احرص على ترك المجلد /wp-content/ دون تعديل، أو قد تعرِّض نفسك لخسارة جميع ملفات الوسائط والصور التي رفعتها إلى موقعك. يمكنك تطبيق ما سبق على الإضافات والقوالب، لكن الفرق الوحيد هو أنَّ عليك تنزيل نسخة حديثة من الإضافات أو القوالب بدلًا من ووردبريس نفسها. إذا فشل كل ما سبق… إذا جرّبتَ كل ما سبق، لكن لم يحالفك الحظ في تشغيل موقعك، فيمكنك أن تجرّب تفعيل نمط التنقيح في ووردبريس، لتفاصيل عن كيفية فعل ذلك، فارجع إلى درس «Debugging WordPress: How to Use WP_DEBUG». ربما تنظر أيضًا في سجل الأخطاء فلربما استطعت التعرف على المشكلة من هناك، ومن ثم ترسلها إلى شركة الاستضافة لتحليل الخطأ. ابحث عن ملفٍ باسم debug.log داخل مجلد /wp-content/. إذا لم يحّل أيٌّ مما سبق مشكلتك، فحان الوقت لكي تراسل شركة الاستضافة، فقد تكون المشكلة من ضبط الخادوم، أو ربما أصابته مشكلة. والحل الوحيد لهذه المشكلة هو التواصل مع شركة الاستضافة وإعلامها بالأمر. حسنًا، هنالك حلٌّ أخير لا أحبذه: إذا لم تكن لديك نسخةٌ احتياطيةٌ وليست لديك مشكلة مع فقدان بيانات موقعك بالكامل، فيمكنك حذف الموقع وإعادة تثبيت ووردبريس. الخلاصة إذا طبّقتَ ما ذكرناه في هذا الدرس وحالفك الحظ فيجب أن يعمل موقعك عملًا سليمًا دون أن ترى أيّة رسائل خطأ تُشير إلى ملف ناقص أو قاعدة بيانات معطوبة. ولتجنب الصداع الناجم عن محاولة إصلاح الموقع (إذا صَدَفَ وتعطّل) فأنصحك بأخذ نسخ احتياطية دوريًّا. ترجمة -وبتصرّف- للمقال Repairing Corrupted, Broken or Missing Files and Databases in WordPress لصاحبته Jenni McKinnon.
-
يشبه أداء المواقع كثيرًا قاعدة 80/20، حيث إن إجراء تحسينات بنسبة 20% ستزيد سرعة الموقع الإلكتروني بنسبة 80%. فاتّخاذ خطوات بسيطة مثل تنظيم شفرة CSS يأتي بثمار طيّبة. يشرح هذا المقال خطوات بسيطة يمكن أن يؤدّي تطبيقها - إلى جانب تنظيم شفرة CSS - إلى تحسّن ملحوظ في أداء الموقع. تصغير الملفات وضغطها تعدّ إزالة الشفرة المتكررة وغير الضرروية من أبسط الطرق وأفضلها في تقليل حجم ملف CSS، ولكن هناك بعض الطرق الأخرى. تتمثّل إحدى هذه الطرق في تصغير minify وضغط ملفات HTML و CSS و JavaScript. كذلك يمكن ضغط الصور وإزالة التعليقات و مواصفات الألوان Color Profiles غير الضرورية. آلية gzip للضغط آلية gzip هي إحدى أشيع وسائل ضغط الملفات، إذ تأخذ هذه الآلية الملفات الشائعة مثل HTML ،CSS، Javascript وما شابهها وتبدأ بتحديد السلاسل النصية المتشابهة وضغطها. وكلما تم التعرّف على المزيد من السلاسل النصية كان حجم الملفات المضغوطة أصغر، وهذا يعني إرسال ملفات أصغر حجمًا من الخادوم إلى المتصفح. ليست تهيئة gzip بالأمر الصعب، وقد أبلى فريق HTML5 Boilerplate بلاءً حسنًا في هذا المجال. ولضغط الملفات بآلية gzip ستحتاج إلى إضافة ملف .htaccess إلى المجلد الرئيسي في خادوم الويب ثم تدرج في هذا الملف أنواع الملفات التي ترغب في ضغطها. لا تنسَ إضافة النقطة إلى بداية اسم الملف، لأنّ هذا الملف هو من الملفات المخفية. يمكنك أن تجد في إعدادات خادوم Apache في HTML5 Boilerplate أنواع الملفات التي يُنصح بضغطها، ولا بأس بالتذكير مرة أخرى أنّ شفرة ضغط هذه الملفات يجب أن تكون في ملف .htaccess في المجلد الرئيسي لخادوم الويب. وجدير بالذكر أن هذا الملف لا يعمل إلا مع خواديم Apache والتي تتطلب تفعيل الوحدات التالية. mod_setenvif.c mod_headers.c mod_deflate.c mod_filter.c mod_expires.c mod_rewrite.c لا تقلق إن وجدت صعوبة في هذا الأمر، فهناك بعض الخواديم التي تهيّئ لك هذه الأمور نيابة عنك، فبطبيعة الحال، ضغط الملفات وتصغير حجمها يكون دائمًا في مصلحة خادوم الويب. قياس نسبة الضغط تقدّم أداة الفحص Inspector في متصفح Google Chrome عددًا كبيرًا من المعلومات حول أداء الصفحة، ويمكن الوصول إليها من خلال التبويب Network. إضافة إلى ذلك، هناك عدد من المواقع الإلكترونية التي تساعد على معرفة ما إذا كانت خاصية الضغط gzip مفعّلة أم لا. في تبويب Network يتم التعرّف على جميع الملفات المحمّلة بواسطة المتصفح وعرض أحجام تلك الملفات والمدة التي استغرقتها عملية التحميل. لاحظ كيف أن ضغط الملفات قد قلّل من حجمها بنسبة 60% تقريبًا. يمكن التعرّف على أنواع وسائل الضغط التي يدعمها المتصفح من خلال اختيار أحد الملفات. في الصورة أعلاه نلاحظ أنّ المتصفح يدعم gzip، deflate و sdch كما هو مبيّن في ترويسة الطلب المرسل من المتصفح. أما ترويسة Header الإجابة الواردة من الخادوم فتبيّن أن الملف مضغوط بواسطة gzip. ضغط الصور قد يكون تقليل حجم الملفات النصّية مفيدًا، ولكن يمكن الحصول على نتائج أفضل من خلال ضغط ملفات الصور. يمكن لحجم ملفات الصور المستخدمة في الموقع الإلكتروني أن يصبح كبيرًا جدًّا، وضغط الصور يمكن أن يساعد على إبقاء حجم الملفات الكلي تحت السيطرة. يتجنّب الكثيرون مسألة ضغط الصور وذلك خوفًا من أن يتسبب الضغط في تقليل جودة الصورة، ولكن هذا غير صحيح في أغلب الأحيان، إذ يمكن ضغط الصورة دون المساس بجودتها، وذلك من خلال التخلص من مواصفات الألوان والتعليقات غير الضرورية. تتوفّر العديد من الأدوات التي تساعد على ضغط الصور، من أفضلها ImageOptim لنظام Mac و PNGGauntlet لنظام Window، و Trimage لنظام لينكس. تقوم هذه الخدمات بضغط صيغ الصور الأكثر شيوعًا مثل JPG و PNG. نموذج لضغط الصور غير مضغوطة، 455kb مضغوطة، 401kb باستخدام ImageOptim فإنّ حجم الصورة أعلاه قد انخفض بمقدار 14% دون المساس بدقّة الصورة أو جودتها. من الجدير بالذكر هنا أن اختيار أبعاد الصورة في HTML باستخدام خاصيتي height و width يساعد على تصيير الصورة بسرعة أكبر وذلك بتحديد الحجم المناسب للصورة. ولكن يجب الانتباه إلى أن هاتين الخاصيتين تستخدمان في تحديد أبعاد الصورة الحقيقية لا لتصغير حجمها، فمن الممارسات السيئة في هذا الصدد استخدام صورة ذات حجم كبير ثم تصغيرها باستخدام خاصية height و width، والنتيجة تحميل بيانات فائضة عن الحاجة. <img src="ocean.jpg" height="440" width="660" alt="Oceanview"> تقليل طلبات HTTP يشكّل عدد طلبات HTTP - بعد حجم الملفات - العائق الأكبر في طريق تحقيق الأداء الأفضل. ففي كل مرة يُرسل فيها الطلب إلى الخادوم يزداد وقت تحميل الصفحة، وفي بعض الأحيان تتطلب معالجة الطلب من قبل الخادوم الانتهاء من معالجة الطلب السابق، وقد تؤدّي كثرة الطلبات إلى حدوث مشاكل في الخادوم. دمج الملفات المتشابهة إحدى الطرق المتّبعة في تقليل طلبات HTTP - وربّما أسهلها - تتمثّل في دمج الملفات المتشابهة، بمعنى دمج جميع ملفات CSS في ملف واحد وجميع ملفات JavaScript في ملف واحد كذلك. يؤدي دمج هذه الملفات ثم ضغطها إلى إنشاء طلب HTTP واحد صغير نسبيًا. <!-- سيء --> <link href="css/reset.css" rel="stylesheet"> <link href="css/base.css" rel="stylesheet"> <link href="css/site.css" rel="stylesheet"> <!-- جيد --> <link href="css/styles.css" rel="stylesheet"> يجب تحميل ملفات CSS في بداية صفحة الوِب ضمن الوسم head، أما ملفات JavaScript فيجب تحميلها في نهاية الصفحة ضمن الوسم body. والسبب هو أنّه يمكن استكمال تحميل ملفات CSS أثناء تحميل بقية أجزاء الصفحة، في حين أنّه لا يمكن تصيير ملفات JavaScript متعددة في نفس الوقت، لذا فإن هذه الملفات تمنع تحميل بقية عناصر الصفحة. يجب الانتباه هنا إلى ملفات JavaScript تُحمّل لا تزامنيًا Asynchronously بعد اكتمال تصيير الصفحة، وكذلك يجب الانتباه إلى أن JavaScript قد تكون مطلوبة في تصيير عناصر الصفحة كما هو الحال عند اسخدام HTML5 shiv. شرائح الصور Image Sprites المقصود بشرائح الصور في CSS هو استخدام صورة خلفية واحدة في مجموعة من العناصر، والهدف هنا هو تقليل عدد طلبات HTTP الناشئة من استخدام مجموعة من الصور. ولإنشاء شريحة اختر مجموعة من صور الخلفية الأكثر استخدامًا ورتّبها إلى جانب بعضها البعض في صورة واحدة، ثم باستخدام CSS أضف الشريحة كصورة خلفية إلى عنصر معين، ثم استخدم خاصّية background-position لعرض الصورة المطلوبة. بهذه الطريقة، يتم تمرير الصورة خلف العنصر ليقوم الأخير بعرض الجزء الملائم من الصورة. فعلى سبيل المثال إن كانت أبعاد العنصر هي 16 بكسل طولًا و 16 بكسل عرضًا فهذا يعني أنّ هذا العنصر سيعرض 16 بكسل طولًا و 16 بكسل عرضًا من الصورة، أما باقي أجزاء الصورة تكون مخفية. هذا مثال عن شريحة تضم صورًا لأيقونات قائمة محرر النصوص، وقد أحيطت كل صورة بخطوط إرشادية لتوضيح أماكن تغيّر موقع الخلفية. يمكن إنشاء قائمة باستخدام شريحة الصور السابقة وذلك بجعلها خلفية للعنصر span، ثم يمكن تغيير موضع الشريحة بواسطة الأصناف، وبذلك يمكن عرض الأيقونة المناسبة في كل مرة. HTML <ul> <li><a href="#"><span class="bold">Bold Text</span></a></li> <li><a href="#"><span class="italic">Italicize Text</span></a></li> <li><a href="#"><span class="underline">Underline Text</span></a></li> <li><a href="#"><span class="size">Size Text</span></a></li> <li><a href="#"><span class="bullet">Bullet Text</span></a></li> <li><a href="#"><span class="number">Number Text</span></a></li> <li><a href="#"><span class="quote">Quote Text</span></a></li> <li><a href="#"><span class="left">Left Align Text</span></a></li> <li><a href="#"><span class="center">Center Align Text</span></a></li> <li><a href="#"><span class="right">Right Align Text</span></a></li> </ul> CSS ul { margin: 0; padding: 0; } li { float: left; list-style: none; margin: 2px; } li a { background: linear-gradient(#fff, #eee); border: 1px solid #ccc; border-radius: 3px; display: block; padding: 3px; } li a:hover { border-color: #999; } li span { background: url("sprite.png") 0 0 no-repeat; color: transparent; display: block; font: 0/0 a; height: 16px; width: 16px; } .italic { background-position: -16px 0; } .underline { background-position: -32px 0; } .size { background-position: -48px 0; } .bullet { background-position: -64px 0; } .number { background-position: -80px 0; } .quote { background-position: -96px 0; } .left { background-position: -112px 0; } .center { background-position: -128px 0; } .right { background-position: -144px 0; } (تجربة حيّة) معرّف الموارد الموحّد URI الخاص ببيانات الصورة إضافة إلى استخدام شرائح الصور، يمكن الاستفادة من البيانات المُرمَّزة Encoded للصورة وتضمينها مباشرة في HTML و CSS وذلك من خلال معرّف الموارد الموحّد الخاص بالبيانات Data URI، وبهذا لن يُرسَل أي طلب HTTP إلى الخادوم. هذه الطريقة مفيدة للصور الصغيرة والتي لا تكون عرضة للتغيير، وعندما يكون بالإمكان نقل ملفات HTML و CSS إلى ذاكرة التخبئة Cach. ولكن لا يخلو الأمر من مشاكل، إذ يصعب أحيانا تبديل هذه المعرّفات ومتابعتها وقد تحتاج إلى توليد المعرّف مرة أخرى، إضافة إلى أنّها لا تعمل مع المتصفحات القديمة وخصوصًا Internet Explorer 7 وما قبله. إن كان بالإمكان تقليل عدد طلبات HTTP باستخدام هذه الطريقة، وإن كان بالإمكان تخزين ملفات HTML و CSS في ذاكرة التخبئة فإن الفوائد التي ستجينها باستخدام هذه الطريقة تفوق المشاكل المترتبة عنها. هناك عدد من الأدوات التي تساعد في توليد معرّف البيانات مثل هذا المحوّل وأداة Patternify. ومع ذلك تأكّد دائمًا من أنّ حجم البيانات في معرّف البيانات الخاصّ بالصورة أقل حجمًا من ملفّ الصورة الأصلية. HTML <img height="100" width="660" alt="Rigged Pattern" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAICAYAAADA+m62AAAAPUlEQVQYV2NkQAO6m73+X/bdxogujiIAU4RNMVwhuiQ6H6wQl3XI4oy4FMHcCJPHcDS6J2A2EqUQpJhohQAyIyYy0nBAGgAAAABJRU5ErkJggg=="> CSS div { background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAICAYAAADA+m62AAAAPUlEQVQYV2NkQAO6m73+X/bdxogujiIAU4RNMVwhuiQ6H6wQl3XI4oy4FMHcCJPHcDS6J2A2EqUQpJhohQAyIyYy0nBAGgAAAABJRU5ErkJggg==") repeat; } (تجربة حيّة) خزّن الملفات الشائعة في ذاكرة التخبئة هناك طريقة أخرى لتقليل عدد طلبات HTTP المرسلة إلى الخادوم ولعرض الصفحات في وقت أقصر، وتتمثّل هذه الطريقة في إضافة الملفات الشائعة إلى ذاكرة التخبئة. فعند تحميل الصفحة للمرة الأولى يمكن تخزين ملفات معيّنة في ذاكرة التخبئة، وبهذا لن يحتاج المتصفح إلى طلب الملفات ذاتها - لمدة معيّنة - في كل زيارة لتلك الصفحة. تحديد مدّة بقاء هذه الملفات في ذاكرة التخبئة عائد إليك. وكما هو الحال مع ضغط الملفات، فإنّ تعيين مدّة بقاء الملفات في ذاكرة التخبئة يكون من خلال ملف .htaccess. ومرة أخرى فقد أعدّ فريق HTML5 Boilerplate ملفًّا خاصًّا لتعيين تاريخ انتهاء صلاحية الملفات في ذاكرة التخبئة وذلك في إعدادات خادوم Apache الخاصّ بهم. عادة ما تخزّن الصور ومقاطع الفيديو والخطوط وملفات الوسائط المعروفة لمدة شهر في ذاكرة التخبئة، أمّا ملفات CSS و JavaScript فتخزّن في الغالب لمدة عام كامل. وفي حال كانت ملفات CSS أو غيرها من الملفات عرضة للتغير في فترات متقاربة، يمكن تغيير اسم الملف - ومن الأفضل أن يكون الترقيم متسلسلًا - ليُحمَّل الملف من خلال المتصفح. كذلك يمكن تغيير مدة بقاء هذه الملفات في ذاكرة التخبئة إلى قيمة أقل. ExpiresByType text/css "access plus 1 year" ExpiresByType application/javascript "access plus 1 year" إن كانت ملفات CSS و JavaScript تتغيّر في كل أسبوع ولا يُتحكَّم في إصداراتها باستخدام ملفات منفصلة فمن الأفضل تغيير قيمة "access plus 1 year" إلى "access plus 1 week". ويمكن مراجعة صفحة صيغة mod_expires للتعرّف على القيم المتاحة. ترجمة - وبتصرّف - للمقال Performance & Organization لصاحبه Shay Howe. حقوق الصورة البارزة محفوظة لـ Freepik
-
- 4
-
- تحسين الأداء
- smacss
- (و 4 أكثر)
-
في الدروس السابقة قمنا بدراسة الأدوات القياسية والتي لابد من استخدامها في معظم تطبيقات ASP.Net، سنتناول في الدروس القادمة أدوات تحكم أكثر تخصصا وتعرف مجموعة الأدوات هذه باسم Rich controls. في هذا الدرس ستتعلم كيف تسمح للمتصفحين بأن يرفعوا ملفاتهم على الموقع، كأن يقوموا مثلا برفع صور، ملفات فيديو ... إلخ. رفع الملفات إلى الموقع نستخدم أداة التحكم FileUpload لرفع الملفات إلى الموقع، ونقوم بتحديد المكان الذي سيتم تخزين ملفات المستخدمين فيه، إما مجلد داخل الموقع أو ضمن قاعدة بيانات الموقع وسنستعرض كلا الحالتين. خصائص أداة التحكم FileUpload Enabled: تفعيل أو إلغاء تفعيل هذه الأداة. FileBytes: للحصول على محتويات الملف كمصفوفة بايتات. FileContent: للحصول على محتويات الملف كمجرى stream. FileName: الحصول على اسم الملف. HasFile: تعيد True عندما يتم رفع الملف. PostedFile: تعيد الملف المرفوع مغلف بغرض من الصف HttpPostedFile. كما أن أداة التحكم FileUpload تدعم الطرائق التالية: Focus: تسمح بوضع التركيز على هذه الأداة. SaveAs: تقوم بتخزين الملف (المراد رفعه) على الموقع. تقوم الخاصية PostedFile بتغليف الملف المرفوع بغرض HttpPostedFile، هذا الأمر يسمح بالحصول على معلومات إضافية حول الملف. خصائص الصف HttpPostedFile ContentLenght: لمعرفة حجم الملف بالبايتات. ContentType: لمعرفة نوع الملف ( اللاحقة). FileName: لمعرفة اسم الملف. InputStream: الحصول على الملف كمجرى stream. كما أن الصف HttpPostedFile يدعم الطريقة SaveAs والتي تقوم بتخزين الملف على الموقع. لاحظ أن الصف HttpPostedFile يقدم بعض الخصائص المتوفرة مسبقا مع أداة التحكم FileUpload والتي يمكن التعامل معها دون الحاجة للصف HttpPostedFile، على سبيل المثال للحصول على اسم الملف يمكن اتباع أحد الأسلوبين: FileUpload.FileName HttpPostedFile.FileName كما أن الطريقة SaveAs موجودة في الصف HttpPostedFile على الرغم من توافرها مع أداة التحكم FileUpload بشكل صريح. مثال: أنشئ صفحة جديدة وأضف عليها الأدوات FileUpload1 ،Button1 ،Label1. أنشئ مجلد جديد داخل ملفات الموقع باسم uploads لنقوم برفع الملفات إليه، في حدث الضغط على الزر اكتب الكود التالي: كود #C protected void Button1_Click(object sender, EventArgs e) { try { if (FileUpload1.HasFile) { string path = "~/uploads/" + FileUpload1.FileName; FileUpload1.SaveAs(MapPath(path)); Label1.Text = "File Uploaded successfuly..."; } } catch (Exception ex) { } } كود VB Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click If (FileUpload1.HasFile) Then Dim filePath As String = "~/uploads/" & FileUpload1.FileName FileUpload1.SaveAs(MapPath(filePath)) End If End Sub كود الصفحة يجب أن يكون كالتالي: كود ASP.net <div> <asp:FileUpload ID="FileUpload1" runat="server" /> <br /> <asp:Button ID="Button1" runat="server" Text="Upload" onclick="Button1_Click" /> <br /> <asp:Label ID="Label1" runat="server" Text=""/> </div> نفذ التطبيق السابق وحاول رفع ملف ما ( صورة مثلا)، أغلق التنفيذ. يجب أن يكون الملف قد أضيف للمجلد Upload، إن لم تره اضغط على تحديث ملفات الموقع كالتالي: في المثال السابق يستطيع المستخدم أن يرفع أي نوع كان من الملفات، سنقوم في المثال التالي بتحديد الأنماط التي نسمح للمستخدم بأن يقوم برفعها ( فقط بعض أنواع الصور). مثال: أنشئ صفحة جديدة وأضف عليها الأدوات FileUpload1 ،Button1 ،Label1. أنشئ مجلد جديد داخل ملفات الموقع باسم uploads لنقوم برفع الملفات إليه. في حدث الضغط على الزر اكتب الكود التالي: كود #C protected void Button1_Click(object sender, EventArgs e) { try { if (FileUpload1.HasFile) { if (CheckFileType(FileUpload1.FileName)) { string path = "~/uploads/" + FileUpload1.FileName; FileUpload1.SaveAs(MapPath(path)); Label1.Text = "File Uploaded successfuly..."; } } } catch (Exception ex) { } } كود VB Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click If (FileUpload1.HasFile) Then If (CheckFileType(FileUpload1.FileName)) Then Dim filePath As String = "~/uploads/" & FileUpload1.FileName FileUpload1.SaveAs(MapPath(filePath)) End If End If End Sub قم باستدعاء فضاء الأسماء الخاص بالدخل والخرج IO، حيث نضيف الكود التالي أعلى الصفحة: كود #C using System.IO; كود VB Imports System.IO أما الدالة CheckFileType المسؤولة عن فحص نوع الملف فهي: كود #C bool CheckFileType(string fileName) { string ext = Path.GetExtension(fileName); switch (ext.ToLower()) { case ".gif": return true; case ".png": return true; case ".jpg": return true; case ".jpeg": return true; default: return false; } } كود VB Function CheckFileType(ByVal fileName As String) As Boolean Dim ext As String = Path.GetExtension(fileName) Select Case ext.ToLower() Case ".gif" Return True Case ".png" Return True Case ".jpg" Return True Case ".jpeg" Return True Case Else Return False End Select End Function كود الصفحة السابقة: كود ASP.net <div> <asp:FileUpload ID="FileUpload1" runat="server" /> <br /> <asp:Button ID="Button1" runat="server" Text="Upload" onclick="Button1_Click" /> <br /> <asp:Label ID="Label1" runat="server" Text=""/> </div> نفذ التطبيق السابق وحاول أن ترفع ملف ما مغاير للأنواع المحددة، ستلاحظ عدم رفع الملف، أعد التجربة مع أحد أنواع الصور السابقة لترى قبول عملية الرفع. رفع الملفات إلى قاعدة بيانات حيث نقوم بتخزين الملفات في قاعدة بيانات عوضا عن مجلد عادي، هذا الأسلوب يسبب كبر هائل بحجم قاعدة البيانات وبالتالي صعوبة وبطء في نقلها والتعامل معها، كما أننا نحتاج لتحويل الملفات إلى بيانات ثنائية (0,1) لنتمكن من تخزينها في الجدول، الأسلوب الأفضل والمتبع في المواقع هو رفع الملفات إلى مجلد عادي وتخزين أسماء الملفات المرفوعة ضمن قاعدة البيانات مع تخزين معلومات أخرى عنها كتاريخ الرفع مثلا. على العموم لن ندخل بهذه التفاصيل الآن على اعتبار أننا لم نتطرق لموضوع قواعد البيانات، سيكون لنا عودة لمناقشة كيفية رفع الملفات بأسلوب احترافي في الدروس المتقدمة. ملاحظة: يتم قبول رفع الملفات ذات الأحجام أصغر من 4 ميغابايت ( عد للمثال الأول وحاول رفع ملف أكبر من هذا الحجم لترى عدم قبول العملية )، ولتغيير الحجم الأقصى المسموح به لكل ملف، نفتح الملف Web.config ونضيف كود السطر الرابع: كود XML <configuration> <system.web> <compilation debug="true" targetFramework="4.0"/> <httpRuntime maxRequestLength="10240"/> </system.web> </configuration> حيث تم تحديد الحجم الأعظمي بـ 10240 كيلو بايت ( أي 10 ميغا بايت ).
-
يتوفّر إطار العمل Laravel على واجهة تطبيقات برمجيّة API موّحّدة للتعامل مع الملفات. تأتي واجهة التطبيقات هذه مجهّزة مبدئيا بتعريفات Drivers تمكّن من إدارة الملفات على نظام الملفات المحلّي، خادوم FTP أو على خدمتي Amazon S3 وRackspace السّحابيتين. سنعرض في هذا الدرس لأساسيّات إدارة الملفات: رفعها Upload، تخزينها والعثور عليها في الإصدار 5.3 من إطار العمل Laravel. أقراص التخزين في Laravel تُضبَط إعدادات تخزين الملفات ضمن الملف config/filesystems.php عن طريق ما يُسمّيه Laravel الأقراص Disks. يُمثّل كل قرص تعريفا، مسارا للتخزين وإعدادات خاصّة بالقرص. يعرّف ملفّ الإعداد مبدئيا ثلاثة أقراص public، local وs3: 'disks' => [ 'local' => [ 'driver' => 'local', 'root' => storage_path('app'), ], 'public' => [ 'driver' => 'local', 'root' => storage_path('app/public'), 'visibility' => 'public', ], 's3' => [ 'driver' => 's3', 'key' => 'your-key', 'secret' => 'your-secret', 'region' => 'your-region', 'bucket' => 'your-bucket', ], ], يستخدم القرصُ local في المثال المبدئي أعلاه التعريفَ local (نظام الملفات المحلّي) ومسار التخزين storage/app. بالنسبة للقرص s3 فهو يستخدم التعريف s3 (خدمة Amazon S3) ويتطلّب قيما ضرورية للولوج إلى الخدمة. يشبه القرص public القرصَ local؛ إلا أنّ بينهما فرقًا جوهريًّا: هذا القرص مهيّأ للملفات التي نريد إتاحتها للعموم. تُخزَّن ملفات هذا القرص على المسار storage/app/public. يمكن ملاحظة أن المسار storage/app/public يوجد خارج المجلّد public الذي يحوي ملفّات المشروع المتاحة للعموم. نستخدم أمر Artisan التالي لجعل ملفات القرص public متاحة على الوِب: php artisan storage:link ينشئ الأمر وصلة رمزيّة على المسار public/storage ويجعلها تحيل إلىstorage/app/public الذي هو مسار تخزين القرص public. سنرى بعد قليل كيف نصل إلى الملفات الموجودة في هذا القرص. ملحوظة: يتطلّب استخدام التعريفيْن s3 وrackspace تثبيت الحزمتييْن التاليّتيْن على التوالي (عن طريق composer): league/flysystem-aws-s3-v3 ~1.0 league/flysystem-rackspace ~1.0 رفع ملفات وعرض روابطها في Laravel 5.3 سنهيّئ في بقيّة الدرس مشروع Laravel 5.3 للعمل عليه. سيكون هدفنا رفع صورة في المتصفّح ثم عرض هذه الصورة في صفحة الوِب. نضيف مسارين إلى ملف مسارات الوِب routes/web.php: Route::get('image-upload','ImageController@imageUpload'); Route::post('image-upload','ImageController@imageUploadPost'); يتلقّى الإجراء get طلبات عرض الصفحة، في ما نستخدم الإجراء post لتخزين الصّورة المحمَّلة في الصفحة التي سننشئها بعد قليل. الخطوة التاليّة هي إنشاء المتحكّم ImageController وكتابة الدالتين imageUpload وimageUploadPost: php artisan make:controller ImageController كلّ ما تفعله الدالة imageUpload هو استدعاء العرض image-upload: public function imageUpload() { return view('image-upload'); } بالنسبة للدالة imageUploadPost فستستقبل الصورة المحمّلة من المتصفّح، تخزّنها ثم ترسلها إلى image-upload الذي يعرضها: public function imageUploadPost(Request $request) { // TODO: return view('image-upload') ->with('message', "Image uploaded successfully") ->with('path', $imagePath); } الدالة غير مكتملة لحد الساعة، فكل ما يظهر منها هو استدعاء القالب وتمرير رسالة إليه تفيد بنجاح رفع الصورة، إضافة إلى متغيّر يمثّل رابط الصورة. استقبال الصورة، تخزينها والحصول على رابط تخزينها سيكون محلّ التعليق TODO. ننشئ القالب image-upload قبل العودة إلى الدالة imageUploadPost. ننشئ الملف image-upload.blade.php على المسار resources/views ونضع فيه المحتوى التالي: <!DOCTYPE html> <html> <head> <title>Laravel 5.3 Image Upload example</title> </head> <body> <div> @if (isset($path)) <p>{{ $message }}</p> <img src="{{ url($path) }}"> @endif <form action="{{ url('image-upload') }}" enctype="multipart/form-data" method="POST"> {{ csrf_field() }} <div> <div> <input type="file" name="image" /> </div> <div> <button type="submit">Upload</button> </div> </div> </form> </div> </body> </html> نتحقّق أولا، عن طريق الدالة isset، من وجود متغيّر باسم path في المعطيات الممرّرة إلى القالب. يمثّل المتغيّر path مسار الصورة التي نعرضها في حال وجود المتغيّر path. ثم يأتي دور استمارة الرّفع التي ترسل طلبا بإجراء POST إلى المسار image-upload. نحدّد نوع المُدخَل input الذي نريد استقبال الصورة عن طريقه بالنوع file ونحدّد اسمه بـimage. نستطيع الآن العودة إلى الدالة imageUploadPost لإكمالها: public function imageUploadPost(Request $request) { // TODO: return view('image-upload') ->with('message', "Image uploaded successfully") ->with('path', $imagePath); } نستقبل الطلب في المعطى request؛ حيث يمكننا تطبيق الدالة file للحصول على الصورة التي حمّلها المتصفّح بتحديد اسم المُدخَل input الذي استقبلها في صفحة الوٍب: $request->file('image'); نطبّق على الملف الدالة store لتخزينه: $image = $request->file('image')->store('images', 'public'); تأخذ الدالة store معطَيَيْن، الأول منهما هو اسم المجلّد حيثُ نريد تخزين الملفّ والثاني اسم القرص الذي نريد استخدامه. إن لم نحدّد اسمَ القرص فسيُستخدَم القرص المبدئي المعرّف بالتعليمة default ضمن ملف الإعداد config/filesystems (تأخذ التعليمة مبدئيا القيمة local). نريد أن تكون الصورة متاحة للعموم ضمن مجلد خاصّ بالصور اسمه images، لذا نمرّر القيمتيْن images وpublic للمعطييْن الأول والثاني على التوالي. خزّنا الآن الصورة على القرص المتاح للعموم. الخطوة التاليّة هي الحصول على مسارها من أجل إرساله إلى القالب image-upload لعرضه. نستخدم الدالة url ضمن الصنف Storage والتي يمكن تطبيقها على أقراص تستخدم أحد التعريفيْن local أو s3: $imagePath = Storage::url($image); لا ننسى استيراد الصّنف Storage: use Illuminate\Support\Facades\Storage; أصبحت دالة المتحكّم مكتملة على النحو التالي: public function imageUploadPost(Request $request) { $image = $request->file('image')->store('images','public'); $imagePath = Storage::url($image); return view('image-upload') ->with('message', "Image uploaded successfully") ->with('path', $imagePath); } لا ننسى إنشاء الوصلة الرمزية: php artisan storage:link نشغّل خادوم التطوير المضمَّن في Laravel: php artisan serve ثم نفتح المتصفّح لزيارة المسار http://localhost:8000/image-upload. نختار صورة لرفعها ثم نضغط على الزّر Upload. يخزّن Laravel الصّورة في المجلّد storage/app/public، ثم يطلُب عرض القالب image-upload مع تمرير رابط الصّورة في المتغيّر path، إضافة إلى رسالة في المتغيّر message تفيد بنجاح الرّفع. ملحوظة: يختار Laravel عند استخدام الدالة store اسما مميّزا للملف بتطبيق دالة تجزئة Hash عليه. إن أردت اختيار الاسم الذي يُخزَّن به الملف فيمكنك ذلك بالدالة storeAs: تخزين الملف في القرص المبدئي: $image = $request->file('image')->storeAs('images','fileName'); تخزين الملف مع تحديد القرص: $image = $request->file('image')->storeAs('images','fileName','public'); العمليّات على الملفات المرفوعة يوفّر Laravel الصّنفَ Storage للتعامل مع الملفات والأقراص. إضافة ملفات إلى التخزين تُستخدَم الدالة put في الصّنف Storage لتخزين ملفات على النحو التالي: Storage::put('images', $fileContents); يُمثّل المعطى الأوّل الممرَّر إلى الدالة اسمَ المجلّد الذي تريد حفظ الملفّ فيه والثاني محتوى الملفّ. تستخدم الدالة أعلاه القرص المبدئي (التعليمة default في ملف الإعداد). إن أردت استخدام قرص مغاير فيمكنك الاستعانة بالدالة disk: Storage::disk('public')->put('images', $fileContents); يُحدَّد المجلّد المُمرَّر إلى الدالة put (المعطَى الأول) اعتمادا على المسار الجذر للقرص المستخدَم؛ أي أن المقصود بالمجلّد images في المثال السابق هو المجلد storage/app/public/images؛ نظرا لكون storage/app/public هو المسار الجذر للقرص public. يُعيَّن المسار الجذر بالتعليمة root أثناء إعداد الأقراص في ملف الإعداد config/filesystems. استرجاع ملف من التخزين يتيح الصّنف Storage الدالة get لاسترجاع محتوى ملف مخزّن في القرص المبدئي: $contents = Storage::get('images/file.jpg'); يمكن تحديد القرص المستهدَف باستدعاء الدالة disk قبل تطبيق get. يتوفّر الصّنف Storage على الدالة exists التي تتيح التأكد من وجود الملفّ: $exists = Storage::disk('s3')->exists('file.jpg'); الحصول على بيانات ملفّ استخدم الدالة size على النحو التالي لمعرفة حجم ملفّ موجود في القرص المبدئي: $size = Storage::size('file1.jpg'); أو بتحديد القرص المستهدَف: $size = Storage::disk('s3')->size('file1.jpg'); يمكن على نفس المنوال معرفة تاريخ آخر تعديل على الملف على صيغة ختم زمني Timestamp: $time = Storage::lastModified('file1.jpg');
-
تعرفنا في المقال السابق على ملفات الوظائف في قالب Underscores بشئ من التفصيل وفي هذا المقال سنلقي نظرة على ملفات العرض وهي ملفات القالب التي يستخدمها ووردبريس لعرض محتويات الموقع في مختلف الصفحات وكذلك ملفات التنسيق. لكن دعنا في البداية نلقي نراجع بصورة سريعة مفهوم ملفات القالب وكذلك هرمية القالب. ملفات القالب وهرمية القالبملفات القالب Template files هي عبارة عن ملفات قابلة لإعادة الإستخدام Reusable يستخدمها ووردبريس لتوليد صفحات الموقع المختلفة. بعض هذه الملفات (مثل ملف الترويسة header.php وملف التذييل footer.php) تستخدم في جميع صفحات الموقع تقريبا، وبعضها مثل ملف single.php وملف index.php تستخدم في حالات معينة فقط (مثلا الصفحة الرئيسية، أو صفحة عرض المقال). يتبع ووردبريس نظام معين لتحديد ملف القالب الذي سيتم إستخدامه في الصفحة الحالية ويقوم بتحميله عند طلب الصفحة ليستخدم في عرضها. هذا النظام يمكن أن نسميه هرمية القالب في ووردبريس WordPress Template Hierarchy. وفقا لهرمية القالب فإن الملفات الموجودة في القالب قد تختلف من قالب لأخر (وهو ما يحدث عادة) ولكن هنالك ملفات أساسية موجودة في أغلب القوالب، وقالب Underscores بدوره يحتوي على هذه الملفات الأساسية، ويمكنك بالطبع إضافة المزيد من ملفات القالب على حسب المشروع الذي تقوم بتطويره وكذلك يمكنك الإستغناء عن بعضها. ملفات القالب في قالب Underscoresملف الترويسة header.phpهذا الملف من الملفات التي يتم إستخدامها في جميع ملفات القالب الأخرى تقريبا حيث يحتوي على ترويسة الموقع اي بداية وسم html ووسم head وكذلك بداية وسم body، ويحتوي أيضا على عنوان ووصف الموقع وكذلك القائمة الرئيسية للموقع. من الأمور والممارسات الجيدة التي يمكن ملاحظتها في هذا الملف: إستخدام الدالة language_attributes داخل وسم html وهي عبارة عن دالة يوفرها ووردبريس وتعرض خصائص اللغة لوسم html وهي خاصية dir وكذلك خاصية lang وهي مفيدة جدا في حالة تطوير الموقع بأكثر من لغة حيث تقوم بجلب إتجاه اللغة الحالية تلقائيا وكذلك اللغة نفسها.إستخدام الدالة wp_head قبل إغلاق وسم head وهي دالة مهمة جدا يستخدمها ووردبريس في عدة امور وتعتمد عليها مجموعة كبيرة من الإضافات لذلك إذا لم تقم بمناداتها في هذا المكان فقد تتفاجأ بأن كثير من الإضافات لا تعمل في موقعك وكذلك لن يتمكن ووردبريس من ربط ملفات التنسيق والجافا إسكربت في ترويسة الموقع. وفي الحقيقة هي مسئولة من من اداة الحدث وبالتالي مناداة أي دالة مرتبطة به.إستخدام الدالة body_class داخل وسم body والتي تقوم بإخراج كلاسات CSS للصفحة الحالية على حسب الصفحة نفسها، فمثلا في ستجد كلاس home في الصفحة الرئيسية وكلاس blog في صفحة المقالات وغيرها من الكلاسات المفيدة والتي تعينك في تنسيق الموقع إعتمادا على الصفحة نفسها.يتم تضمين هذا الملف في بقية ملفات القالب من خلال الدالة get_header. ملف الفوتر footer.phpمثل ملف الهيدر فإن ملف الفوتر يتم إستخدامه في جميع ملفات القالب الأخرى تقريبا، حيث يحتوي على وسم الإغلاق لكل من html وكذلك body ويحتوي أيضا على الدالة wp_footer والتي يتم مناداتها قبل إغلاق وسم body مباشرة ومهمتها مشابهة لمهمة الدالة wp_head التي ذكرناها اعلاه إلا أن هذه الدالة مرتبطة بالحدث wp_footer وهي بنفس أهمية wp_head وعليك دوما التأكد من أن قالبك يحتوي على كليهما في جميع صفحات الموقع. ملف المقالات (الصفحة الرئيسية) index.phpهذا الملف يستخدم لعرض الصفحة الرئيسية للموقع، أو بصورة أدق صفحة المقالات (لانه يمكنك إستخدام صفحة ثابتة لرئيسية الموقع وعرض المقالات في صفحة اخرى غير الصفحة الرئيسية وهو ما يمكنك التحكم به من خلال إعدادات القراءة في لوحة تحكم ووردبريس). مهمة هذا الملف هو عرض جميع المقالات في الموقع وبالتالي فإن الحلقة Loop في هذا الملف تجلب بصورة تلقائية جميع المقالات، وما يمكن ملاحظته في هذا الملف: يتم تضمين ترويسة الموقع (ملف الترويسة) من خلال إستخدام الدالة get_header كما أسلفنا.يتم إستخدام الدالة get_template_part مع الدالة get_post_format لتضمين ملف الcontent المناسب من داخل مجلد template-parts على حسب بنية المقال بالصورة التالية:get_template_part( 'template-parts/content', get_post_format() );فمثلا عندما تكون بنية المقال إقتباس quote سيتم تحميل ملف content-quote.php من داخل مجلد template-part، وهذا في حالة كان الملف content-quote.php موجودا وإذا لم يكن موجود فإن الدالة get_template_part تقوم تلقائيا بتضمين الملف content.php وهذه إحدى مميزات الدالة get_template_part. وكما سترى فإن هذه الدالة مستخدمة في عدد من ملفات القالب لجلب الأجزاء الموجودة في مجلد template-parts وبهذه الطريقة تصبح ملفات القالب أكثر تنظيما وتصبح الشيفرة البرمجية مقرؤة بصورة أكبر. ملف المقال المفرد single.phpكما هو معلوم لديك فإن ووردبريس يستخدم هذا الملف لعرض المقال المفرد وقد يستخدمه أيضا لعرض صفحة التفاصيل لأنواع المقالات المخصصة الأخرى في بعض الأحيان وفق هرمية القالب التي أشرنا إليها سابقا. ما يمكن ملاحظته في هذا القالب هو إستخدام الدالة get_template_part داخل الحلقة لجلب ملف تفاصيل المقال المفرد وبعد ذلك يتم إستدعاء الدالة the_post_navigation التي تم تعريفها في ملف template-tags.php لعرض المقال السابق والمقال التالي لهذا المقال في حالة وجودهما. بعد ذلك يتم التحقق من إذا ما كانت التعليقات مفتوحة لهذا المقال وفي هذه الحالة يتم جلب ملف comments.php والذي يحتوي نموذج التعليقات وأيضا يعرض التعليقات السابقة في حالة وجودها. وأخيرا يتم جلب ملف sidebar.php من خلال الدالة get_sidebar التي يوفرها ووردبريس، وكذلك يتم جلب ملف الفوتر. ملف الصفحة المفردة page.phpهذا الملف شبه مطابق للملف السابق، فقط داخل الحلقة يتم جلب ملف content-page.php بدلا عن ملف content-single.php. ملف الشريط الجانبي sidebar.phpفي هذا الملف يتم التحقق من وجود أي ودجات نشطة في الشريط الجانبي Sidebar المسمى sidebar-1 وذلك من خلال الدالة is_active_sidebar وفي حالة لم يكن هنالك ودجات نشطة يتم الخروج من الملف وإلا سيتم جلب محتويات الشريط الجاني من خلال الدالة dynamic_sidebar والتي تستقبل معرف الشريط الجانبي لجلبه. ملف الأرشيف archive.phpكما هو معلوم وفق هرمية القالب يتم إستخدام هذا الملف لعرض أرشيف التصنيفات والشهور والكاتب وعموما أي أرشيف إذا لم يكن لديه ملف أرشيف خاص به (مثلا في حالة وجود ملف category.php فحينها سيتم إستخدامه لعرض أرشيف التصنيف ولا يتم إستخدام ملف archive.php لأرشيف التصنيف). نلاحظ أنه في البداية وقبل الدخول الى الحلقة يتم إستخدام الدالتين the_archive_title و the_archive_description لجلب عنوان ووصف الأرشيف على التوالي، وبعد ذلك تجد بقية الملف مشابه لملفات single.php وpage.php طبعا مع إختلاف الملف content الذي يتم جلبه حيث يتم جلبه هاهنا وفق تنسيق المقال كما في ملف index.php. ونلاحظ فرق أخر في هذا الملف وهو أنه في حالة لم يكن هنالك محتويات في الأرشيف الحالي يتم جلب ملف content-none.php والذي في هذه الحالة يخرج رسالة للزائر تفيده بأنه لا يمكن إيجاد المحتوى المطلوب بالإضافة لنموذج البحث. وقبل ذلك وبعد نهاية الحلقة يتم إستدعاء الدالة the_posts_navigation التي تم تعريفها في ملف template-tags.php والتي تعرض روابط التنقل بين المقالات (الصفحة السابقة والصفحة التالية). ملف البحث search.phpفي بداية هذا الملف وقبل الدخول الى الحلقة يتم عرض عنوان يشير الى كلمة البحث (يمكن ان يترجم إلى نتائج البحث عن: "كلمات البحث") حيث يتم الوصول الى الكلمة التي بحث عنها المستخدم من خلال الدالة get_search_query التي يوفرها ووردبريس. بعد ذلك يتم عرض نتائج البحث في حالة وجودها من خلال إستدعاء ملف content-search.php وفي حالة عدم وجود نتائج مطابقة يتم إستدعاء الملف content-none.php والذي في هذه الحالة يعرض رسالة للزائر تفيده بأنه لم يتم إيجاد نتائج مطابقة وتقترح عليه إستخدام كلمات أخرى في البحث ويرفق له نموذج البحث. ملف الخطأ 404.phpيستخدم هذا الملف لعرض صفحة الخطأ المشهورة 404 وفي قالب underscores تم برمجته بحيث يقدم فائدة كبيرة للمستخدم حيث أنه بالإضافة لعنوان الصفحة ورسالة الخطأ يقوم بعرض نموذج البحث، وودجت أخر المقالات، والتصنيفات الأكثر إستخداما في المدونة، والأرشيف الشهري للمدونة، بالإضافة لسحابة الوسوم. ملف التعليقات comments.phpيستخدم هذا الملف لعرض التعليقات السابقة ونموذج التعليقات لكل من الصفحات والمقالات في حالة كانت التعليقات مفتوحة للمقال المعين. وربما نخصص لطريقة برمجة ملف التعليقات في ووردبريس مقالا مفردا لنتعرف على أهم الدوال التي يوفرها ووردبريس للتعليفات وطريقة إستخدامها، وحاليا يمكنك إستخدام هذا الملف كما هو في قالبك مع التعديل على التنسيق بما يتناسب مع تصميم القالب. ملفات التنسيق في قالب Undescoresلا يجبرك قالب Underscores على إستخدام ملفات التنسيق الموجودة فيه ويمكنك بكل بساطة مسحها أو مسح محتوياتها والبدء بكاتبة شيفراتك الخاصة، لكنه يوفر لك بعض الأمور الأساسية المهمة في تنسيق قوالب ووردبريس لتبني عليها كما سنرى. ملف style.cssكما هو معلوم فإن هذا الملف من الملفات الأساسية التي لا بد من وجودها في أي قالب ووردبريس ليعمل حيث يستخدم ووردبريس الترويسة الموجودة في هذا القالب والمكتوبة كتعليق ليأخذ منها معلومات القالب التي سيعرضها في لوحة التحكم لذلك لابد من إرفاق هذا القالب وكتابة هذه المعلومات في أي قالب ووردبريس، لكنك غير مجبر على كتابة تنسيقات القالب في هذا الملف ولا ربطه في ترويسة الموقع (من خلال إستخدام الدالة wp_enqueue_style كما أشرنا لذلك في المقال السابق) ولكن يحسن بك أن تستخدمه ما دام ليس هنالك مانع يمنعك من إستخدامه. بعد ترويسة هذا الملف تلاحظ وجود تعليق طويل هو عبارة عن جدول لمحتويات الملف، وهذه من الأشياء التي يمكنك تعلمها من قالب Underscores ليسهل فهم ملف التنسيق والوصول لأي جزء فيه فيما بعد بسرعة أكبر. وكما هو ملاحظ في جدول المحتويات فإن هذا الملف يحتوي مسبقا على الأمور الأساسية في تنسيقات CSS حيث يحتوي على Normalize لعناصر html وتنسيقات الخطوط والعناصر والنماذج وهذه الثلاثة الأخيرة يمكنك تعديلها بما يتناسب معك. بعد ذلك يحتوي على تنسيقات التنقل وتنقسم الى الروابط والقائمة، وفي تنسيقات القائمة ستجد بعد الأصناف المعدة مسبقا لتضيف عليها تنسيقات القائمة (وفق الصنف الذي تم كتابته في القائمة في ملف header.php)وبعض التنسيقات الأساسية التي تجدها مكتوبة بل إن القائمة معدة مسبقا للعمل في الأجهزة الصغيرة من خلال توفير تنسيقات مختلفة لهذه الأجهزة من خلال Media queries وهنالك أيضا ملف navigation.js المسئول عن إضافة وحذف بعض الأصناف على حسب عرض الجهاز المستخدم لتصفح الموقع وهذا يعني أن القائمة شبه جاهزة لديك وعليك فقط إضافة القليل من الشيفرات لتتناسب مع تنسيق القالب الخاص بك. بعد ذلك يحتوي الملف على تنسيقات خاصة بإمكانية الوصول والمحازاة وتنظيف الfloat، وبعدها بعض التنسيقات الخاصة بالودجات. وبعدها تسنيقات المحتويات (الصفحات والمقالات والتعليقات) وتلاخظ فيها إستخدام بعض الأصناف التي يولدها ووردبريس سواء في وسم body أو وسم المقال نفسه من خلال الدالتين body_class و post_class على التوالي، وبعدها تنسيقات خاصة بـ Infinite scroll في إضافة Jetpack. بعد ذلك هنالك التنسيقات الخاصة بالميديا وهذه التنسيقات مفيدة لمعرفة الأصناف التي يولدها ووردبريس مع الميديا مثل Caption الخاص بالصور والمعرض Gallery. ملف التنسيق لللغات من اليمين للشمال rtl.cssفي حالة كانت لغة العرض للموقع تتبع التنسيق من اليمين للشمال مثل اللغة العربية يقوم ووردبريس تلقائيا بربط الملف المسمى rtl.css في ترويسة الموقع في حالة وجوده في القالب، بالتالي يحسن وضع التنسيقات المختصة بهذه اللغات في هذا الملف حيث أن ووردبريس يقوم بربطه بعد ملف style.css وهذا يعني أن التنسيقات في هذا الملف سيكون لها أولوية للتنسيقات المشابهة في ملف style.css كما هو معلوم في لغة CSS. خاتمةكما تلاحظ فإن ملفات العرض (ملفات القالب) في قوالب ووردبريس تعتمد بصورة كبيرة على فهم هرمية القالب والحلقة وكذلك معرفة وسوم القالب التي يوفرها ووردبريس ومنها الوسوم الشرطية وقد تحتاج أيضا لإنشاء دوال أخرى لإستخدامها ورأينا أنه من المهم أيضا معرفة الأصناف التي يولدها ووردبريس لتستطيع الإستفادة منها في تنسيق القالب وفق الصفحة والمقال وتنسيق طريقة عرض الميديا. بهذا نكون وصلنا لختام هذه السلسلة التي ألقينا فيها نظرة سريعة على ملفات قالب Underscores بشيء من التفصيل وتعلمنا منه بعض الأمور المفيدة في تطوير قوالب وودربريس.
- 1 تعليق
-
- 1
-
- underscore
- تنسيق
-
(و 2 أكثر)
موسوم في:
-
يمكن القراءة والكتابة من وإلى الملفات النصيّة في سي شارب بعدّة طرق. سنتناول أسلوبًا بسيطًا وذلك من خلال الصنفين StreamWriter و StreamReader. يسمح الصنف StreamWriter بالكتابة فقط، أمّا الصنف StreamReader فهو يسمح بالقراءة فقط. كما يمكن استخدام كلا الصنفين في نفس البرنامج. وكلّ منهما موجود ضمن نطاق الاسم System.IO. يرث الصنف StreamWriter من الصنف TextWriter في حين يرث الصنف StreamReader من الصنف TextReader. الكتابة إلى ملف نصي سنعمل في البرنامج Lesson12_01 على إنشاء الملف data.txt وكتابة بعض الأسطر ضمنه: 1 using System; 2 using System.IO; 3 4 namespace Lesson12_01 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 string[] lines = { "First Line", "Second Line", "Third Line" }; 11 12 StreamWriter fileWriter = new StreamWriter("data.txt"); 13 14 foreach (string line in lines) 15 { 16 fileWriter.WriteLine(line); 17 } 18 19 fileWriter.Close(); 20 } 21 } 22 } صرّحنا في السطر 10 عن المصفوفة lines التي عناصرها نصوص، لاحظ أنّنا استخدمنا الطريقة المختصرة لإنشاء كائن مصفوفة وإسناد العناصر الموجودة ضمن الحاضنة {} إلى عناصره مباشرةً. نصرّح في السطر 12 عن المتغيّر fileWriter حيث نسند إليه كائن من الصنف StreamWriter. عند إنشاء هذا الكائن، مرّرنا اسم الملف "data.txt" إلى بانية الصنف StreamWriter. في الحقيقة تخضع هذه البانية إلى زيادة التحميل overloading، حيث تمتلك ثمانية أشكال مختلفة اخترنا أبسطها، وهو مسار واسم الملف المراد إنشاؤه. وبما أنّنا مرّرنا الاسم فقط دون المسار، فسيتم إنشاء هذا الملف في نفس المجلّد الموجود ضمنه الملف التنفيذي للبرنامج. بعد ذلك نستخدم التابع WriteLine من المتغيّر fileWriter لكتابة عناصر المصفوفة lines على أسطر منفصلة ضمن الملف data.txt. العبارة البرمجيّة في السطر 19 ضرورية لإغلاق الملف باستدعاء التابع Close وتحرير المصدر الذي يحجزه في نظام التشغيل. جرّب تنفيذ البرنامج، لن تحصل على شيء على الشاشة، ولكن إذا فتحت الملف data.txt (ستجده غالبًا ضمن bin\debug ضمن مجلّد المشروع) ستجد الأسطر الثلاثة موجودةً ضمنه. ملاحظة: يوجد شكل آخر لبانية الصنف StreamWriter يقبل بالإضافة إلى اسم الملف ومساره قيمة منطقيّة (من نوع bool) تُدعى append. إذا مرّرت true مكانها فسيعمل البرنامج إلى الإضافة إلى محتويات الملف data.txt، أمّا إذا مرّرت false فسيعمل على الكتابة عليه. أمّا إذا أهملت هذا الشكل تمامًا كما هو الحال في مثالنا فسيعمل البرنامج على الكتابة على الملف، أي استبدال محتوياته، في كلّ مرّة ننفّذ فيها البرنامج. في الحقيقة ليس هذا هو الاستخدام الأمثل للصنف StreamWriter والسبب في ذلك أنّ مصادر نظام التشغيل محدودة، حيث يؤدّي التعامل مع الملفات إلى حجز بعض من هذه المصادر، لذلك ينبغي تحرير هذه المصادر فورًا عندما تنتفي الحاجة إليها. قد يبدو أنّنا قد فعلنا ذلك باستخدام التابع Close وهذا صحيح تمامًا، ولكن ليس بالسرعة القصوى الممكنة! هناك أسلوب آخر يسمح بتحرير المصادر بشكل أكثر فعاليّة وسرعة باستخدام الكلمة المحجوزة using. سأعدّل البرنامج Lesson12_01 ليستخدم هذا الأسلوب الجديد. انظر البرنامج Lesson12_02 بعد التعديل: 1 using System; 2 using System.IO; 3 4 namespace Lesson12_02 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 string[] lines = { "First Line", "Second Line", "Third Line" }; 11 12 using (StreamWriter fileWriter = new StreamWriter("data.txt")) 13 { 14 foreach (string line in lines) 15 { 16 fileWriter.WriteLine(line); 17 } 18 } 19 } 20 } 21 } لاحظ السطر 12 كيف وضعنا عبارة التصريح عن المتغيّر fileWriter والإسناد إليه ضمن عبارة using. في الواقع لن يكون المتغيّر fileWriter مرئيًّا خارج حاضنة using (من السطر 13 حتى السطر 18)، وبمجرّد وصول تنفيذ البرنامج إلى السطر 19 سيتم إغلاق الملف فورًا وتحرير المصدر الذي يحجزه. يظهر من البرنامج السابق أنّنا لم نعد نحتاج إلى استخدام التابع Close. القراءة من ملف نصي سنستخدم الصنف StreamReader لهذا الغرض. سيعمل البرنامج Lesson12_03 على قراءة محتويات الملف data.txt السابق وعرضها على الشاشة: 1 using System; 2 using System.IO; 3 4 namespace Lesson12_03 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 using (StreamReader fileReader = new StreamReader("data.txt")) 11 { 12 while(!fileReader.EndOfStream) 13 { 14 string line = fileReader.ReadLine(); 15 Console.WriteLine(line); 16 } 17 } 18 } 19 } 20 } تخضع بانية الصنف StringReader أيضًا لزيادة التحميل، حيث تمتلك 11 شكلًا مختلفًا تسمح للمبرمج بالتحكّم الكامل بكيفيّة القراءة من الملف. أبسط هذه الأشكال هو الشكل الذي استخدمناه في البرنامج Lesson12_03 حيث سنمرّر لهذه البانية اسم الملف data.txt الذي أنشأناه في البرنامج Lesson12_02 السابق. استخدمنا في هذا البرنامج أيضًا العبارة using (من السطر 10 حتى السطر 17) لتحرير المصدر الذي يحجزه الملف عند الانتهاء من القراءة. ننشئ كائن من الصنف StreamReader ونسنده إلى المتغيّر fileReader ضمن عبارة using في السطر 10. ثمّ نستخدم حلقة while لقراءة محتويات الملف، وذلك لأنّنا من الناحية النظريّة لا نعلم بالتحديد كم سطرًا يحوي الملف. لاحظ شرط استمرار حلقة while حيث تُرجع الخاصيّة EndOfStream للمتغيّر fileReader القيمة true إذا وصلنا إلى نهاية الملف أثناء عمليّة القراءة، وإلّا فإنّها تُرجع false. إذًا، في حال لم نصل بعد إلى نهاية الملف ستُرجع الخاصيّة القيمة EndOfStream القيمة false وبسبب وجود عامل النفي المنطقي (!) قبل هذه الخاصيّة مباشرةً، ستكون القيمة النهائيّة لهذا التعبير هو true مما يسمح لحلقة while بالاستمرار. أمّا عند الوصول إلى نهاية الملف سيحدث العكس تماماً مما يجعل شرط استمرار الحلقة false وينتهي تنفيذ الحلقة. نقرأ في السطر 14 سطرًا من الملف data.txt ونسنده إلى المتغيّر النصي line في كل دورة، ثمّ نطبع محتويات هذا المتغيّر إلى الشاشة في السطر 15. استخدمنا في عمليّة قراءة سطر من الملف data.txt التابع ReadLine من المتغيّر fileReader الذي يعمل على قراءة سطر واحد في كلّ مرّة من الملف data.txt. تمارين داعمة تمرين 1 اكتب برنامجًا يطلب من المستخدم إدخال خمس جُمل، ثم يعمل على تخزين هذه الجُمل على اعتبار أنّ كل جملة يُدخلها المستخدم تمثّل سطرًا نصيًّا. تخزّن كل جملة مع رقم سطرها بحيث يفصل بينهما محرف الجدولة (\t). تمرين 2 استفد من الصنف Student التالي: class Student { public string Name { get; set; } public int Mark { get; set; } } في كتابة برنامج يطلب من المستخدم إدخال بيانات خمسة طلّاب (اسم الطالب Name، والدرجة Mark) مستخدمًا المجموعة العموميّة <List<Student في تخزين بيانات هؤلاء الطلّاب (ستحتاج إلى استخدام نطاق الاسم System.Collections.Generic في بداية البرنامج). بعد الانتهاء من الإدخال، يجب على البرنامج حفظ بيانات هؤلاء الطلّاب ضمن الملف students.txt على شكل جدول بسيط، بحيث تصبح محتويات الملف مشابهة للشكل التالي: Amjad 50 Mohammad 80 Mazen 90 Nour 88 Anwar 40 الخلاصة تعرّفنا في هذا الدرس على المبادئ الأساسيّة في التعامل مع الملفات النصيّة. حيث تعلّمنا كيفيّة القراءة من الملف النصيّ وكيفيّة الكتابة إليه. وتعلّمنا أساليب مهمّة عند فتح الملف للقراءة أو الكتابة تتمثّل في استخدام العبارة using لكي نحرّر المصدر الذي يحجزه الملف فور الانتهاء من التعامل معه.
-
- streamwriter
- streamreader
-
(و 4 أكثر)
موسوم في:
-
تحدد صلاحيّات الملفّات من يستطيع قراءة، إنشاء، تحرير ملف و/أو فتحه، وهذه العملية مهمّة في ووردبريس، لأنها قد تحتاج إلى إمكانية إنشاء ملفات جديدة في مجلد wp-content الّلازمة لعمل بعض الوظائف. إن عدم امتلاك ملفات الموقع للصلاحيات الضرورية والكافية يفتح المجال للآخرين للتطفّل على ملفّات موقعك، وقد لا يحميك تعيين الصلاحيات بشكل صحيح من جميع الهجمات الإلكترونية، لكنه سيساعدك في جعل موقعك أكثر أمانًا، حيث سيكون إجراءً أمنيًّا آخر يضاف إلى إجراءاتك الأمنية الحالية. يحتوي توثيق ووردبريس على بعض المعلومات حول صلاحيات الملفات الضرورية لـ ووردبريس، لكن قد يكون من الصعب متابعته لأنّه لا يشرح التفاصيل، لذا يهدف المقال إلى شرح تفاصيل صلاحيات الملفات والمجلّدات وكيفية تغييرها بغرض رفع أمان الموقع. كيف تبدو صلاحيات الملفات؟ توجد فئتان يجب أخذهما بعين الاعتبار عند التحدّث عن صلاحيات الملفّات: العمليّات ومستخدمو العمليّات. العمليّات وهي العمليات التي من الممكن تنفيذها على الملفّات: القراءة Read: تسمح بقراءة محتوى ملف فقط، ويتم تمثيلها بالحرف r كما سنرى لاحقًا. الكتابة Write: تسمح بإنشاء ملف جديد و/أو تعديل محتوى ملف موجود مسبقًا، ويتم تمثيلها بالحرف w. التنفيذ Execute: تعطي إمكانية تنفيذ الملف بغرض تشغيله كبرنامج أو سكربت، ويتم تمثيلها بالحرف x. ملاحظة: يجب الانتباه إلى عدم الخلط ما بين عمليّتي القراءة والتنفيذ، فالأولى تسمح بقراءة محتوى ملف (سواء كان ملف نصّي، أو صورة، أو برنامج حتّى) ولكنّها لازمة وغير كافية لتنفيذ محتوى الملف إن كان برنامجًا، فحينها يجب أن يمتلك ملف البرنامج إمكانيّتي القراءة والتنفيذ كي يكون بالإمكان تشغيله كبرنامج. أما مستخدمو العمليات فهم: المستخدم User: وهو مالك الملف owner، المجموعة Group: ويمكن أن تضم مستخدمين آخرين لهم صلاحية الوصول إلى الملفات التي تختارها والتي لهذه المجموعة صلاحية الوصول إليها; الطرف الثالث World: أي مستخدم آخر عدا ما ذُكر. ويمكن تمثيل صلاحيات الملفّات كمجموعات متتالية من الأرقام على الشكل rwxrwxrwx-: الرقم الأول rwx: صلاحيات الوصول الخاصة بمالك الملف user (أو owner). الرقم الثاني rwx: صلاحيات الوصول الخاصة بالمجموعة group. الرقم الثالث rwx: صلاحيات الوصول الخاصة بالطرف الثالث world. وللحصول على قيمة الرقم الخاص بِكلّ مجموعة سنقوم اعتمادًا على النظام الثنائيّ binary باستنباط الجدول التالي: نظام rwx الثُنائي binary القيمة بالنظام العُشري decimal إمكانيّة Read/Write/Execute 000 0 001 1 تنفيذ فقط 010 2 كتابة فقط 011 3 كتابة + تنفيذ 100 4 قراءة فقط 101 5 قراءة + تنفيذ 110 6 قراءة + كتابة 111 7 قراءة + كتابة + تنفيذ فاستنادًا للجدول السابق فإن أعلى صلاحية rwxrwxrwx- يمكن منحها بالنظام العُشريّ هي 777 حيث يكون لكلٍّ من المالك، المجموعة والطرف الثالث جميعهم، إمكانية القراءة والكتابة والتنفيذ، وبنفس الشكل يمكن القول بأنّ أقلّ صلاحية rwxrwxrwx- يمكن منحها (إلى جانب عدم وجود أيّ صلاحية على الإطلاق) هي 444، حيث يملك الجميع إمكانية القراءة فقط. لا تخف فهناك طريقة سهلة لتذكر الصلاحيات، فعلى سبيل المثال لو أردنا إعطاء مالك الملف كامل الصلاحيات والحدّ من صلاحيات باقي المستخدمين، فنقوم بما يلي: المستخدم User – سيملك إمكانية القراءة (4)، الكتابة (2) والتنفيذ (1)، فتكون قيمة الصلاحية النهائية (1+2+4=7) المجموعة Group – ستملك إمكانية القراءة (4) والكتابة (2)، فتكون قيمة الصلاحية النهائية (4+2=6) الطرف الثالث World – سيملك إمكانية القراءة فقط (4). إذًا، تصبح صلاحية الملف النهائيّة 764 أو rwxrw-r-- في هذا المثال، ولكنّ هذه الصلاحية غير مثاليّة لملفات مدوّنات ووردبريس، فقد تلاحظ بأن صلاحيات الملفّات تبدو مختلفة قليلًا عند التحقق منها عبر SSH أو FTP، كما في الصورة: تذكّر بأن الـ - (hyphen) في صيغة صلاحيّات الملفّات تمثّل غياب إمكانية ما، عدا أوّل - إلى أقصى اليسار والتي تبيّن فيما إذا كانت الصلاحية لملف أو مجلّد، فإن كانت لمجلّد حلّ محلّها الحرف d، الحرف الأول من كلمة directory. تجدر الإشارة إلى أنّ المحرف الأول إلى اليسار قد يملك قيمًا مختلفة عن الحرف d ولكن يندر أن تصادف هذا في ووردبريس. وكما ذكرنا سابقًا فإنّ كلّ مجموعة تمثّل الإمكانيات المسموحة لكل مجموعة مستخدمين، فإن أخذنا الصلاحية التالية rwxr-xr-x- فإنّ الـ - في أقصى اليسار تخبرنا بأنّ هذه صلاحية ملف، أما الـ rwx التي تليها فتخبرنا بأنّ المستخدم مالك الملف يملك إمكانية القراءة والكتابة والتنفيذ، بينما تملك مجموعة المستخدمين المالكة للملف إمكانية القراءة والتنفيذ، وأخيرًا يكون لباقي المستخدمين إمكانية القراءة والتنفيذ أيضًا، فإن قُمنا بتحويل نمط الصلاحية هذا إلى الشكل الرقمي لحصلنا على القيمة 755. من الجدير بالذكر بعد هذا الشرح المطوّل بأنّ الصلاحية 777 تعطي جميع المستخدمين كامل الصلاحيات وهذا غير مناسب أمنيًّا ويجب عدم استخدامه لمواقع ووردبريس على الأقل، وفي الوقت ذاته فإنّ الصلاحية 444 لن تكفي ليعمل موقع يستخدم ووردبريس. ما الصلاحيات اللازمة لمواقع ووردبريس؟ إن قمت بتنصيب ووردبريس بنفسك فإنّ الصلاحيات ستكون معدّة بشكل صحيح غالبًا، ولكن إن كنت تحصل على رسائل خطأ بصلاحيات الوصول أو كان موقعك معدًّا من قبل شخص آخر، فإنّ الوقت مناسب لمراجعة صلاحيات الملفّات. تختلف الصلاحيات المطلوبة باختلاف الإضافات plugins التي قد تستخدمها في موقعك والتي تتبع لطبيعة عمل الـ plugin، وستعتمد صلاحية الملفات والمجلّدات على إعدادات استضافتك، فإن كنت تستخدم خادومًا خاصًا بك بالكامل (dedicated server) فإنّ بالإمكان استخدام الصلاحيات التالية بشكل آمن تبعًا لما يذكره توثيق ووردبريس: للمجلّدات – 755 للملفّات – 644 أمّا الملفّات الأكثر خصوصية كملف الإعدادات الخاصة بـ ووردبريس والذي يتضمن معلومات حسّاسة wp-config.php، فيمكن استخدام الصلاحية 600 معه، ويستثنى من ذلك ملف htaccess. والذي يحتاج موقع ووردبريس للوصول إليه ليتم تحديث محتواه بشكل اوتوماتيكي، فينصح باستخدام الصلاحية 644 معه أو الصلاحية الأكثر أمنًا 604 في معظم الحالات. كيف يمكن التحكم بصلاحيات الملفات؟ يمكن إيجاد صلاحيات الملفات المذكورة على أنظمة لينكس/يونكس فقط، فإن فرضنا أنّ الاستضافة مزوّدة بلوحة تحكّم cPanel فعندها للوصول إلى صلاحيات الملفات نتوجّه بعد تسجيل الدخول إلى: Files > File Manager وعند ظهور نافذة اختيار المجلّد الرئيسي، نضغط زر Go أسفل النافذة. بعد ظهور صفحة إدارة الملفات، نختار أيّ ملف ثم نضغط على أيقونة Change Permissions في أعلى الصفحة. ستظهر الآن نافذة منبثقة تحوي على صلاحيات الملف أو المجلّد الذي قمنا باختياره، والتي يمكن من خلالها التعديل عليها: إضافة لما سبق فإنّ بالإمكان التعديل على الصلاحيات عبر برنامج إدارة الملفّات باستخدام FTP، فمثلًا باستخدام FileZilla بعد إتمام الاتصال، يمكن الوصول إلى صلاحيات الملف بالضغط بالزر الأيمن على الملف أو المجلّد المطلوب واختيار File permissions: حيث ستظهر نافذة يمكن خلالها التعديل على الصلاحيات كالمعتاد أيضًا: وأخيرًا يمكن التعديل أيضًا على الصلاحيات عبر سطر الأوامر من خلال SSH بعد تسجيل الدخول، باستخدام الأمر التالي: للمجلّدات find /path/to/your/wordpress/install/ -type d -exec chmod 755 {} \; للملفّات find /path/to/your/wordpress/install/ -type f -exec chmod 644 {} \; سيقوم الأمر السابق بإعادة ضبط صلاحيات جميع المجلّدات في المسار المحدّد لتأخذ الصلاحية 755 وجميع الملفّات لتأخذ الصلاحية 644، وبالطبع لا تنس التأكّد من إدخال مسار تثبيت ووردبريس بشكل صحيح قبل التنفيذ. الخلاصة قمنا بتغطية الأساسيات الخاصّة بصلاحيات الملفات الّلازمة لعمل ووردبريس وكيفية تغييرها من خلال لوحة تحكم cPanel أو من خلال بروتوكوليّ FTP و SSH، لكن يبقى تحديث إصدار ووردبريس أمرًا ضروريًّا من الناحية الأمنيّة، فإنّ هذا يضمن بأنّ صلاحيات الملفات سيتم ضبطها بشكل تلقائيّ إلى الوضع الأمثل. إن كنت تفضّل استخدام الإضافات، فهناك 3 منها يمكنك تجربتها: Triagis® WordPress Security Evaluation SECURE BulletProof Security حيث تقوم هذه الإضافات بالتحقّق من صلاحيات الملفات وتخبرك إن كان هناك إعدادات غير مقبولة. هل احتجت من قبل لإصلاح صلاحيات الملفات لديك؟ شاركنا تجربتك عبر التعليقات في الأسفل. ترجمة -وبتصرّف- للمقال Understanding File Permissions and Using Them to Secure Your Site لصاحبته Jenni McKinnon.
-
- permissions
- ووردبريس
- (و 5 أكثر)
-
رغم قيامك بكل شيء بالطريقة الصحيحة، قد تواجهك أحيانا بعض رسائل الخطأ (errors) على ووردبريس. لا تقلق فإلى جانب أنك قد لا تكون السبب في ذلك بتاتا فقد تجد حلّا سهلًا وبسيطًا له. يتوفر ووردبريس افتراضيا على قيمة قصوى محدودة لرفع الصور، مقاطع الفيديو والملفات الأخرى، نفس الأمر بالنسبة لمحدودية ذاكرة PHP التي تساعدك على تشغيل الملحقات والسكربتات (scripts). قد يصبح هذا الأمر مشكلة حقيقية خصوصا إن كنت تملك موقعا ضخما غنيا بالمحتوى، عند وصولك إلى هذه القيم القصوى فإنك تواجه رسالة خطأ كالتالي: The uploaded file exceeds the upload_max_filesize directive in php.ini عند وصولك إلى القيمة القصوى للذاكرة من المحتمل أن تواجه رسالة مشابهة لما يلي: Fatal error: Allowed memory size of 12345678 bytes exhausted (tried to allocate 2345678 bytes) in /home/your-username/public_html/wp-includes/plugin.php on line 1000 قد يكون إصلاح هذا المشكل أمرا صعبا بعض الشيء بناء على إعدادات الخادوم (server)، لذ سنخصص هذا المقال لتوضيح كيفية زيادة قيمة الرفع القصوى وفي سعة الذاكرة على خادومك حتى تستأنف عملك كالمعتاد. تحديث ملف php.ini إن كنت تستخدم cPanel، اذهب إلى قسم الملفات Files واضغط على زر File Manager. تأكد التأشير على خانة Show Hidden Files ثم اضغط على Go. قم بتحديد مجلد wp-admin، ابحث عن أحد الملفين php.ini أو php5.ini، إن لم تجد أيا منهما، أنشئ واحدا جديدًا بالنّقر على زر New File في الزاوية أعلى اليسار، اختر اسم php.ini للملف ثم اضغط على Create File في الشاشة المنبثقة. يمكنك اختيار Document Root من أجل ولوج أسرع، ستذهب مباشرة إلى ملفات موقعك بعد اختيارها من القائمة المنسدلة. إذا اتبعت هذه الخطوات ولم ينجح الأمر، جرب تغيير اسم الملف إلى php5.ini، بمجرد فتح الملف أضف أو قم بتعديل الأسطر التالية، احفظ التغييرات ثم غلق الملف. upload_max_filesize = 1000M post_max_size = 2000M memory_limit = 3000M file_uploads = On max_execution_time = 180 يدل حرف M على ميغابايت، قم بتغيير القيم القصوى 1000M ،2000M و 3000M إلى قيم أخرى من اختيارك والتي تراها مناسبة لك. يؤدي تغيير قيمة max_execution_time إلى الحد من الوقت المستغرق في تحميل السكربت (مقدّرًا بالثّواني). في العديد من الحالات تتصاعد القيم التي تدخلها أثناء نزولك في القائمة من السطر الأول إلى الثالث، يجب على قيمة upload_max_filesize أن تكون هي الصغرى في حين تكون قيمة memory_limitshould هي الكبرى أما قيمة post_max_size فتمثل الوسط بينهما. قبل التأكد من ذهاب رسالة الخطأ، تأكد من حذف التخزين المؤقت للمتصفح (browser’s cache). تعديل ملف htaccess. إن لم يفِ التعديل السابق بالغرض، جرب التعديل على ملف htaccess.، أضف أو عدّل على الكود التالي في أسفل الصفحة: php_value upload_max_filesize 1000M php_value post_max_size 2000M php_value memory_limit 3000M php_value max_execution_time 180 php_value max_input_time 180 يتم تعديل هذا الكود بنفس طريقة التعديل على ملف php.ini، قم بتغيير القيم إلى ما يناسب احتياجاتك، لا تنس حفظ التعديلات وحذف التخزين المؤقت لمتصفحك. تحسين ملف wp-config.php إن لم تفلح أي الطريقتين السابقتين، جرب التعديل على ملف wp-config.php من خلال إضافة ما يلي إلى أسفل الصفحة مباشرة قبل سطر "happy blogging": define('WP_MEMORY_LIMIT', '3000M'); احفظ التعديلات واحذف التخزين المؤقت للمتصفح (browser’s cache). تغيير القيم القصوى في WHM إن كنت تستضيف موقعك على خادوم مخصص (dedicated server) أو من نوع VPS، يمكنك أن تجرب تغيير القيم القصوى للتحميل والذاكرة في WHM الخاص بك. بعد تسجيل الدخول، اذهب إلى: Server Configuration > Tweak Settings > PHP استخدم نفس القيم التي استخدمتها أعلاه وذلك من أجل نتائج أفضل. أدخل القيم المناسبة لك ثم اضغط على Save أسفل الصفحة. بعد ذلك، اذهب إلى: Service Configuration > PHP Configuration Editor تصفح الصفحة نزولا حتى تجد الأقسام الرئيسية memory_limit و upload_max_filesize. يجب على القيم التي تدخلها هنا أن تكون مطابقة لتلك التي حاولت إدخالها سابقا في ملفي: php.ini و htaccess.. أدخل القيم المناسبة لإعدادك. أخيرًا في قسم Options & Information حدد مكان max_execution_time وقم بتحديثه إلى نفس القيم التي أدخلتها في ملفي: php.ini و htaccess.. اضغط على Save أسفل الصفحة واحذف التخزين المؤقت للمتصفح. خلاصة أنت الآن على أتم استعداد لحل مشكل رسائل الخطأ، استمتع برفع ملفات أكبر حجما واستمر في استخدام الملحقات كما تشاء على موقع ووردبريس الخاص بك. لن تأخذ هذه التغييرات أكثر من بضع دقائق ليظهر تأثيرها لتتمكن من استئناف عملك بسرعة. إذا احتجت إلى رفع ملفات بحجم أكبر مرة واحدة فقط، يمكنك أن تقوم أيضا برفعها من خلال FTP لتجنب هذا العناء. في حين لا يتم عادة عرض الملفات المرفوعة على /wp-content/uploads/ directory باستخدام FTP في مكتبة الميديا، يمكن للملحق Media from FTP أن يسجلها في المكتبة ببضع نقرات. يتم تحديث هذا الملحق بشكل دوري. إن لم تعمل أي من الخيارات المقترحة، لم تتمكن من الولوج إلى الأماكن المذكورة أو واجهت بعض المشاكل أثناء القيام بهذه التغييرات عليك بالاتصال بمزود الاستضافة الخاصة بك الذي يمتلك صلاحية الولوج من أجل القيام بالتغييرات المطلوبة، فمزودك هو الأنسب لهذه المهمة. هل استطعت تغيير القيم القصوى للرفع وذاكرة PHP باستخدام هذه الطرق؟ هل واجهت أي مشاكل في القيام بذلك سابقا؟ تفضل بمشاركتنا تجربتك في التعليقات أسفله. ترجمة بتصرف للمقال: How to Increase the Maximum Upload and PHP Memory Limit in WordPress لصاحبته: JENNI MCKINNON.
-
يعدّ أمر tar من بين الأدوات التي يشيع استخدامها في سطر أوامر لينكس، إلا أن جوانب مفيدة كثيرة في الأمر تبقى مجهولة. نعرض في هذا المقال بعض أشهر استخدامات الأمر tar إضافة إلى استخدامات رائعة أخرى يقل الانتباه إليها. أول ما تجب معرفته هو الغرض الأساسي من tar؛ إذ يعمل الأمر على جمع الكثير من الملفات في واحد. إذا نفذت أمر tar على مجلّد من 37 ملفّا فستحصُل على ملفّ واحد يضمّها جميعا وبالتي يسهُل مشاركتها مع الآخرين. كما أن الأمر يحافظ على بنية المجلّد ويمكن أن يحافظ على الأذونات ومعلومات الوقت والزمن كذلك. الخيارات في ما يلي قائمة بأهم الخيارات التي يمكن استخدامها مع tar. c: إنشاء ملف أرشيف. f: استخدام مُخرج الأمر لإنشاء ملف. تظهر مخرجات الأمر في الطرفية فقط إن لم يٍُستخدَم هذا الخيار. x: استخراج محتويات ملف أرشيف. j: استخدام خوارزمية bzip2 لضغط الملفات. z: استخدام خوارزمية gzip لضغط الملفات. p: الحفاظ على الأذونات عند استخراج الملفات. t: الحصول على قائمة بمحتويات ملف الأرشيف. v: عرض تقدّم عمل الأمر أثناء تنفيذه. d: عرض الفروق بين ملف الأرشيف ونظام الملفات. إنشاء ملف أرشيف إنشاء ملف أرشيف لمجلّد: tar cf directory.tar directory إنشاء ملفّ أرشيف انطلاقا من مجموعة ملفات: tar cf directory.tar file1 file2 file3 إنشاء ملف أرشيف مضغوط بخوارزمية bzip لملفات mp3 الموجودة في المجلّد الحالي: tar -cvf mp3collection.tar ./*.mp3 إنشاء ملف أرشيف من المجلد /home/academy/ مع الحفاظ على الأذونات: tar cvpf academy.tar /home/academy/ إنشاء أرشيف من المجلد etc/ مع استبعاد المجلد الفرعيّ apache2: tar cvf etc_without_apache.tar –exclude='/etc/apache2/' ضغط الملفات إنشاء ملف مضغوط بـbzip2 مع عرض تقدّم عمل الأمر في الطرفية: tar cjvf directory.tar.bz2 directory/ إنشاء ملف مضغوط بـgzip مع عرض تقدّم عمل الأمر في الطرفية: tar czvf directory.tar.gz directory/ عرض محتوى أرشيف عرض محتوى ملف الأرشيف directory: tar tvf directory.tar.bz2 ... bluewaters_1440x900.jpg cloudyday_1440x900.jpg fragile_1600x1200.jpg coolemoticon_1440x900.jpg cloudyday_1440x900.jpg ... الاستخراج من ملفات الأرشيف استخراج محتوى ملف أرشيف: tar xvf directory.tar.bz2 استخراج ملف passwd فقط من أرشيف etc: tar xvf etc.tar.bz2 passwd استخراج مجلد postfix فقط من أرشيف etc: tar xvf etc.tar.bz2 /etc/postfix/ استخراج ملفات php فقط من أرشيف htdocs: tar xvf htdocs.tar.bz2 –wildcards '*.php' الفروق الفرق بين ملف أرشيف ومجلّد (في حال عدم ذكر المجلد فالمقارنة تكون مع مجلد بنفس اسم الأرشيف في المجلد الحالي): tar df directory.tar.bz2 البحث عن ملف في الأرشيف: tar df directory.tar.bz2 directory/file1 ملحوظة: يجب في إصداراتٍ من tar تمرير خيار خوارزمية الضغط أثناء استخراج الملفات أو أثناء النظر في فروق ملفات أرشيف مضغوطة)؛ إلا أن الأمر اختياري في أغلب الإصدارات الأخيرة. مثلا: tar xjvf etc.tar.bz2 /etc/postfix/ بدلا من: tar xvf etc.tar.bz2 /etc/postfix/ ترجمة -وبتصرّف- لمقال A tar Primer لصاحبه Daniel Miessler.
-
يجد كثير من مستخدمي لينكس والأنظمة الشبيهة بيونكس عموما مشاكل في فهم أذونات Permissions الملفات والمجلّدات. يتعلق الأمر أحيانا بترتيب أوضاع بتات القراءة، الكتابة أو التنفيذ؛ بينما تكمن الصعوبة أحيانا أخرى بفهم رموز العدّ الثمانيّ Octal أو ربما كيفية حل لغز بت setuid والبت اللاّصق Sticky bit. يتوجّه هذا المقال إلى من لم يفهم قطّ هذه الأذونات بالدرجة الأولى وإلى من يجد خلطا من حين لآخر في تفاصيلها. راجع أيضا مقال مقدّمة إلى أذونات لينكس Linux Permissions. الأساسيات نبدأ أولا بالنظر إلى مخرجات أمر ls: ls -lah -rwxr-xr-- 1 daniel consultants 5K Mar 10 06:55 scanner.rb -rwxr-xr-x 1 sarah teachers 18M Jul 30 10:07 papers.tar.bz2 ثلاث مجموعات من ثلاثة أحرف: بما أن الأمر يتعلّق هنا بملفات فستظهر عارضة - في أول كل مُخرَج (سطر) . تلي العارضة مجموعة محارف (9 بالضبط، تدخُل العوارض - في الحساب) سنصطلح على تقسيمها إلى ثلاث مجموعات فرعية متساوية (3x3). المستخدِم-المجموعة-الآخرون: نسمي المجموعات الثلاث على الترتيب المستخدِم User, U، مجموعة المستخدم Group, G والآخرين Other, O. يعني هذا أن أول مجموعة محارف (rwx في السطريْن) تتعلق بالمستخدِم مالك الملفّ، الثانية (r-x في السطريْن) تتعلّق بمجموعة المستخدمين مالكة الملفّ والثالثة (--r في السطر الأول وr-x في السطر الثاني) تعني الآخرين أي بقية المستخدمين. صاحب (مالك) الملف: يظهر في نتيجة الأمر المستخدم مالك الملف ومجموعة المستخدمين مالكة الملف كذلك، لكنك لن ترى الآخرين. يعود السبب في ذلك إلى أن أذونات الآخرين (مجموعة المحارف الأخيرة ضمن المجموعات الثلاث أعلاه) تنطبق على كل من ليس مالكَ الملف وليس ضمن مجموعة المستخدمين صاحبة الملف. الأعداد الثلاثة يرتبك بعضهم عندما يرى الأذونات مذكورة بصيغة مجموعة من ثلاثة أعداد، لكنّ الأمر ليس بهذا التعقيد. تذكّر فقط أن هذه الأعداد هي أماكن تحوي الرقم الموافق للإذن حسب الترتيب (من اليسار إلى اليمين): r (القراءة)، w (الكتابة) وx (التنفيذ). لاحظ الصورة. بالنسبة لكلّ رمز، نضربه في 1 إذا كان مذكورا في الأذونات وفي 0 إن لم يكن (تظهر عارضة مكانه)، ثم نجمع نتيجة كل ثلاثي. الأذونات على المجلدات يجب الانتباه إلى أن الأذونات على المجلدات تختلف عنها على الملفات. توحي أسماء الأذونات على الملفات بعملها: قراءة الملف (r)، الكتابة فيه أو حذفه (w) وتنفيذه (x)؛ بينما الدلالة مختلفة قليلا في المجلدات: يعني إذن القراءة على مجلد أن بإمكانك عرض المجلّد. يدلّّ إذن الكتابة أن لديك القدرة على إنشاء محتوى في المجلد أو حذفه منه. يشير إذن التنفيذ إلى أنه بالإمكان الدخول إلى المجلّد، تنفيذ أمر cd عليه مثلا. البت اللاصق، معرف المستخدم ومعرف المجموعة تمثّل هذه الخيارات الثلاثة الجزئية الأكثر تعقيدا لدى الكثيرين في أذونات لينكس. معرف المستخدم صُمِّم خيار معرّف المستخدم setuid (اختصار لـ Set user ID upon execution "اضبط معرّف المستخدم أثناء التنفيذ") لحلّ مشكل أساسي: غياب الإذن الكافي لتنفيذ بعض البرامج. كان حلّ هذا المشكل بإضافة خيار إلى الملف يقول “نفّذ هذا البرنامج وفق أذونات المستخدم الذي يملكه بغضّ النظر عن المستخدم الذي ينفّذ الملف”. ينبغي الحذر من استخدام هذا الخيار - الذي أصبح متجاوزا - إذ قد يؤدي لأخطار أمنية. إن حدث ومررت بإذن على النحو التالي فأنت أمام خيار setuid: -rwsr-xr-- 1 daniel consultants 5K Mar 10 06:55 scanner.rb لاحظ حرف s في أذونات المستخدم مالك الملف مكان إذن التنفيذ x. يشير حرف s إلى أن إذن setuid مضبوط. يظهر حرف s في المثال أعلاه صغيرا Lowercase وهو ما يعني أن خيار التنفيذ متاح أيضا لمالك الملف. إن كان خيار setuid فقط مضبوطا (بمعنى أنه لا يُتاح لمالك الملف إذن تنفيذه) فسيظهر الحرف كبيرا Uppercase هكذا S. ملحوظة: ينطبق التنبيه أعلاه بخصوص هيئة الحرف (صغير أو كبير) على جميع خيارات الأذونات الخاصة. المبدأ العام هو: إذا كان الحرف الذي يشير للإذن الخاص صغيرا فهذا يعني أن الإذن لدى المالك أيضا، أما إذا كان كبيرا فهذا يعني أنه ليس لدى المالك هذا الإذن. معرف المجموعة setguid يشبه الخيّار السابق في عمله مع فرق أنه يُطبَّق على مجموعة المستخدمين المالكة للملف بدلا من المستخدم المالك: -rwxr-Sr-x 1 bjones principals 101K Aug 16 04:01 grades.xml الفرق هنا بالمقارنة مع المثال في الفقرة السابقة هو أن حرف S يوجد ضمن أذونات المجموعة بدلا من المستخدِم. لاحِظ أيضا أن الحرف S في هذا المثال كبير وهو ما يعني أنّه ليس لدى المجموعة المالكة (principals في هذه الحالة) إذن التنفيذ ولكن عند تنفيذ المستخدِم bjones (المالك) أو مستخدم آخر ليس ضمن مجموعة principals للملف فإنّ التنفيذ سيكون بصلاحيات المجموعة المالكة. البت اللاصق يُستخدم هذا البت من أجل منع مستخدمين من التعديل على أو حذف ملفات مستخدِم أو مجموعة مستخدمين. يمكن تطبيق البت اللّاصق على ملفات عادية ولكنّه يُطبَّق أكثر على المجلّدات. نفرض مثلا أنك وضعت مجلدا تحت تصرّف مجموعة من التلاميذ ثم منحت لكل طالب مجلدا خاصا به. يمكن باستخدام البتّ اللاصق التأكد من أنه لن يكون بإمكان طالب حذفُ محتوى مجلد خاصّ بطالب آخر. يبدو البت اللاّصق كما يلي (لاحظ حرف t): drwxr-xr-t 1 alice alice 4.4K 2007-01-01 09:21 Alice التعديل على الأذونات استخدم أمر chmod لتعديل أذونات ملفّ بذكر الأذونات الجديدة التي تريد تطبيقها. يغيّر الأمر التالي أذونات مجلد الويب لتصبح 755: chmod 755 web_directory يغيّر الأمر أدناه أذونات ملف لتصبح 644: chmod 644 grocery_list.txt تعيين معرف المستخدم، معرف المجموعة والبت اللاصق يمكن استخدام أمر chmod أيضا لتعيين الأذونات الخاصّة. لتعيين معرّف المستخدم (نضيف 4 أمام الأذونات الاعتيادية): chmod 4644 script.rb يمكن أيضا استخدام طريقة إضافة الأذونات الأخرى: chmod u+s script.rb لتعيين معرّف المجموعة (نضيف 2 أمام الأذونات الاعتيادية): chmod 2644 script.rb أو: chmod g+s script.rb لتعريف البت اللّاصق (نضيف 1 أمام الأذونات الاعتيادية): chmod 1644 myfiles أو: chmod o+t myfiles ترجمة -وبتصرّف- للمقال A Unix and Linux Permissions Primer لصاحبه Daniel Miessler.
- 1 تعليق
-
- البت اللاصق
- linux
-
(و 7 أكثر)
موسوم في:
-
لينكس هو نظام تشغيلٍ متعدد المستخدمين مبني على مفاهيم يونكس (Unix) لملكيّة الملفّّات والأذونات (permissions) بهدفِ توفير حمايةٍ أفضل. إذا كنتَ تخطط لتحسين مهاراتك بلينكس فيجب عليك أن تمتلك فهمًا جيدًا لكيفية عمل ملكية الملفّّات والأذونات في لينكس. هناك العديد من التعقيدات عند التعامل مع ملكية الملفّّات والأذونات، لكننا سنحاول جهدنا لاستخلاص المفاهيم الأساسية المهمّة لفهم كيفية عملها سنتطرّق إلى كيفية عرض وفهم ملكية الملفّّات والأذونات في لينكس. إذا كنتَ تبحث عن دليلٍ حول كيفية تعديل الأذونات، فاطّلع على هذا الدّرس: مبادئ أذونات الملفات (File permissions) على لينكس. المتطلبات تأكّد من أنّك تفهم المفاهيم التي تم تغطيتها بالدروس السابقة في هذه السلسلة: مقدّمة إلى طرفية لينكس. أساسيات التصفّح في لينكس وإدارة الملفّّات. حول المستخدمين كما ذكرنا في المقدّمة، لينكس هو نظام متعدد المستخدمين. يجب علينا أن نفهم أساسيات مستخدمي ومجموعات نظام لينكس قبل الحديث عن ملكية الملفّّات والأذونات، لأنهما الكيانان اللذان ينطبق عليهما ملكية الملفّّات والأذونات. فلنبدأ بالحديث عن أساسيات ماهيّة المستخدمين أولًا. في لينكس، هناك نوعان من المستخدمين: مستخدمو النظام (system users) والمستخدمون العاديون (regular users)، بشكلٍ عام، مستخدمو النظام يتم استخدامهم لتشغيل العمليات غير التفاعلية (non-interactive processes) والعمليات التي تعمل بالخلفية (background processes) على النظام، بينما يتم استخدام المستخدمين العاديين لتسجيل الدخول إلى النظام وتشغيل العمليات التفاعلية. عندما تقوم بالولوج لأول مرّة إلى أيّ نظام لينكس، قد تلاحظ أن النظام يبدأ مع عدّة مستخدمين للنظام حيث يقوم هؤلاء المستخدمون بتشغيل الخدمات التي يعتمد عليها نظام التشغيل، وهذا الأمر طبيعي تمامًا. من الطرق السهلة لعرض جميع المستخدمين المتوفّرين على النظام هي عرض محتويات ملفّّ etc/passwd/. كلّ سطر في هذا الملفّّ يحتوي معلوماتٍ حول مستخدمٍ واحد، بدءً باسم المستخدم الخاص به (الاسم قبل إشارة ":” الأولى). يمكنك طباعة محتويات ملفّّ passwd عن طريق الأمر التالي: cat /etc/passwd المستخدم الجذر بالإضافة إلى النوعين السابقين للمستخدمين، هناك "المستخدم الجذر" أو ما يعرف بـSuperuser أو root user، وهو يمتلك القدرة على الكتابة فوق أي تقييدات لأذونات ملكية الملفّّات أو تعديلها. بشكلٍ آخر، هذا يعني أن المستخدم الجذر يمتلك القدرة على الوصول إلى أيّ شيءٍ على خادومه الخاص. حيث يتم استخدام هذا المستخدم لتطبيق التغييرات المتعلقة بالنظام بأكمله، ويجب إبقاء هذا المستخدم آمنًا. من الممكن أيضًا أن يتم إعداد حسابات مستخدمين آخرين تمتلك صلاحيات "المستخدم الجذر". في الواقع، من أفضل التدربيات الممكن القيام بها هو إنشاء مستخدمٍ عادي يمتلك صلاحيات sudo لإدارة مهام النظام. حول المجموعات المجموعات هي تجميعات لـ0 مستخدمين أو أكثر. ينتمي المستخدم عادةً إلى المجموعة الافتراضية ويمكن أيضًا أن يكون عضوًا في أيٍّ من المجموعات الأخرى على الخادوم. من الطرق السهلة لعرض جميع المجموعات المتوفّرة على الخادوم والأعضاء بداخلها هي الاطّلاع على ملفّّ etc/group/. لن نغطّي أساسيات إدارة المجموعات في هذا المقال، ولكن يمكنك تطبيق هذا الأمر في حال كنتَ فضوليًا عن مجموعاتك: cat /etc/group الآن صرتَ تعرف ماهيةَ المستخدمين والمجموعات، فلنتحدّث عن ملكية الملفّّات والأذونات. عرض ملكية الملفات والأذونات في لينكس، كلّ الملفّّات تعتبر مملوكة من طرف مستخدمٍ واحد ومجموعةٍ واحدة، وكلّ ملفٍّّ يمتلك أذونات الوصول الخاصة به. فلنأخذ لمحة على كيفية عرض أذونات الملفّّات وملكيّتها. الطريقة الأكثر شيوعًا لعرض أذونات ملفٍّّ ما هي باستخدام الأمر ls مع خيار السرد الطويل (long listing option)، كمثال: ls -l myfile . إذا كنتَ تريد عرض أذونات جميع الملفّّات الموجودة في مسارك الحالي، فقم باستخدام الأمر بدون أيّ معامِلات مثل: ls -l تلميح: إذا كنتَ في مسار المنزل الخاص بك وكان فارغًا، ولم تقم بإنشاء أي ملفّّات لعرضها بعد، فيمكنك متابعة العملية عن طريق سرد محتويات المسار etc/ باستخدام هذا الأمر: ls -l /etc بالأسفل تجدُ مثالًا على لقطة شاشة لِمَا يُمكن للخرج أن يكون، مع تسميات كلِّ عمودٍ من الخرج: لاحظ أنّه يتم سرد وضع كلّ ملفّّ، المالك، المجموعة والاسم الخاصّين به. باستثناء عمود وضع الملفّّ (file's mode) فإنّه من السهل فهم جميع أجزاء الخرج. للمساعدة في شرح جميع هذه الحروف والرموز، فلنقم بتقسيم عمود الوضع (Mode column) إلى مكوناته الأساسية. فهم وضع الملفات للمساعدة في فهم ما تعنيه تلك الحروف والرموز، ألقِ نظرة على هذه الصورة التوضيحية التي تشرح ماهية "الوضع" أو الـ"mode” الخاص بأول ملفٍّّ من المثال أعلاه: نوع الملفات في لينكس، هناك نوعان أساسيان من الملفّّات: عادي وخاص. يتم تحديد نوع الملفّّ عن طريق أول حرفٍ من الوضع الخاص به. في هذا الدليل سنشير إلى هذا عن طريق استخدام مصطلح "حقل نوع الملفّّ". يُمكن أن يتم التعرف على الملفّّات العادية عن طريق شَرْطَة hyphen ( - ) في حقل نوع الملفّّ الخاص بها. الملفَّّات العادية هي مجرد ملفَّّات صرّفَة تحتوي على بيانات. يتم تسميتها بالملفّّات "العادية" لتمييزها عن الملفّّات الخاصة. الملفّاّت الخاصّة هي الملفّات التي تمتلك محرف غير شَرْطَي (non-hyphen character) مثل الحروف العادية في حقل نوع الملفّ الخاصة بها، ويتم معاملتها من جانب نظام التشغيل بطريقةٍ مختلفة عن الملفّاّت المحلّية. المحرف الذي يظهر في حقل نوع الملفّ يحدّد نوع الملفّ الخاص. مثل المجلّدات (folders)، وهي الملفّاّت الخاصة الأكثر شيوعًا من بين الملفّاّت الخاصّة. يتم التعرّف على المجلّدات عن طريق محرف d الذي يظهر في حقل نوع الملفّ الخاصّ بالمجلّد (مثل لقطة الشاشة السابقة). هناك أنواعٌ أخرى من الملفّاّت الخاصّة ولكنّها ليست أساسية لِمَا سنتعلّمه هنا. أصناف الأذونات نعلمُ من الرسم البياني السابق أنّ عمود الوضع يحدد نوع الملفّّ، متبوعًا بثلاثة أصناف (classes) من الأذونات: المستخدم (المالك)، المجموعة والآخرون. ترتيب هذه الأصناف ثابت على جميع توزيعات لينكس. فلنلقِ نظرة على الأصناف التي ينتمي إليها كلّ نوعٍ من المستخدمين: المستخدم (User): مالك الملفّ (owner) ينتمي إلى هذا الصنف. المجموعة (Group): أعضاء مجموعة الملفّ ينتمون إلى هذا الصنف. الآخرون (Other): أيُّ مستخدمين آخرين ليسوا جزءًا من صنفيّ المستخدم أو المجموعة فهم ينتمون إلى هذا الصنف. قراءة الأذونات الرمزية الشيء التالي الذي من الواجب الاهتمام به هو تشكيلة المحارف الثلاثة الخاصّة بوضع الملفّ، لأنها هي التي تقوم بتحديد الأذونات الخاصّة بالملفّ، بشكلٍ رمزي (symbolic) يمتلكها كل ملفّ. يتم تمثيل أذونات الكتابة، القراءة والتنفيذ في كلِّ تشكيلةٍ ثلاثية (triad) على النحو التالي: القراءة: يتم تمثيلها بحرف r بالموقع الأول. الكتابة: يتم تمثيلها بحرف w بالموقع الثاني. التنفيذ: يتم تمثيله بحرف x بالموقع الثالث. في بعض الحالات الخاصّة، يمكن أن يكون هناك حرفٌ آخر هنا. عندما يتم وضع شَرْطَة ( - ) في أي موقعٍ من هذه المواقع، فهذا يعني الإذن المعين ذاك ليس متوفرًا لهذا الصنف. كمثال: إذا كانت التشكيلة الثلاثية للمجموعة المالكة لملفٍّ معين هي: --r ، فهذا يعني أن الملفّ هو قابل للقراءة فقط لتلك المجموعة المتصلة بالملفّ. فهم قراءة، كتابة وتنفيذ الملفات الآن صرتَ قادرًا على قراءة الأذونات الخاصّة بكلّ ملفّّ، وعلى الأرجح فإنّك الآن تريد معرفة مالذي يسمح كلّ نوعٍ من أنواع الأذونات للمستخدمين أن يفعلوا. سوف سنشرح كلّ إذنٍ بشكلٍ منفصل، ولكن عليك أن تتذكر أنّه غالبًا ما يتمُ استخدام خليط من هذه الأذونات مع بعضها البعض للسماح بوصولٍ معين إلى هذه الملفّات والمسارات من قبل المستخدمين. إليك شرحًا بسيطًا إلى نوع الوصول الذي يمنحه كلٌّ نوعٍ من الأذونات للمستخدمين. 1- القراءة يسمحُ إذن القراءة لملفٍّ عادي أن يتم عرضه من قبل المستخدم لمشاهدة محتويات الملفّ. لمجلد أو مسار، يسمح إذن القراءة لمستخدمٍ أن يقوم بعرض أسماء الملفّات الموجودة بتلك المجلدات أو المسارات. 2- الكتابة يسمحُ إذن الكتابة لملفٍّ عادي أن يتم تعديله أو حذفه من قبل المستخدم. لمجلدٍ أو مسار، يسمح إذن الكتابة بأن يتم حذف المجلد أو المسار وتعديل محتوياته (إنشاء، حذف وإعادة تسمية الملفّات الموجودة بداخله) وتعديل محتويات الملفّات التي يمكن قراءتها من قبل المستخدم. 3- التنفيذ يسمح إذن الكتابة بأن يتم تنفيذ ملفٍّ من قبل المستخدم (يجب على المستخدم أن يمتلك إذن القراءة أيضًا). أذونات التنفيذ يجب أن يتم إعطاؤها للبرامج التنفيذية وسكربتات الشلّ (shell scripts) قبل أن يتمكّن المستخدم من تشغيلها. لمجلدٍ أو لمسار، يسمح إذن التنفيذ بالوصول إلى البيانات الوصفية (metadata) الخاصة بالملفّات الموجودة بداخله (مثل الأمر cd أو ls -l). أمثلة على أوضاع الملفّات والأذونات الآن وبعدما صرتَ قادرًا على قراءة وضع الملفّات وفهم معنى إذنِ كلِ واحدٍ منها، فسوف نتطرّق إلى بضعة أمثلة لأوضاعٍ شائعة للملفّات مع شرحٍ بسيط حولها: -rw-------: تمثّل ملفًّا قابلًا للوصول فقط من قبل مالكه. -rwxr-xr-x: تمثّل ملفًّا قابلًا للتنفيذ من قبل جميع المستخدمين على النظام. -rw-rw-rw-: تمثّل ملفًّا قابلًا للتعديل من قبل جميع المستخدمين على النظام. drwxr-xr-x: تمثّل مسارًا يمكن لجميع المستخدمين على النظام الوصول إليه وقراءته. drwxrwx---: تمثّل مسارًا قابلًا للتعديل (بالإضافة إلى محتوياته) من قبل مالكه والمجموعة التي ينتمي إليها. drwxr-x---: تمثّل مسارًا يمكن الوصول إليه من قبل مجموعته. كما تلاحظ، عادةً، مالك الملفّ يتمتّع بغالب الأذونات الخاصة بالملفّ مقارنةً مع الصنفين الآخرين. عادةً، سترى أنّ صنفيّ "المجموعة" و "الآخرون" يمتلكان أذونات فرعية فقط من أذونات مالك الملفّ (مساوية لها أو أقل). هذا أمرٌ منطقي لأن الملفّات يجب أن تكون قابلة للوصول فقط من طرف المستخدمين الذين يحتاجون الوصول إليه لسببٍ معيّن. شيءٌ آخر لملاحظته هو أنّه وعلى الرغم من أنّه هناك العديد من تشكيلات الأذونات الممكنة، فإنّ عددًا محدودًا منها فقط قد يكون استخدامها منطقيًا في حالاتٍ معيّنة. كمثال فإنّ أُذنيّ الكتابة والتنفيذ غالبًا ما يتم إلحاقهما بإذن القراءة، لأنّه سيكون من الصعب تعديل، ومن المستحيل تنفيذ ملفٍّ لا تستطيع قراءته. تعديل ملكية الملفات والأذونات للإبقاء على هذا الدليل بأبسط ما يمكن، لن نتطرف إلى كيفية تعديل ملكيّة الملفّات والأذونات هنا. الخاتمة يجب أن تكون الآن قد امتلكت معرفة جيّدة حول كيفية عمل ملكيّة الملفّات والأذونات في نظام لينكس. إذا كنتَ تحبّ تعلم المزيد عن أساسيات لينكس، فمن المستحسن بشدّة أن تقوم بقراءة الدّرس القادم من هذه السّلسلة والذي سيكون حول إعادة توجيه الإدخال/الإخراج في لينكس. ترجمة -وبتصرّف- للمقال: An Introduction to Linux Permissions.
-
مجموعات التحكم هي آلية في النواة لتجميع وتتبع ووضع حد لاستهلاك الموارد للمهام؛ الواجهة الإدارية التي توفرها النواة تكون عبر نظام ملفات وهمي؛ لكن طوِّرت أدوات إدارية لمجموعات التحكم ذات مستوى أعلى، بما فيها libcgroup و lmctfy. بالإضافة لذلك، هنالك دليل في freedesktop.org حول كيف يمكن أن تتعاون التطبيقات بأفضل طريقة باستخدام واجهة نظام الملفات لمجموعات التحكم (cgroup filesystem interface). في أوبنتو 14.04؛ أصبح مدير مجموعات التحكم (cgmanager) متوفرًا كأداة أخرى لإدارة واجهة cgroup؛ حيث هدفه هو الاستجابة لطلبات dbus من أي مستخدم، مما يمكِّنه من إدارة مجموعات التحكم التي أُسنِدَت إليه فقط. لمحة إن مجموعات التحكم (cgroups) هي الميزة التي تستعمل لتجميع المهام؛ حيث يكون تتبع الموارد ووضع حدود لها مُدارًا من أنظمة فرعية؛ إذ أنَّ الهيكلية (hierarchy) هي مجموعة من الأنظمة الفرعية الموصولة مع بعضها بعضًا؛ على سبيل المثال، إذا كانت الأنظمة الفرعية للذاكرة والأجهزة (devices) موصولة مع بعضها في /sys/fs/cgroups/set1، فيمكن لأي مهمة في /child1 أن تكون عرضةً للحدود الموافقة للنظامين الفرعيين السابقين. حيث تُشكِّل كل مجموعة من الأنظمة الفرعية الموصولة «هيكليةً» (مع استثناءات)؛ مجموعات التحكم التي تكون أولاد /child1 تكون عرضةً للحدود المفروضة على /child1، ويكون استهلاك الموارد محسوبًا على /child1. الأنظمة الفرعية الموجودة تتضمن: cpusets: تبسيط إسناد مجموعة من المعالجات وعُقَد الذاكرة إلى مجموعات التحكم؛ فالمهام في مجموعة تحكّم فيها النظام الفرعي cpusets يمكن أن تستخدم المعالجات المُسنَدة إلى تلك المجموعة فقط. blkio: تحديد كتل الدخل/الخرج لكل مجموعة تحكم. cpuacct: توفير حساب الاستهلاك للمعالج لكل مجموعة تحكم. devices: التحكم في قدرة المهام على إنشاء أو استخدام عقد الأجهزة إما باستعمال قائمة بيضاء (whitelist) أو سوداء (blacklist). freezer: توفير طريقة «لتجميد» (freeze) و «تذويب» (thaw) مجموعات التحكم؛ لا يمكن جدولة (scheduled) مجموعات التحكم وهي مجمدة. hugetlb: تبسيط وضع حد لاستهلاك hugetlb لكل مجموعة تحكم. memory: السماح للذاكرة، وذاكرة النواة، وذاكرة التبديل (swap) بأن تُتَبَّع وتقيّد. net_cls: توفير واجهة لوضع علامات على الرزم الشبكية بناءً على مجموعة التحكم المُرسِلة؛ يمكن استعمال هذه العلامات لاحقًا باستخدام tc (traffic controller) لإسناد أولويات للرزم الشبكية. net_prio: السماح بضبط أولوية بيانات التراسل الشبكي بناءً على مجموعة التحكم. cup: تمكين ضبط جدولة الخصائص على أساس مجموعة التحكم. pref_event: تفعيل نمط لكل معالج لمراقبة الخيوط (threads) لمجموعات تحكم معينة. يمكن إنشاء مجموعات تحكم مُسماة دون استخدام أنظمة فرعية معها، ويكون الغرض من ذلك هو تتبع العمليات؛ على سبيل المثال، يقوم systemd بذلك لتتبع خدماته وجلسات المستخدم. نظام الملفات تُنشَأ هيكلية بوصل نسخة من نظام ملفات مجموعة التحكم لكل نظام فرعي مُراد استخدامه كخيار للوصل؛ على سبيل المثال: mount -t cgroup -o devices,memory,freezer cgroup /cgroup1 وهذا ما سيُنشِئ هيكلية فوريًا مع الأجهزة ومجموعات التحكم للذاكرة موصولةً مع بعضها؛ ويمكن إنشاء مجموعة تحكم فرعية (child cgroup) باستخدام mkdir: mkdir /cgroup1/child1 يمكن نقل المهام إلى مجموعة التحكم الفرعية الجديدة بكتابة أرقام معرفات عملياتهم في ملف tasks أو cgroup.procs: sleep 100 echo $! > /cgroup1/child1/cgroup.procs يمكن الإدارة أيضًا عبر ملفات في مجلدات cgroup؛ على سبيل المثال، لتجميد جميع المهام في child1: echo FROZEN > /cgroup1/child1/freezer.state يمكن العثور على كمية كبيرة من المعلومات عن مجموعات التحكم وأنظمتها الفرعية في مجلد التوثيق cgroups في شجرة مصدر النواة. التفويض يمكن لملفات ومجلدات مجموعات التحكم أن تُملَك من مستخدمين غير المستخدم الجذر، مما يمكِّن تفويض (delegation) إدارة مجموعات التحكم؛ عمومًا، تُجبِر النواة القيود المفروضة على الهيكلية على الأولاد؛ على سبيل المثال، إن كانت مجموعة الأجهزة /child1 لا تملك وصولًا للقرص الصلب، فلا تستطيع مجموعة التحكم /child1/child2 إعطاء نفسها هذه الامتيازات. في أوبنتو 14.04، يوضع المستخدمون افتراضيًا في مجموعة من مجموعات التحكم التي يملكونها، مما يسمح لهم باحتواء المهام التي يشغلونها باستخدام مجموعات تحكم فرعية بأمان؛ تُستخدَم هذه الميزة عمليًا ويمكن الاعتماد عليها فمثلًا يمكن استخدامها لإنشاء حاوية LXC دون امتيازات. المدير مدير مجموعات التحكم (cgmanager) يوفر خدمة D-Bus للسماح للبرامج والمستخدمين بإدارة مجموعات التحكم دون الحاجة إلى معرفة أو وصول مباشر إلى نظام ملفات مجموعات التحكم. وللطلبات من المهام في نفس مجال الأسماء (namespace) للمدير، فيمكن للمدير إجراء التحققات الأمنية اللازمة للتأكد من شرعية تلك الطلبات؛ وللطلبات الأخرى، كتلك القادمة من مهمة في حاوية، فيجب القيام بطلبات D-Bus مُحَسَّنة؛ حيث يجب أن تُمرَّر معرفات process، و user، و group على شكل SCM_CREDENTIALS، لذلك يمكن للنواة ربط المعرفات إلى قيم المضيف العامة. ولتبسيط استخدام استدعاءات D-Bus من جميع المستخدمين، فيبدأ «وسيط مدير مجموعات التحكم» (cgproxy) تلقائيًا في الحاويات؛ حيث يقبل طلبات D-Bus قياسية من المهام في نفس مجال أسمائه، ثم يحوله إلى طلبات SCM D-Bus محسنة التي تُمرَّر بعد ذلك إلى cgmanager. مثال بسيط عن إنشاء مجموعة تحكم -التي ستُشغِّل تصريفًا (compile) يستهلك كثيرًا من طاقة المعالجة- سيكون كالآتي: cgm create cpuset build1 cgm movepid cpuset build1 $$ cgm setvalue cpuset build1 cpuset.cpus 1 make مصادر مشروع cgmanager مُستضاف في linuxcontainers.org. يمكن العثور على صفحة توثيق النواة هنا. ويمكن العثور على دليل freedesktop.org لاستخدام مجموعات التحكم هنا. ترجمة -وبتصرف- للمقال Ubuntu Server Guide: Control Groups.
-
تتميز خدمة Google Analytics بروعة أدائها في تتبع حركة مرور زوار موقع ما، دون الحاجة إلى أي إعدادات أو إضافات، إلا أنها لا تتتبع تحميل الملفات مثل: ملفات PDF ،MP3، مستندات Word أو مقاطع الفيديو نظرا لاعتمدها على JavaScript. آخِذِينَ ما سبق بعين الاعتبار، سنتطرق وإياكم في هذا الموضوع إلى كيفية استخدام الأحداث (events) في Google Analytics بغرض تتبع تحميل الملفات. سنتطرّق بشكل سريع إلى بعض الطّرق التي تصلح على جميع المواقع ثم سنختم بمجموعة مُلحقات خاصة بووردبريس. ما يجب أن تعرفه قبل الشروع في العمل بحكم أنّك تقرأ هذا الموضوع، سنفترض أنك تملك مسبقا حساب Google Analytics جاهزا للعمل، إن كنت حديث العهد بهذه الخدمة فمن الأفضل أن تلقي أوّلًا نظرة على سلسلة مدخل إلى Google Analytics هنا على أكاديمية حسوب. يجب عليك أيضا أن تتأكد من استخدامك لأحدث نسخة Universal Analytics من شفرة التتبع (tracking code)، سنفترض أنك فعلا تستخدمها، أما إن كنت بحاجة إلى ترقية نسخة السكربت، يوفر لك جوجل كما هائلا من الموارد لمرافقتك في تطبيق مختلف الخيارات خلال كل مراحل عملية الترقية. استعمال الأحداث (Events) في Google Analytics يعمل جوجل على توفير طريقة أكثر مرونة لقياس تفاعل المستخدمين مع موقعك وذلك من خلال الأحداث (Events) في خدمة Analytics دون الحاجة إلى التقيد بشكل كامل بعدد الزيارات (page loads). يمكنك الولوج إلى الأحداث (Events) على حسابك من خلال الذهاب إلى تبويب Reporting ثم اختيار Behavior < Events. قسم Events في Google Analytics قبل تفعيله يتميز تصميم الأحداث (Events) في Google Analytics بقابلية الإعداد والتهيئة حسب ما ترغب فيه، يتوفر كل حدث على أربع مكونات أساسية يمكنك التعديل عليها بكل حرية لتناسب احتياجاتك ومتطلباتك: Category (التصنيف): الوصف أو المصطلح الذي يعود على نوع محدد من الأحداث، يعطيك هذا الخيار إمكانية تجميع الأحداث المتشابهة مثلا الكتب الإلكترونية (e-book) أو ما كل ما يتعلق بمقاطع الفيديو. Action (الإجراء): النتيجة أو الهدف الذي ترغب في تَتَبّعَهُ، يمكن أن يكون تحميلا، ضغطة على زر مُعيّن أو أي نوع آخر من الإجراءات أو العمليات التي تود أن تستهدفها. Label (الوصف): يوفر لك خيار الوسوم هذا بعض المساحة الإضافية لإضافة أي معلومات أخرى قد تبدو لك ذات أهمية. هذا الحقل اختياري Value (القيمة): لنفترض على سبيل المثال أن العرض المجاني الذي تقدمه لزوارك مقابل التسجيل في موقعك هو تحميل كتاب إلكتروني ما ولنفترض أيضا أن معدل التحويل على هذا التحميل هو %10 من قيمة المنتوج التابع لهذا الكتاب والتي تبلغ 150 دولارا، يمكن إذا في هذه الحالة ربط كل تحميل بقيمة 15 دولارا. هذا الحقل اختياري أيضًا يمكنك الاطلاع على المزيد من التفاصيل فيما يخص الخيارات (options) المتوافرة لكل واحدة من المكونات السابقة على توثيق جوجل لأحداث خدمة Analytics. لننتقل الآن إلى الاستخدام الفعلي لخاصية الأحداث هذه بغرض تجميع البيانات. كيفية إنشاء حدث جديد قم أولا بتسجيل الدخول إلى حسابك، تحديد الموقع (من قسم property) ثم الضغط على رابط Admin أعلى الشاشة: اختر Goals من الخانات الثلاث الظاهرة. يمكنك الآن أن ترى ثلاث خانات كما في الصورة أعلاه، اضغط على رابط Goals في خانة View ثم New Goal لتبدأ بعملية الإعداد: إنشاء هدف الحدث (Event Goal) ما يأخذنا إلى الشاشة أعلاه حيث يمكن إدخال المعلومات التالية: name (الاسم) وgoal ID (المُعرف الخاص بالإجراء المستهدف) ثم اختر Event لتحديد نوع الإجراء المستهدف. إنشاء تفاصيل الإجراء المستهدف (goal) نصل أخيرا إلى مرحلة إدخال المكونات المشار إليها مسبقا، عند انتهائك من ذلك ومُراجعتك للإعدادات التي اخترتها ما عليك إلا أن تضغط Save لحفظ التغييرات ما ينهي هذه المرحلة من الإعداد. إضافة تتبع حدث (Event Tracking) أولي إلى الصفحة بعد الانتهاء من إعداد الحدث في خدمة Analytics، علينا الآن أن نصبح قادرين على تفعيله على الموقع، يعتبر استخدام حدث من نوع onclick أسهل طريقة لإضافة التتبع إلى صفحة معينة، حيث يتم إرسال المعلومات إلى Analytics بمجرد تفاعل المستخدم مع الإجراء المستهدف. على سبيل المثال، إذا أردنا تتبع أداء كتاب إلكتروني مجاني، يجب فقط إضافة الشيفرة التالية إلى الرابط المعني كما هو مبين أسفله: <a onclick="ga('send', 'event', 'Downloads', 'Click', 'E-book downloaded', '0');" href="http://mysamplesite.com/wp-content/uploads/2015/12/my-free-lead-magnet.pdf">Download Our Guide to Speeding up Your Site</a> يمكنك الاطلاع على التفصيل الكامل للمزيد من الخيارات على صفحة تتبع الأحداث (Event Tracking) في Google Developers. قد تكون إضافة هذا الكود يدويًا حلًا عمليًا لما يكون لديك حدث واحد لتتبّعه، أما إذا كنت ترغب في تتبّع العديد من الأحداث، فهنالك بعض الطرق البديلة التي يمكنك استخدامها. يُمكن مثلا الاستعانة بـ jQuery لإضافة آلية تتبّع الأحداث بشكل آلي، ويُمكن مثلًا أن نُحدّد الرّوابط التي نرغب في استهدافها عبر إضافة id خاص إليها. كما يُمكننا الاستعانة بـ Google Tag Manager لإدارة هذه الأحداث دون الحاجة إلى التّعديل على شيفرة الموقع. أما إذا كنت تستخدم ووردبريس كنظام إدارة مُحتوى على موقعك فهناك عدّة مُلحقات تسمح لك بالقيام بالأمر دون أيّ عناء. تتبع تحميل الملفات باستعمال ملحق ووردبريس إذا بدا لك أن ما أسلفنا الذكر من الطرق والتقنيات كثير التعقيد، فإليك مجموعة من الملحقات التي يمكنها أن تتكفل بتتبع وإدارة تحميل الملفات على ووردبريس، إليك فيما يلي ثلاثا من أكثرها شعبية وانتشارا: Google Analytics Dashboard for WP يعمل ملحق Google Analytics Dashboard for WP على إحضار بيانات موقعك مباشرة إلى ووردبريس كما يسمح لك بالاطلاع على المعلومات بخصوص التحميلات المسجلة كأحداث (events). تم تنزيل هذا المُلحق حوالي 600 000 مرة ويُقارب تقييمه الخمس نجمات. يعتبر هذا الملحق طريقة عملية لجلب قوة Analytics مباشرة إلى لوحة التحكم الخاصة بك. Download Monitor يَتَّبِعُ ملحق Download Monitor مقاربة مختلفة قليلا فيما يخص تحميل الملفات عن طريق وضعها على قدم المساواة مع المنشورات والصفحات على موقعك. يسمح لك هذا الملحق بتصنيف ووسم تحميلاتك، إضافة بيانات وصفية مخصصة لها فضلا عن تتبعها، كما يوفر خصائص متقدمة مثل التحميلات الخاصة بالأعضاء. يوفر الملحق أيضا مجموعة من الإضافات الرائعة إن أردت التحكم بشكل أفضل في تحميل الملفات على موقعك. WordPress Download Manager يوفر ملحق WordPress Download Manager خصائص عَدِّ التحميلات وإرسال التقارير إضافة إلى إمكانية الدمج السلس مع Google Drive ،Dropbox و Box.com كما توفر النسخة المدفوعة من الملحق الكثير من خيارات التجارة الإلكترونية. هل تقوم أنت بتتبع تحميل الملفات على موقعك؟ كيف تقوم بذلك؟ شاركنا في التعليقات أسفله نصائحك والحيل التي تتبعها كما يمكنك أن تطرح علينا أي أسئلة تراودك. ترجمة وبتصرف للمقال: Tracking File Downloads With Google Analytics And Wordpress لصاحبه: TOM EWER.
-
أنماط حماية سامبا هنالك مستويان أمنيان متوفران لبروتوكول الشبكة «نظام ملفات الإنترنت الشائع» (Common Internet Filesystem اختصارًا CIFS) هما user-level و share-level؛ نمط الحماية المستخدم في سامبا يسمح بمرونة زائدة، موفرًا أربع طرق لاستخدام الحماية من مستوى user-level وطريقة لاستخدام share-level: النمط security=user: يتطلب من العملاء توفير اسم مستخدم وكلمة مرور للاتصال إلى المشاركات؛ حسابات المستخدمين في سامبا منفصلة عن حسابات مستخدمي النظام، لكن الحزمة libpam-smbpass ستُزامن مستخدمي النظام وكلمات مرورهم مع قاعدة بيانات مستخدمي سامبا. النمط security=domain: هذا النمط يسمح لخادوم سامبا بأن يَظهر لعملاء ويندوز كالمتحكم الرئيسي بالنطاق (Primary Domain Controller اختصارًا PDC)، أو متحكم الاحتياطي بالنطاق (Backup Domain Controller اختصارًا BDC)، أو خادوم عضو في النطاق (Domain Member Server اختصارًا DMS)، وسنشرح ذلك في الدرس القادم. النمط security=ADS: السماح لخادوم سامبا بالانضمام إلى نطاق Active Directory كعضو أصيل (native member). النمط security=server: هذا النمط تُرِك قبل أن يتمكن سامبا من أن يصبح خادومًا عضوًا، وبسبب بعض المشاكل الأمنية، فلا يجب أن يُستخدَم؛ راجع قسم «Server Security» من دليل سامبا لمزيدٍ من التفاصيل. النمط security=share: يسمح لجميع العملاء بالاتصال إلى المشاركات دون توفير اسم مستخدم وكلمة مرور. يعتمد اختيارك لنمط الحماية بالبيئة التي تعمل فيها وما الذي تريد من خادوم سامبا أن يُنجزه. النمط Security = User سيعيد هذا القسم ضبط خادوم سامبا لمشاركة الملفات والطباعة من القسمين السابقين، كي يتطلب الاستيثاق. أولًا، ثبِّت الحزمة libpam-smbpass التي ستزامن مستخدمي النظام إلى قاعدة بيانات مستخدمي سامبا: sudo apt-get install libpam-smbpass ملاحظة: لو اخترت مهمة «Samba Server» أثناء التثبيت، فستكون الحزمة libpam-smbpass مثبَّتةً مسبقًا. عدِّل الملف /etc/samba/smb.conf، وعدِّل ما يلي في قسم [share]: guest ok = no في النهاية، أعد تشغيل سامبا لكي تأخذ الإعدادات الجديدة مفعولها: sudo restart smbd sudo restart nmbd سيُطلَب منك الآن إدخال اسم مستخدم وكلمة مرور عند الاتصال إلى المجلدات المشاركة أو الطابعات. ملاحظة: إذا اخترت ربط قرص شبكي للمشاركة، فعليك تفعيل الحقل «Reconnect at Logon»؛ مما يجعله يطلب اسم المستخدم وكلمة المرور مرةً واحدةً فقط، على الأقل إلى أن تُغيَّر كلمة المرور. تأمين المشاركة هنالك عدِّة خيارات متوفرة لزيادة الحماية لمشاركات المجلدات المنفصلة؛ وباستخدام مثال «[share]»، فسيشرح هذا القسم بعض الخيارات الشائعة. المجموعات تُعرِّف المجموعات تشكيلةً من الحواسيب أو المستخدمين الذي يملكون وصولًا متكررًا إلى مورد شبكي معين؛ على سبيل المثال، إذا عُرِّفت المجموعة qa وكانت تحتوي على المستخدمين freda، و danika، و rob؛ ومجموعة ثانية هي support تحتوي على المستخدمين danika، و jeremy، و vincent؛ وضُبِط مورد شبكي معيّن للسماح بالوصول إلى المجموعة qa، والذي بدوره سيمنح المستخدمين freda، و danika، و rob وصولًا لكن ليس jeremy أو vincent؛ ولما كان المستخدم danika ينتمي إلى كلي المجموعتين qa و support؛ فسيتمكن من الوصول إلى الموارد التي يُسمَح لكلا المجموعتين بالوصول إليها، بينما كل المستخدمين الباقيين سيقيدون بالموارد التي تسمح بوصول مجموعتهم إليها. يبحث سامبا عن المجموعات في النظام المحلي المُعرَّفة في /etc/group ليحدد أي مستخدم ينتمي إلى أي مجموعة؛ للمزيد من المعلومات حول إضافة أو إزالة المستخدمين من المجموعات، راجع القسم «إضافة وحذف المستخدمين» من درس إدارة المستخدمين. عند تعريف المجموعات في ملف ضبط سامبا، /etc/samba/smb.conf؛ فإن الصيغة المتعارف عليها هي بدء اسم المجموعة بالرمز «@»؛ على سبيل المثال، إذا أردت تعريف مجموعة مسماة sysadmin في قسم محدد من ملف /etc/samba/smb.conf، فعليك إدخال اسم المجموعة @sysadmin. أذونات الملف تُعرِّف أذونات الملف الحقوق المحددة التي يملكها حاسوب أو مستخدم على مجلد أو ملف أو مجموعة ملفات؛ يمكن تعريف هذه الأذونات بتعديل الملف /etc/samba/smb.conf وتحديد الأذونات لمشاركة ملف معيّن. على سبيل المثال، لو عَرَّفتَ مشاركة سامبا اسمها share وأردت إعطاء أذونات «للقراءة فقط» لمجموعة المستخدم qa؛ لكنك تريد السماح بالكتابة لمجموعة اسمها sysadmin ومستخدم اسمه vincent، فعليك تعديل الملف /etc/samba/smb.conf وإضافة القيود الآتية تحت قيد [share]: read list = @qa write list = @sysadmin, vincent طريقة أخرى لضبط الأذونات في سامبا هي التصريح عن أذونات «إدارية» لمورد معيّن مُشارَك؛ حيث يمكن للمستخدمين الذي يملكون أذونات إدارية قراءة أو كتابة أو تعديل أيّة معلومات موجودة في المورد الذي أُعطي ذاك المستخدم أذوناتٍ إدارية خاصة عليه. على سبيل المثال، إذا أردت إعطاء المستخدم melissa أذوناتٍ إدارية للمشاركة share، فعليك تعديل الملف /etc/samba/smb.conf وإضافة الأسطر الآتية تحت القيد [share]: admin users = melissa بعد تعديل الملف /etc/samba/smb.conf، أعد تشغيل سامبا كي تأخذ التعديلات مجراها: sudo restart smbd sudo restart nmbd ملاحظة: لكي تعمل «read list» و «write list»، لا يجب أن يكون نمط حماية المستخدم في سامبا مضبوطًا إلى security = share. ضُبِط الآن سامبا ليحدد أيّة مجموعات تملك الوصول إلى مجلد مُشارَك، يجب الآن تحديث أذونات نظام الملفات. نظام أذونات لينُكس التقليدي لا يترابط جيدًا مع قوائم التحكم بالوصول في ويندوز (NT (Windows NT Access Control Lists اختصارًا ACLs؛ لحسن الحظ، توجد POSIX ACLs في خواديم أوبنتو موفرةً تحكمًا أفضل؛ على سبيل المثال، للسماح باستخدام ACLs على /srv بنظام ملفات EXT3، فعدِّل الملف /etc/fstab وأضف الخيار acl كما يلي: UUID=66bcdd2e-8861-4fb0-b7e4-e61c569fe17d /srv ext3 noatime,relatime,acl 0 1 ثم أعد وصل القسم: sudo mount -v -o remount /srv ملاحظة: تفترض الأوامر السابقة أن /srv على قسمٍ مختلف؛ إذا كان /srv، أو أي مسار آخر تختار مشاركته، هو جزء من قسم الجذر /، فربما عليك إعادة إقلاع النظام. لمطابقة ضبط سامبا، فستُعطى المجموعة sysadmin أذونات القراءة والكتابة والتنفيذ إلى /srv/samba /share، وستُعطى المجموعة qa إذنَيّ القراءة والتنفيذ؛ وستُملَك الملفات من المستخدم melissa. أدخِل الأوامر الآتية في الطرفية: sudo chown -R melissa /srv/samba/share/ sudo chgrp -R sysadmin /srv/samba/share/ sudo setfacl -R -m g:qa:rx /srv/samba/share/ ملاحظة: الأمر setfacl السابق يعطي أذونات التنفيذ إلى جميع الملفات في المجلد /srv/samba/share، ربما يكون أو لا يكون هذا ما تريده. الآن من عميل ويندوز، يجب أن تلاحظ تطبيق الأذونات الجديدة للملف؛ راجع صفحات دليل acl و setfacl لمزيد من المعلومات حول POSIX ACLs. ملف ضبط سامبا لبرمجية AppArmor يأتي أوبنتو مع وحدة الحماية AppArmor، الذي يوفر تحكمًا مقيّدًا للوصول؛ ملف الضبط الافتراضي الخاص ببرمجية AppArmor لخدمة سامبا يجب أن يلائم ضبطك، للمزيد من التفاصيل حول استخدام AppArmor راجع درس AppArmor. هنالك ملفات ضبط افتراضية لكلي /usr/sbin/smbd و /usr/sbin/nmbd (الملفات الثنائية لعفريت سامبا) كجزءٍ من حزمة apparmor-profiles؛ أدخِل الأمر الآتي من الطرفية لتثبيت الحزمة: sudo apt-get install apparmor-profiles apparmor-utils افتراضيًا، تكون ملفات الضبط لعفريتي smbd و nmbd في وضع «البناء» مما يسمح لخدمة سامبا بالعمل دون تعديل ملف الضبط، وستُسجَّل الأخطاء فقط؛ لجعل ملف ضبط smbd في وضع «الإجبار»، ولكي يعمل سامبا كما يجب، فيجب أن يُعدَّل ملف الضبط لتضمين المجلدات التي تمت مشاركتها. عدِّل ملف /etc/apparmor.d/usr.sbin.smbd مضيفًا معلومات [share]: /srv/samba/share/ r, /srv/samba/share/** rwkix, ضع الملف في وضع «الإجبار» وأعد تحميله: sudo aa-enforce /usr/sbin/smbd cat /etc/apparmor.d/usr.sbin.smbd | sudo apparmor_parser -r يجب أن تكون قادرًا على قراءة وكتابة وتنفيذ الملفات في المجلد المُشارَك كالمعتاد، لكن smbd يملك الآن حق الوصول إلى الملفات والمجلدات المضبوطة فقط؛ تأكد من إضافة القيود لكل مجلد تضبط مشاركته في سامبا؛ وستسجل أيضًا أيّة أخطاء إلى /var/log/syslog. مصادر الفصل الثامن عشر من «Samba HOWTO Collection» مخصصٌ للحماية. للمزيد من المعلومات حول Samba و ACLs، راجع الصفحة «Samba ACLs». راجع أيضًا صفحة ويكي أوبنتو «Samba». ترجمة -وبتصرف- للمقال Ubuntu Server Guide: Securing File and Printer.
-
- أوبنتو
- ubuntu server
-
(و 8 أكثر)
موسوم في:
-
نظام ملفات الشبكة (NFS)يسمح NFS للنظام بمشاركة المجلدات والملفات مع الآخرين عبر الشبكة؛ إذ يمكن للمستخدمين والبرامج الوصول إلى الملفات في الأنظمة البعيدة كأنها ملفاتٌ محلية باستخدام NFS. بعض الميزات الملحوظة التي يوفرها استخدام NFS: محطات العمل المحلية تستهلك مساحة قرص أقل ﻷنها تستخدم بيانات يمكن تخزينها على جهاز واحد وتبقى متاحةً للبقية عبر الشبكة.لا توجد حاجة ليُنشَأ للمستخدمين مجلدات منزل منفصلة في كل جهاز شبكي؛ حيث يمكن ضبط مجلدات المنزل على خادوم NFS وتتوفر للجميع عبر الشبكة.أجهزة التخزين مثل سواقات CD-ROM وأقراص USB يمكن استخدامها من الأجهزة الأخرى على الشبكة، وربما يقلل هذا من عدد مشغلات الوسائط القابلة للإزالة في الشبكة.التثبيتأدخل الأمر الآتي في الطرفية لتثبيت خادوم NFS: sudo apt-get install nfs-kernel-serverالضبطتستطيع ضبط المجلدات لكي «تُصدَّر» عبر إضافتها لملف /etc/exports، على سبيل المثال: /ubuntu *(ro,sync,no_root_squash) /home *(rw,sync,no_root_squash)تستطيع استبدال * بإحدى صيغ أسماء المضيفين، تأكد من أن تعريف اسم المضيف محدد كي لا تستطيع الأنظمة غير المعنية أن تصل إلى NFS. نفِّذ الأمر الآتي في مِحَث الطرفية لتشغيل خادوم NFS: sudo service nfs-kernel-server startضبط عميل NFSاستخدم الأمر mount لوصل مجلد NFS مشترك من جهاز لآخر؛ وذلك بكتابة أمرٍ شبيه بالأمر الآتي في الطرفية: sudo mount example.hostname.com:/ubuntu /local/ubuntuتحذير: يجب أن تكون نقطة الوصل /local/ubuntu موجودةً مسبقًا، ولا يجب أن يكون هنالك أيّة ملفات أو مجلدات فرعية في نقطة الوصل. طريقة أخرى لوصل مشاركة NFS من جهاز لآخر هي إضافة سطر إلى ملف /etc/fstab؛ يجب أن يُحدِّد هذا السطر اسم مضيف خادوم NFS، والمجلد الذي صُدِّرَ من الخادوم، والمجلد في الجهاز المحلي الذي يجب وصل NFS إليه؛ الشكل العام للسطر الذي سيُضاف إلى ملف /etc/fstab هو: example.hostname.com:/ubuntu /local/ubuntu nfs rsize=8192,wsize=8192,timeo=14,intrإذا حدثت معك مشكلة في وصل NFS، فتأكد أن الحزمة nfs-common مثبتة في نظام عميلك؛ وذلك بإدخال الأمر الآتي في الطرفية: sudo apt-get install nfs-commonمصادرLinux NFS faqصفحة ويكي أوبنتو «NFS Howto»«مبادر» iSCSIإن iSCSI (Internet Small Computer System Interface) هو بروتوكول يسمح بنقل أوامر SCSI عبر الشبكة؛ عادةً يُستخدَم iSCSI في SAN (Storage Area Network) للسماح للخواديم بالوصول إلى مخزن كبير لمساحة القرص الصلب؛ يُشير بروتوكول iSCSI للعملاء «بالمبادرين» (initiators) ولخواديم iSCSI بالأهداف (targets). يمكن أن يُضبَط خادوم أوبنتو كمبادر أو هدف iSCSI، يوفر هذا الدرس الأوامر والضبط اللازم لإعداد مبادر iSCSI، على فرض أنك تملك هدف iSCSI في شبكتك وتملك الامتيازات المناسبة للاتصال إليه؛ التعليمات حول إعداد هدف تختلف اختلافًا كبيرًا بين مزودي العتاد، لذلك راجع توثيق الشركة لضبط هدف iSCSI الذي عندك. تثبيت مبادر iSCSIلضبط خادوم أوبنتو كمبادر iSCSI، فثبِّت الحزمة open-iscsi بإدخال الأمر الآتي: sudo apt-get install open-iscsiضبط مبادر iSCSIبعد أن تُثبَّت حزمة open-iscsi، عليك تعديل الملف /etc/iscsi/iscsid.conf مغيرًا ما يلي: node.startup = automaticتستطيع التأكد إذا كان الهدف متوفرًا حاليًا باستخدام الأداة iscsiadm؛ وذلك بإدخال الأمر الآتي في الطرفية: sudo iscsiadm -m discovery -t st -p 192.168.0.10-m: يحدد النمط الذي سيُنفَّذ فيه iscsiadm.-t: يحدد نوع الاستكشاف.-p: يحدد عنوان IP للهدف.ملاحظة: عدِّل 192.168.0.10 إلى عنوان IP للهدف على شبكتك المحلية. إذا كان الهدف متوفرًا، فيجب أن تشاهد مخرجات شبيهة بما يلي: 192.168.0.10:3260,1 iqn.1992-05.com.emc:sl7b92030000520000-2ملاحظة: قد يختلف رقم iqn وعنوان IP في الأعلى بناءً على العتاد الذي تستخدمه. يجب أن تكون الآن قادرًا على الاتصال بهدف iSCSI، واعتمادًا على إعدادات الهدف، فربما تحتاج لإدخال بيانات المستخدم لتسجيل الدخول إلى عقدة iSCSI: sudo iscsiadm -m node --loginتأكد الآن أن القرص الجديد قد عُثِرَ عليه باستخدام dmesg: dmesg | grep sd [ 4.322384] sd 2:0:0:0: Attached scsi generic sg1 type 0 [ 4.322797] sd 2:0:0:0: [sda] 41943040 512-byte logical blocks:(21.4GB/20.0 GiB) [ 4.322843] sd 2:0:0:0: [sda] Write Protect is off [ 4.322846] sd 2:0:0:0: [sda] Mode Sense: 03 00 00 00 [ 4.322896] sd 2:0:0:0: [sda] Cache data unavailable [ 4.322899] sd 2:0:0:0: [sda] Assuming drive cache: write through [ 4.323230] sd 2:0:0:0: [sda] Cache data unavailable [ 4.323233] sd 2:0:0:0: [sda] Assuming drive cache: write through [ 4.325312] sda: sda1 sda2 < sda5 > [ 4.325729] sd 2:0:0:0: [sda] Cache data unavailable [ 4.325732] sd 2:0:0:0: [sda] Assuming drive cache: write through [ 4.325735] sd 2:0:0:0: [sda] Attached SCSI disk [2486.941805] sd 4:0:0:3: Attached scsi generic sg3 type 0 [2486.952093] sd 4:0:0:3: [sdb] 1126400000 512-byte logical blocks: (576 GB/537 ↪ GiB) [2486.954195] sd 4:0:0:3: [sdb] Write Protect is off [2486.954200] sd 4:0:0:3: [sdb] Mode Sense: 8f 00 00 08 [2486.954692] sd 4:0:0:3: [sdb] Write cache: disabled, read cache: enabled, ↪ doesn't support DPO or FUA [2486.960577] sdb: sdb1 [2486.964862] sd 4:0:0:3: [sdb] Attached SCSI diskفي الناتج أعلاه، يكون sdb هو قرص iSCSI الجديد؛ تذكر أن هذا مجرد مثال، قد يختلف الناتج عمّا تراه على الشاشة. أنشِئ الآن قسمًا، وهيّء نظام الملفات، وصِل قرص iSCSI الجديد؛ وذلك بإدخال ما يلي في الطرفية: sudo fdisk /dev/sdb n p enter wملاحظة: الأوامر الآتية من داخل الأداة fdisk؛ راجع man fdisk لتعليمات تفصيلية؛ أيضًا الأداة cfdisk في بعض الأحيان تكون «صديقة» للمستخدم أكثر. هيّء الآن نظام الملفات وصِله إلى /srv على سبيل المثال: sudo mkfs.ext4 /dev/sdb1 sudo mount /dev/sdb1 /srvفي النهاية، أضف مدخلة إلى /etc/fstab لوصل قرص iSCSI أثناء الإقلاع: /dev/sdb1 /srv ext4 defaults,auto,_netdev 0 0فكرة جيدة هي التأكد أن كل شيء يعمل على ما يرام قبل إعادة تشغيل الخادوم. مصادرموقع Open-iSCSI الإلكتروني.صفحة ويكي دبيان «Open-iSCSI».ترجمة -وبتصرف- للمقالين: Ubuntu Server Guide: Network File System NFS و Ubuntu Server Guide: ISCSI Initiator.
-
إن eCryptfs هو نظام ملفات للتشفير متوافق مع معايير POSIX ومن فئة الشركات لنظام لينُكس؛ وبتشكيل طبقة فوق طبقة نظام الملفات، فإن eCryptfs يحمي الملفات بغض النظر عن نظام الملفات المُستخدَم أو نوع القسم ...إلخ. هنالك خيار أثناء التثبيت لتشفير قسم /home، هذا سيضبط تلقائيًا كل شيء يحتاج له النظام لتشفير ووصل ذاك القسم. سنشرح هنا طريقة الضبط لتشفير /srv باستخدام eCryptfs. استخدام eCryptfsأولًا، ثبِّت الحزم اللازمة، بإدخال الأمر الآتي من الطرفية: sudo apt-get install ecryptfs-utilsالآن صِل القسم الذي تريد تشفيره: sudo mount -t ecryptfs /srv /srvستُسأل الآن عن بعض التفاصيل حول كيفية تشفير البيانات. لاختبار أن الملفات الموجودة في /srv هي مشفرة، فانسخ المجلد /etc/default إلى /srv: sudo cp -r /etc/default /srvثم افصل القسم /srv، وحاول عرض الملف: sudo umount /srv cat /srv/default/cronإعادة وصل /srv باستخدام ecryptfs ستجعل البيانات قابلةً للعرض مرةً أخرى. وصل الأقسام المشفرة تلقائياهنالك طريقتان لوصل نظام ملفات مُشفَّر باستخدام ecryptfs أثناء الإقلاع؛ سيستخدم هذا المثال الملف /root/.ecryptfsrc الذي يحتوي على خيارات الوصل، بالإضافة إلى ملف مرور موجود على قرص USB. أنشِئ أولًا الملف /root/.ecryptfsrc الذي يحتوي على: key=passphrase:passphrase_passwd_file=/mnt/usb/passwd_file.txt ecryptfs_sig=5826dd62cf81c615 ecryptfs_cipher=aes ecryptfs_key_bytes=16 ecryptfs_passthrough=n ecryptfs_enable_filename_crypto=nملاحظة: عدِّل ecryptfs_sig إلى التوقيع في /root/.ecryptfs/sig-cache.txt. ثم أنشِئ ملف المرور /mnt/usb/passwd_file.txt: passphrase_passwd=[secrets]أضف الآن الأسطر الضرورية إلى ملف /etc/fstab: /dev/sdb1 /mnt/usb ext3 ro 0 0 /srv /srv ecryptfs defaults 0 0تأكد أن قرص USB سيوصل قبل القسم المشفر. في النهاية، أعد الإقلاع ويجب أن يوصل /srv باستخدام eCryptfs. أدوات أخرىالحزمة ecryptfs-utils تحتوي على أدواتٍ أخرى مفيدة: الأداة ecryptfs-setup-private تُنشِئ مجلد ~/Private الذي يحتوي على المعلومات المشفرة؛ يمكن تنفيذ هذه الأداة من المستخدمين العاديين للحفاظ على بياناتهم من المستخدمين الآخرين على النظام.الأداة ecryptfs-mount-private والأداة ecryptfs-umount-private ستصل أو تفصل مجلد ~/Private على التوالي وبالترتيب.ecryptfs-add-passphrase: إضافة عبارة مرور لما يسمى «kernel keyring».ecryptfs-manager: إدارة كائنات eCryptfs مثل المفاتيح.ecryptfs-stat: السماح لك بعرض معلومات eCryptfs الوصفية لملفٍ ما.مصادرللمزيد من المعلومات حول eCryptfs، راجع صفحة المشروع على Lanuchpad.هنالك مقالة في Linux Journal تشرح eCryptfs.للمزيد من خيارات eCryptfs، راجع صفحة الدليل man ecryptfs.لدى صفحة ويكي أوبنتو «eCryptfs» المزيد من التفاصيل.ترجمة -وبتصرف- للمقال Ubuntu Server Guide: eCryptfs.
-
- 1
-
- نظام ملفات
- ملفات
-
(و 5 أكثر)
موسوم في:
-
سوف نتطرق في هذا الدرس إلى كيفية تنسيق وتخصيص عناصر <"input type="file> بالطريقة الصحيحة والسليمة وباستعمال العنصر <label> وبعض الجافاسكربت. معاينة النتيجة النهائية. يمكنك تحميل الشيفرة المصدرية للأمثلة من هنا. هناك العديد من الطرق لتخصيص العنصر <"input type="file> وقد جربت العديد منها ولكنها لم تعجبني ولم تُلبّي متطلباتي. لذلك حاولت البحث في Google ولكني لم أجد مبتغاي. وبعد أن فقدت الأمل وظننت أنني لن أجد ما أبحث عنه وقعت عيني بالصدفة على أحد التعليقات الموجودة في موقع StackOverflow، وكان ذلك التعليق يحتوي على كلمة "<label>" وكان ذلك بداية الخيط وأعتقد أنّه ما كنت أبحث عنه. وكما تعلمون فالنقر على عنصر label يؤدي إلى تفعيل أحد عناصر <input> مرتبطة به، ومما يثير الاهتمام أنّه إذا كان ذلك العنصر عبارة عن <"input type="file> فإنّ النقر على الـlabel المرتبطة به يؤدي إلى فتح متصفح الملفات وهذا هو الحل المثالي الذي كنت أبحث عنه. <input type="file" name="file" id="file" class="inputfile" /> <label for="file">Choose a file</label>أي أنّ النقر على أي واحد من هذين العنصرين (<label> أو <"input type="file>) سوف يعطي نفس النتيجة وهي فتح متصفح الملفات، وهذا يعني أنّ أصعب جزء قد تم حلُّه. لن نحتاج إلى جافاسكربت أو حلول معقدة، كل ما نحتاجه هو السطرين البرمجيين الموجودين في الأعلى. أنظر إلى الصورة في الأسفل. دعونا الآن نقوم بتنسيق العناصر حتى تبدو وكأنّنا نملك زرا عاديا. إخفاء عنصر <input>في البداية يجب علينا إخفاء العنصر <input>، وسوف تتكفل الخاصيتين display: none أو visibility: hidden بذلك. لماذا نريد إخفاءه؟ لأنّ قيمة المُدخل (input) لن يتم ارسالها إلى الخادوم عندما نقوم بعمل تسليم (submit) للنموذج. والسبب الثاني هو أننا لا نريد أن يتم تحديد ذلك العنصر عندما يقوم الزائر بتصفح الموقع باستعمال الزر tab الموجود على لوحة المفاتيح (لأننا نريد لموقعنا أن يكون قابل للوصول accessible). وبناءً على ذلك قمت باستعمال تنسيقات CSS التي تراها في الأسفل التي سوف تعمل على إخفاء العنصر عن أنظارنا ولكنه سيبقى مرئي بالنسبة للمتصفح نفسه: .inputfile { width: 0.1px; height: 0.1px; opacity: 0; overflow: hidden; position: absolute; z-index: -1; }قد تتسائل لماذا وضعنا القيمة 0.1px لكل من العرض والارتفاع وليس 0px. يعود السبب في ذلك إلى أنّه إذا أعطينا عنصر ما عرض وارتفاع بقيمة 0px فإنّنا لن نتمكن من استخدام زر tab على تلك العناصر في بعض المتصفحات. وأمّا بالنسبة للخاصية position: absolute فقد استخدمناها حتى نمنع أن يتداخل العنصر مع العناصر الأخرى. تنسيق العنصر <label>بما أنّ العنصر <label> هو الزر افتراضيًا فإننا نستطيع تنسيق هذا العنصر كما نريد. سنقوم بشيء بسيط هنا ولن نجعل التنسيقات معقدة: .inputfile + label { font-size: 1.25em; font-weight: 700; color: white; background-color: black; display: inline-block; } .inputfile:focus + label, .inputfile + label:hover { background-color: red; }الوصولية (accessibility)كيف يمكنك أن تعرف بأنّ أحد عناصر الصفحة قابل للنقر عليه؟ هناك شيئان يدلان على ذلك، الأول هو أنّ العنصر يجب أن يظهر عليه ذلك، بحيث يعطيك شعورًا بأنّه يمكنك النقر عليه أو استعمال زر tab، والثاني هو أنّه يجب أن يتغير مؤشر الفأرة إلى شيء مناسب عندما تقوم بوضع مؤشر الفأرة عليه. وبما أننا قمنا بفعل الشيء الأول سابقًا (من خلال التنسيقات الموجودة في الأعلى) فسوف نهتم بالشيء الثاني (تغير مؤشر الفأرة عند وضعه عليه) باستعمال بعض الأكواد البسيطة: .inputfile + label { cursor: pointer; /* "hand" cursor */ }أنظر إلى الصورتين التاليتين ولاحظ أنّ في الصورة الأولى لا يتغير مؤشر الفأرة على عكس الصورة الثانية التي يتغير فيها مؤشر الفأرة عند وضعه على العنصر ليعطي انطباعًا بأنّ هذا العنصر قابل للنقر. التصفح/التنقل باستخدام لوحة المفاتيحإن كان زوار موقعك لا يستطيعون تصفح موقعك باستخدام لوحة مفاتيح فقط فتأكد حينها أنّك تقوم بشيء خاطئ ويجب عليك اصلاحه. وقد كان إخفاء عنصر <input> بطريقة صحيحة هو أحد الأشياء الجيدة لتحسين تجربة المستخدم، وأمّا الشيء الآخر هو أن تُعطي للمستخدم انطباعًا ما بأنّ العنصر قد أصبح في حالة focus (يُصبح العنصر في حالة focus عند التصفح باستخدام زر tab في لوحة المفاتيح، وبالتالي نستطيع استخدام الفئة الزائفة focus: على ذلك العنصر): .inputfile:focus + label { outline: 1px dotted #000; outline: -webkit-focus-ring-color auto 5px; }تُستخدم القيمة webkit-focus-ring-color auto 5px من أجل الحصول على المظهر الإفتراضي للخط الخارجي (outline) في متصفحات Chrome، Opera وSafari. وبالنسبة للقيمة 1px dotted #00 فهي موجودة فقط للمتصفحات التي لا تفهم -webkit-. مشاكل متعلقة باللمس (touch)إذا كنت تستخدم FastClick (وهي مكتبة للتخلص من الإيقاف المؤقت للنقر والذي مُدته 300ms في الأجهزة التي تعمل باللمس) وكنت تنوي إضافة عناصر إضافية داخل العنصر <label>، فإنّ الزر لن يعمل كما يجب إلا إذا استخدمت الخاصية pointer-events: none: <label for="file"><strong>Choose a file</strong></label>.inputfile + label * { pointer-events: none; } تحسين بعض الأمور باستخدام الجافاسكربتبقي علينا شيء واحد يجب فعله وهو إظهار إذا ما كان هناك ملفات تم اختيارها أم لا. ومع أنّ العنصر <"input type="file> يُظهر ذلك عادةً إلا أننا قمنا بإخفائه إن كنت تذكر، ولكن لحسن حظنا فهناك طريقة لفعل ذلك باستخدام الجافاسكربت بحيث نجعل نص الـlabel هو اسم الملف المُختار، وإذا كان هناك عدة ملفات فإنّ نص الـlabel يصبح عدد تلك الملفات: <input type="file" name="file" id="file" class="inputfile" data-multiple-caption="{count} files selected" multiple />var inputs = document.querySelectorAll( '.inputfile' ); Array.prototype.forEach.call( inputs, function( input ) { var label = input.nextElementSibling; labelVal = label.innerHTML; input.addEventListener( 'change', function( e ) { var fileName = ''; if( this.files && this.files.length > 1 ) fileName = ( this.getAttribute( 'data-multiple-caption' ) || '' ).replace( '{count}', this.files.length ); else fileName = e.target.value.split( '\\' ).pop(); if( fileName ) label.querySelector( 'span' ).innerHTML = fileName; else label.innerHTML = labelVal; }); });قمت أيضًا بكتابة أكواد jQuery تقوم بنفس العمل، لذلك تأكد من أن تتصفح الملف المصدري إن كنت تفضل استخدام jQuery. توضيح بسيط للأكواد الموجودة في الأعلى:وجود الصفة multiple في عنصر <input> يسمح للمستخدم بأن يختار أكثر من ملف مرة واحدة. أمّا الصفة data-multiple-caption فهي تستخدم للتعبير عن الرسالة التي تريد أن تظهر للمستخدم عندما يقوم باختيار عدة ملفات. وبالنسبة للعبارة { count } فهي اختيارية وسوف يتم استبدالها برقم يُعبّر عن عدد الملفات المُختارة.الصفة multiple غير مدعومة في متصفح Internet Explorer 9 أو أقل ولا حتى الخاصية files الخاصة بالجافاسكربت، ولذلك سوف نعتمد على value. وبما أنّها عادةً تحتوي على قيمة بالصيغة C:\fakepath\filename.jpg فإنّ ()split( '\\' ).pop تقوم باستخراج اسم الملف.من المثير للاهتمام أنّه يمكنك إلغاء قيمة من المدخلات عن طريق الضغط على زر ESC عندما تكون نافذة تصفح الملفات مفتوحة، وهذا متاح فقط في متصفحي Chrome وOpera. ولهاذ استخدمنا المتغير labelVal لتخزين القيمة الافتراضية للـlabel وإرجاعها عند الحاجة لذلك.سوف تكون النتيجة النهائية كما في الصورة: ولكن ماذا لو كانت الجافاسكربت غير مفعلة؟بما أنّه لا يوجد طريقة أخرى غير الجافاسكربت لمعرفة إذا ما قام المستخدم باختيار ملف أم لا، فإنّه من الأفضل الاعتماد على المظهر الافتراضي لمُدخِل الملفات من أجل سهولة الاستخدام. لذلك كل ما علينا فعله هو إضافة class باسم "no-js" للعنصر <html> ومن ثم نستخدم الجافاسكربت لاستبداله بالاسم "js" وبهذه الطريقة نعرف إذا كان الجافاسكربت مفعلًا أم لا. <html class="no-js"> <head> <!-- remove this if you use Modernizr --> <script>(function(e,t,n){var r=e.querySelectorAll("html")[0];r.className=r.className.replace(/(^|\s)no-js(\s|$)/,"$1js$2")})(document,window,0);</script> </head> </html>وهذه تنسيقات CSS: .js .inputfile { width: 0.1px; height: 0.1px; opacity: 0; overflow: hidden; position: absolute; z-index: -1; } .no-js .inputfile + label { display: none; } خطأ في متصفح Firefoxإنّه لمن المفاجئ معرفة أنّ متصفح Firefox يتجاهل input[type="file"]:focus بينما تعمل :hover و:active بشكل جيد. ولكن لحسن الحظ فإنّ هذا المتصفح يسمح لنا بالتعرف على حالة focus باستخدام الجافاسكربت، لذلك فإنّ الحل هو إضافة class للعنصر <input> ليسمح لنا بالتحكم بحالة الـfocus: input.addEventListener( 'focus', function(){ input.classList.add( 'has-focus' ); }); input.addEventListener( 'blur', function(){ input.classList.remove( 'has-focus' ); });.inputfile:focus + label, .inputfile.has-focus + label { outline: 1px dotted #000; outline: -webkit-focus-ring-color auto 5px; } خاتمةإلى هنا نكون قد وصلنا إلى نهاية هذا الدرس. لذلك تأكد بأن تطلع على الشفرة المصدرية وعلى المعاينات وأن تقوم بالتعديل عليها لتتناسب مع احتياجاتك وذوقك. كما أنّ لديك الحرية الكاملة في استخدام الشفرات الموجودة في هذا الدرس في مشاريعك القادمة. ترجمة -وبتصرّف- للمقال Styling & Customizing File Inputs the Smart Way لصاحبته Osvaldas Valutis.
-
- 1
-
- جافا سكربت
- label
-
(و 6 أكثر)
موسوم في:
-
عادة ما تستخدم الصور لزيادة قبول المقالات ووضوحها، ولكن بالرغم من انتشارها الواسع، فقد أُهملت صفحة المرفق للأسف، وصفحة المرفق هي صفحة مخصصة لمرفق بسيط، صورة مثلًا. لا تخصص العديد من القوالب صفحة للمرفق، مما يعني أن موقعك ومستخدميك يفتقدون مصدر مهم للمعلومات، وإضافة جيدة لـ SEO. في هذا المقال سنشرح صفحة المرفق مع كيفية إنشاءها. ما هو المرفق؟في ووردبريس المرفق هو ملف مرفوع على الموقع، قد يكون صورة، ملف مضغوط، فيلم أو ملف PDF. وتُخزن المرفقات في جدول المقالات بقاعدة بيانات الموقع، أي في نفس المكان الذي تُخزن فيه المقالات والصفحات. في الواقع، المرفقات هي مقالات من نوع مختلف – وهو "مرفق”. وهذه الطريقة في التخزين صُممت لتسهيل النفاذ والبحث، مثمرة عن تطوير أسهل وتقدم أسرع. ما هي صفحة المرفق؟صفحة المرفق هي صفحة منفردة. مصطلح الصفحة المنفردة هو مصطلح شامل، يتضمن أنواع مختلفة مثل صفحة المقال المفرد وصفحات المقال المنفرد المُخَصّص. وبما أن المرفق عبارة عن مقال، فهو أيضًا له صفحة منفردة، وتدعى صفحة المرفق. الصفحة المنفردة الخاصة بك هي صفحة مُخَصّصة لمقالك، وتعرض العنوان، المحتوى، البيانات الوصفية، التعليقات وما شابه. بالمثل، لا بد أن تكون صفحة المرفق مُخَصّصة للمرفق المعروض. أي لو كان المرفق صورة فيجب أن تحتوي الصفحة على العنوان، الصورة، والوصف، وقد تتضمن التعليقات ومعلومات أخرى عن الصورة. كيف تُعرض صفحة المرفق؟تستخدم كل صفحة في موقع ووردبريس ملف للقالب في عرض محتواها. و يمكنك مطالعة الهرم التسلسلي للقوالب لتحدد أي ملف يُستخدم في العرض. يُدعى الملف المستخدم لعرض صفحة المرفق في القالب attachment.php. قوالب كثيرة تتجاهل هذا الملف، وتستخدم الملف البديل وهو single.php. هذا في حد ذاته ليس بمشكلة، فكثير من صفحات المقال المنفرد مبنية بشكل يدعم العرض الجيد للمرفقات بدون أي نص برمجي إضافي. بعض الصفحات المنفردة تستخدم جمل الشروط "if-else"، التي تحدد كيفية ظهور الصفحة المنفردة في حالة عرض مرفق. للأسف، لا يهتم مطوري القوالب بتصميم صفحة المرفق، إذ أنهم عادة ما يكتفون بتصميم صفحة المقالة المنفردة، مما يثمر عن نتائج غير مستحبة: هذا مثال توضيحي لعرض صفحة المرفق في قالب X الغني عن التعريف. كما ترى فإنه لا يوضح أي معلومات عن الصورة ويعرضها كصورة مصغرة، بالرغم من أن الصورة كبيرة جدًا في الواقع. بالإضافة إلى فاصل مزدوج نتيجة لجزء فارغ لعدم وجوده في قسم المعلومات التفصيلية. يمكن لمطوري القوالب أداء أفضل من ذلك بتخصيص صفحات المرفق بحيث تعرض روابط إلى الصور التالية والسابقة، ومعلومات تفصيلية متعلقة بالصورة وهكذا دواليك. انظر إلى المثال الموضح من موقعي الخاص الذي يستخدم قالب Twenty Fifteen، القالب الافتراضي لووردبريس. ستجد أن الصورة معروضة مع الوصف المناسب أسفلها. وهي معروضة بأكبر مساحة تتناسب مع مقاييس الصفحة والأبعاد الأصلية مذكورة ضمن المعلومات التفصيلية. وهناك أيضًا جزء غير ظاهر في المثال هو استمارة التعليق ورابط إلى المقال الذي نشرت فيه الصورة. هذا أفضل بكثير! كيف أصل إلى صفحة المرفق؟أسهل طريق للوصول إلى صفحة المرفق هو الذهاب إلى قسم الوسائط في لوحة التحكم، ثم اختيار الصورة التي تريدها، وستجد خيار مشاهدة صفحة المرفق "View attachment page” تحت عنوان الصورة. يمكنك أيضًا استنتاج رابط الصفحة بسهولة إذا كنت تعلم رابط المقال المرفق إليه، ويستخدم موقعك روابط دائمة واضحة. فمثلًا إذا كان رابط المقال هو "http://mywebsite.com/my-post/” واسم ملف الصورة شيء مثل "my-image.jpg”، فمن المحتمل أن يكون رابط صفحة المرفق للصورة هو "http://mywebsite.com/my-post/my-image/”. كيف تنشء صفحة مرفقسنستخدم في مثالنا هذا قالب Hueman المجاني، قالب رائع لكن ينقصه عرض لطيف لصفحة المرفق. ملف صفحة المرفقاتسنبدأ بإنشاء قالب فرعي قبل إجراء أي تعديلات. وهذا سيكون صعبًا بعض الشيء لإنك ستحتاج لنسخ ملفات قالبك الحالي كيفما أمكن للتأكد من أن قالبك الجديد مماثل في الرؤية مع القالب الرئيسي. وتعتمد صعوبة أو سهولة هذه الخطوة على وضوح النص البرمجي للقالب الخاص بك. حيث توجد قوالب عديدة صعب قراءة نصها البرمجي، مما يؤثر على سهولة عملية التعديل. بدايةً، أنشء ملف attachment.php في قالبك الفرعي. ويمكنك التأكد من هذه الخطوة بزيارة صفحة المرفق. يجب أن تكون بيضاء، حيث أن الملف نفسه فارغ. ثم انسخ محتويات ملف single.php بالكامل من القالب الرئيسي إلى ملف attachment.php الجديد. وعندئذ عندما تفتح صفحة المرفق مجددًا فيجب أن تجدها عادت كما كانت سابقًا إذ أنها تستخدم نفس الكود (لا تنس أن ووردبريس يستخدم ملف صفحة المقال المنفرد في حالة عدم وجود ملف صفحة المرفق)، فقط من ملف مختلف. تخصيص صفحة المرفقنريد أن نتجنب التعديلات غير الضرورية في الملف. وستجد بالنظر إلى النص البرمجي أن ما نحتاج إلى تغييره هو ما يقع ضمن عنصر post-inner. فقط. وهذا يعني، في النسخة التي نعمل عليها، كل شيء يقع ضمن السطور 12-27 في هذا الملف. وهذا ما صار إليه الآن: <h1 class="post-title"><?php the_title(); ?></h1> <p class="post-byline"> <?php _e('by','hueman'); ?> <?php the_author_posts_link(); ?> · <?php the_time(get_option('date_format')); ?> </p> <?php if( get_post_format() ) { get_template_part('inc/post-formats'); } ?> <div class="clear"></div> <div class="entry"> <div class="entry-inner"> <?php the_content(); ?> <?php wp_link_pages(array('before'=>'<div class="post-pages">'.__('Pages:','hueman'),'after'=>'</div>')); ?> </div> <div class="clear"></div> </div><!--/.entry-->والآن سننشء التصميم الذي يُظهر الصورة بالأعلى، يليها العنوان والوصف. دعنا نتخلص من قسم البيانات الوصفية بالإضافة إلى جزء أنواع المقالات إذ لا نحتاجهم. <?php echo wp_get_attachment_image( get_the_ID(), 'large' ); ?> <h1 class="post-title"><?php the_title(); ?></h1> <div class="entry"> <div class="entry-inner"> <?php the_content(); ?> </div> <div class="clear"></div> </div><!--/.entry-->يوضح النص البرمجي بالأعلى المحتوى المُعدل الذي يقع ما بين وسميّ البداية والنهاية لعنصر post-inner. وقد استخدمت وظيفة ()wp_get_attachment_image لاستحضار الصورة بتوفير رقم ID للمقال الحالي – لا تنس أنه أيضًا رقم ID للصورة حيث أننا في صفحة المرفق – واخترت الحجم الكبير للصورة. والآن أصبح لدينا العنوان والوصف بنفس تنسيق القالب الأصلي. وحذفت قسم البيانات الوصفية وترقيم الصفحات للمقال، الآن أصبح أفضل بكثير: يمكننا الاكتفاء بهذا، لكني أريد أن أعرض فكرة لإضافة تفاصيل أكثر إلى الصفحة، دعنا نضيف روابط للأحجام المختلفة من الصورة لتسهيل التحميل. عن طريق وظيفة ()wp_get_attachment_metadata التي تتيح عرض قائمة لكل أحجام الصورة وتصفحها في حلقة Loop. وهذا مثال لكتابتها: <div class="entry"> <div class="entry-inner"> <?php the_content(); ?> <p class='resolutions'> Downloads: <?php $images = array(); $image_sizes = get_intermediate_image_sizes(); array_unshift( $image_sizes, 'full' ); foreach( $image_sizes as $image_size ) { $image = wp_get_attachment_image_src( get_the_ID(), $image_size ); $name = $image_size . ' (' . $image[1] . 'x' . $image[2] . ')'; $images[] = '<a href="' . $image[0] . '">' . $name . '</a>'; } echo implode( ' | ', $images ); ?> </p> </div> <div class="clear"></div> </div><!--/.entry-->ترى أنني عدّلت محتوى جزئية entry.، حيث أضفت عنصرًا جديدًا لعرض الأحجام. وفيه استخرجت أحجام الصورة المعرّفة باستخدام ()get_intermediate_image_sizes. وما تبقى هو مجرد حلقة بسيطة، تدور عبر أحجام الصورة مع استخراج الأبعاد بالإضافة إلى الرابط لكل صورة. وقد استخدمت هذه البيانات لإنشاء بعض الروابط وكتابتها في النهاية. الختامصفحات المرفق رائعة لأنها توفر لك فرصة لتقدم شيئًا قيمًا للقراء: معلومات أكثر عن صورك، خواطرك عنها، وربما روابط التحميل أو حتى معلومات عن الكاميرا والتقنيات التي استُخدمت في إلتقاطها. هذه المعلومات الغنية لها تقييم عالٍ على جوجل إذا استُخدمت بشكل دائم وصحيح. فهي أكثر من مجرد خاصية جذابة. إذا لم تمتلك صفحة مرفق بعد، فإني أقترح عليك إتباع هذا المقال وإنشاءها الآن. يمكنك أيضًا تحميل قالب Hueman الفرعي الذي أنشأته في هذا المقال، بالرغم من أنه سيكون ذا فائدة فقط إذا استخدمت قالب Hueman بالفعل كقالب رئيسي. هل وجدت هذا المقال مفيدًا؟ سنسعد بمعرفة آرائكم والرد على استفساراتكم في التعليقات. مترجم بتصرف من مقال Creating an Advanced Attachment Page in WordPress لصاحبه Daniel Pataki.
-
- مرفق
- attachment
- (و 5 أكثر)