گیک فارسی

نوشته های یک گیک فارسی از فعالیت ها ،‌ علاقه مندی ها و نقد هایش

پیدا کردن فایل‌هایی که BOM دارن و طریقه حذف کردنشون

نویسنده:
20 جولای 15

همچنان یکی از چالشی ترین مباحثی که توی انجمن‌های PHP بهش بر میخورم خطای معروف Headers Already Sent هست که توضیحات مختصری توی این پُست در موردش دادم و اگه اون را بخونین متوجه میشین که وجود BOM یا همون Byte Order Mark یکی از مهمترین دلایلی هست که باعث به وجود اومدن این خطا میشه.

البته همیشه BOM باعث این مشکل نیست اما اگه بتونیم بفهمیم آیا فایلی توی پروژه ما هست که آلوده (کلمه درستی نیست اما برای این مطلب کاربردیه !) به BOM باشه خودش خیلیه ! خوب توی لینوکس که اصلاً نیاز به فکر کردن نیست و با یک جستجوی ساده به دستور زیر میرسیم :

grep -rlI $'\xEF\xBB\xBF' . --include \*.php

توجه : فرض بر این هست که دستور را وقتی در پوشه اصلی پروژه هستیم میزنیم (. [نقطه] توی لینوکس یعنی پوشه جاری)

اگه فایلی نبود که قطعاً مشکل از BOM نیست و اگه چند تا فایل بود هم میتونیم یکی یکی بازشون کنیم و دوباره بدون BOM ذخیرشون کنیم ،‌اما اگه تعدادشون زیاد بود خوب میشه نوشت :

find . -type f -name '*.php' -exec sed '1s/^\xEF\xBB\xBF//' -i.bak {} \; -exec rm {}.bak \;

البته ممکنه این فایل‌ها هم با وجود داشتن BOM دخالتی توی خطای صفحه مربوط نداشته باشن و باید دنبال مشکلات دیگه گشت.

واوو… داشت یادم میرفت ،‌ نمیدونم چرا همیشه فرض میکنم خوانندگان وبلاگ من تا حالا متوجه شدن ویندوز ابزار مناسبی برای توسعه وب نیست و مهاجرت کردن به لینوکس اما خوب چه میشه کرد ،‌ همچنان ممکنه دوستانی ویندوز را ترجیح بدهند !

در مورد ویندوز هم یک برنامه bomremover هست که کارتون را راحت میکنه و به راحتی میتونید فایل‌های php را از BOM پاک کنید :

bomremover.exe D:\www\myWebsite *.php

به طور کلی هر برنامه‌ای که بتونه محتویات فایل‌ها را بررسی کنه و بتونید بهش مقدار HEX بدین باهاش میشه BOM ها را جستجو و حذف کرد. مقدار BOM برای UTF-8 هم EF BB BF هستش و نرم افزاری که میدونم این قابلیت را داره Total Commander هستش.

توضیحات مختصر و مفید در مورد خطای Headers Already Sent در PHP

نویسنده:
25 ژوئن 15

یکی از متداول ترین پرسش های برنامه نویسان در انجمن‌های PHP در مورد خطای Headers Already Sent هست.PHP به صورت عادی اطلاعات را Buffer نمیکنه ، یعنی خروجی ها را در لحظه ارسال میکنه ، خیلی ساده اگه بخوام بگم ، ارسال ها را به دو دسته تقسیم میکنیم یکی Header ها و دیگری Content یا همون محتوا ،‌Header ها قبل از محتوا ارسال میشن و این یک قرارداد بر اساس HTTP Protocol هست.

headers already sent

PHP وقتی شما اولین مقدار حالا بایت یا کاراکتر یا هر چی را ارسال میکنید ابتدا Header های استاندارد و اونهایی که شما با تابع ()header ارسال کردین را میفرسته و بعدش شروع به ارسال محتوا میکنه. حالا اگه شما بعد از ارسال محتوا تابع ()header را صدا بزنین خیلی طبیعیه که PHP بگه Header ها را ارسال کردم و نمیشه شما Header دیگری بفرستی !

این محتوا بعضی مواقع میتونه یک Space هم باشه یا کاراکتری که به چشم نمیاد مثل BOM که ادیتور ها برای فایل های یونیکد اضافه میکنن یا خطایی که PHP داره در موردش توی خروجی توضیح میده یا ممکنه خود شما بدون اینکه متوجه باشین دارین یک مقداری را با echo یا print ارسال میکنید.
در زمانی که این خطا را میبینید PHP در انتهای توضیح با Output Started At اشاره میکنه که اولین خروجی در چه فایلی و کجاش ارسال شده که میشه با بررسی اون فایل متوجه مشکل شد و اون را رفع کرد. راه دیگه این هست که با یک درخواست Http از یک نرم افزار مثل wget توی لینوکس یا هر چیز متشابه دیگه توی ویندوز بیایم و خروجی را بررسی کنیم و ببینیم داره چی ارسال میشه و بعدش اون مقدار را توی فایل هامون جستجو و مرتفع کنیم.

اگه بخوایم این حالت را نداشته باشیم و رفتاری شبیه به ASP .NET داشته باشیم باید به PHP بگیم خروجی را در لحظه ارسال نکنه و اون را Buffer کنه و در آخر همه را با هم اعم از Header و خروجی ارسال کنه. برای این کار از Output Buffering استفاده میکنیم. برای این کار قبل از شروع کد ها تابع ()ob_start را صدا میزنیم و در آخر هم ()ob_end_flush باعث ارسال اطلاعات به مرورگر کاربر میشه.

به طور کلی Output Buffering را فقط زمانی توصیه میکنم که واقعاً قصد دخل و تصرف در محتوا قبل از ارسال به کاربر را داشته باشین و در غیر این صورت روش معمول کفایت میکنه و بهتره با کمی صبر و بررسی مشکل ارسال Header را بررسی کنید.