Fork me on GitHub

خوش آمدید

اطلاعات بسیار قدیمی موجود در وب باعث می‌شود کاربران جدید پی‌اچ‌پی دچار سرگردانی شده و عادت‌های بد کدنوشتن (از جمله نا امن بودن کد) را در آن‌ها ایجاد می‌کند. پی‌اچ‌پی: از راه درستش یک راهنمای ساده و جامع از بهترین روش‌های کدنویسی در پی‌اچ‌پی است، که به بسیاری از راهنماهای معتبر در وب پیوند دارد که اکثر آن‌ها شامل بهترین روش‌های کدنویسی هستند.

استفاده از پی‌اچ‌پی استاندارد خاصی ندارد. هدف این وبسایت معرفی موضوعاتی برای توسعه‌دهندگان پی‌اچ‌پی است که تا به حال با آن برخورد نکرده‌اند، همچنین معرفی ایده‌هایی برای افراد حرفه‌ای است که ممکن است سال‌ها از این ایده‌ها استفاده کرده بدون اینکه به یاد داشته باشند. این وبسایت شما را به استفاده از یک ابزار خاص سوق نمی‌دهد بلکه گزینه‌های مختلفی پیش روی شما می‌گذارد، که هر زمان لازم باشد تفاوت بین آن‌ها گفته می‌شود.

این یک سند فعال و در حال تغییر است که طی بازه‌های زمانی با اطلاعات جدید و کاربردی جایگزین می‌شود.

ترجمه‌ها

وبسایت پی‌اچ‌پی: از راه درستش به زبان‌های مختلفی ترجمه شده است (یا در حال ترجمه است):

چگونه مشارکت کنم

کمک کنید تا این وبسایت را به بهترین منبع برای برنامه‌نویسان پی‌اچ‌پی (مخصوصا تازه واردها) تبدیل کنیم! مشارکت در Github

اطلاع رسانی کنید!

وبسایت پی‌اچ‌پی: از راه درستش بنرهایی مخصوص وب دارد که می‌توانید در سایت خود قرار دهید. پشتیبانی کنید و بگذارید تازه‌واردهای PHP به منابع خوب دسترسی داشته باشند.

مشاهده‌ی بنرها

Back to Top

شروع کنید

استفاده از آخرین نسخه پایدار (۵.۶)

اگر تازه با PHP آشنا شده‌اید توصیه می‌کنیم از آخرین نسخه‌ی پایدار PHP 5.5 استفاده کنید. PHP طی سال‌های اخیر ویژگی‌های جدید قدرتمندی را اضافه کرده است. با اینکه تفاوت نسخه‌های 5.2 تا 5.6 ناچیز به نظر می‌رسد اما تغییرات بزرگی را شامل می‌شود. اگر به دنبال تابع یا عملکرد خاصی هستید، مستندات رسمی php.net پاسخگوی شماست.

وب سرور پیش فرض

در PHP 5.4 و نسخه‌های بعد از آن، شما می‌توانید به راحتی یادگیری را آغاز کنید بدون آنکه نیاز به یک وب سرور کامل داشته باشید. برای راه‌اندازی سرور، دستور زیر را در زیرشاخه‌ی اصلی پروژه‌ی خود اجرا کنید:

> php -S localhost:8000

نصب در مکینتاش

سیستم عامل OSX به صورت پیش فرض PHP را نصب دارد اما از نسخه‌های قدیمی‌تر آن استفاده می‌کند. Lion با PHP 5.3.6، Mountain Lion با PHP 5.3.10 و Mavericks با PHP 5.4.17 همراه است.

برای بروزرسانی PHP در OSX می‌توانید از مدیر بسته‌های مختلف استفاده کنید، که توصیه ما استفاده از php-osx توسط Liip است.

شما همچنین می‌توانید خودتان آن را کامپایل کنید; در این صورت، اطمینان حاصل کنید که قبل از آن Xcode یا جایگزین Apple برای آن را نصب کرده باشید، که از وبسایت رسمی Apple قابل دریافت است.

بسته‌های آماده‌ای مانند MAMP یا XAMPP هستند که شامل زبان برنامه‌نویسی PHP، وب سرور Apache و پایگاه داده‌ی MySQL به همراه محیط گرافیکی ساده هستند.

نصب در ویندوز

در ویندوز نسخه‌های مختلفی از PHP وجود دارد. شما می‌توانید از باینری‌های مخصوص ویندوز یا فایل‌های msi استفاده کنید. فایل‌های msi از نسخه‌ی PHP 5.3.0 به بعد توسعه داده نشدند.

به منظور یادگیری و استفاده شخصی می‌توانید از وب سرور پیش فرض PHP که از نسخه‌ی 5.4 به بالا قابل دسترسی است استفاده کنید. اگر تمایل دارید از بسته‌های کاملی که شامل یک وب سرور کامل و پایگاه داده‌ی MySQL هستند استفاده کنید ابزارهایی مانند Web Platform Installer و Zend Server CE و XAMPP و EasyPHP و WAMP وجود دارند که به سرعت می‌توانید کار را با آن‌ها آغاز کنید. توجه داشته باشید، این ابزارها نسب به محیط اصلی سرور کمی متفاوت عمل می‌کنند و شما باید متوجه تغییرات آن‌ها در مقایسه با محیط سرورهای مبتنی بر لینوکس باشید.

اگر قصد دارید محیط اصلی توسعه نرم‌افزار تحت وب در ویندوز را پیاده‌سازی کنید بنابراین IIS7 بهترین گزینه برای شماست. شما می‌توانید از پلاگین phpmanager جهت پیکربندی PHP در ویندوز استفاده کنید. IIS7 به صورت پیش فرض با FastCGI ارایه می‌شود، تنها کافی است PHP را به صورت یک کنترل‌کننده در آن تنظیم کنید. جهت پشتیبانی و دسترسی به منابع بیشتر وبسایت iis.net بخشی مختص به PHP را دارد.

Vagrant

نرم‌افزار در محیط‌های متفاوت (محیط توسعه و تولید) دچار باگ‌های عجیبی می‌شود که هنگام اجرای رسمی، با آن مواجه می‌شوید. زمانی که با تیمی از توسعه‌دهندگان همکاری می‌کنید، بسیار دشوار است که محیط‌های مختلف توسعه را با یکدیگر سازگار و یکسان نگاه دارید.

اگر محیط توسعه‌ی شما ویندوز و محیط تولید شما لینوکس (یا هر محیط غیر ویندوزی) است یا در قالب یک تیم فعالیت می‌کنید، استفاده از یک ماشین مجازی را باید مد نظر داشته باشید. ممکن است کمی دشوار باشد، اما با استفاده از ابزاری مانند Vagrant می‌توانید یک ماشین مجازی ساده را در کوتاه‌ترین زمان آماده کنید. این بسته‌های پایه به صورت دستی قابل نصب هستند، یا می‌توانید از نرم‌افزارهایی مانند Puppet یا Chef جهت پیاده‌سازی اولیه‌ی آن‌ها برای شما، استفاده کنید. استفاده از این ابزارها برای ایجاد بسته‌های پایه روش مناسبی است جهت اطمینان حاصل کردن از این مورد که تمام بسته‌ها در محیط‌های متفاوت، عمکرد یکسانی خواهند داشت. همچنین می‌توانید بسته‌ی پایه‌ی خود را “نابود” کرده و دوباره آن را بسازید، بدون آنکه این کار را دستی انجام دهید.

Vagrant پوشه‌هایی را جهت اشتراک‌گذاری کد شما روی ماشین شما و ماشین مجازی ایجاد می‌کند، که به این معنی است شما فایل‌های خود را در ماشین خود ایجاد یا ویرایش می‌کنید و برنامه‌ی شما در ماشین مجازی اجرا می‌شود.

اندکی راهنمایی

اگر در استفاده از Vagrant به کمی راهنمایی نیاز دارید سه سرویس مختلف وجود دارند که شما را یاری می‌رسانند:

Back to Top

راهنمای سَبک کدنویسی

جامعه‌ی PHP بزرگ و پراکنده است که از کتابخانه‌ها، فریم‌ورک‌ها و اجزای گوناگونی تشکیل شده است. برای توسعه‌دهندگان PHP امری طبیعی است که بخشی از این ابزار را در پروژه‌های خود به کار ببرند. از این رو، بسیار مهم است که کد PHP از یک سبک استاندارد (تا آنجا که امکان دارد) طبعیت کند تا توسعه‌دهندگان بتوانند به سادگی از کتابخانه‌های مختلف در پروژه‌ی خود استفاده کنند.

گروه تعاملی فریم‌ورک PHP مجموعه‌ای از سبک‌ها را تهیه و آماده کرده است. تمام آن‌ها مربوط به کدنویسی نمی‌شوند، اما آن‌هایی که هستند عبارتند از:

این توصیه‌ها تقریبا مجموعه‌ای از قوانین هستند که پروژه‌هایی نظیر Drupal، Zend، Symfony، CakePHP و بسیاری دیگر از آن‌ها استفاده می‌کنند. شما می‌توانید از آن‌ها در پروژه‌های خود استفاده کنید، یا همان سبک کدنویسی خود را ادامه دهید.

در حقیقت باید طوری کد بنویسید که از یک استاندارد شناخته‌شده طبعیت کند. این استاندارد می‌تواند هر ترکیبی از PSRها یا یکی از استانداردهای ایجاد شده توسط PEAR یا Zend باشد. این بدان معنی است که سایر توسعه‌دهندگان به سادگی بتوانند با کد شما ارتباط برقرار کنند، و نرم‌افزارهایی که از اجزای جداگانه تشکیل شده‌اند با یکدیگر سازگاری داشته باشند.

شما می‌توانید از ابزاری مانند PHP CodeSniffer برای بررسی هر یک از این استانداردها، یا از افزونه‌هایی برای ویرایشگرهای متن مانند Sublime Text 2 استفاده کنید.

همچنین ابزار PHP Coding Standards Fixer که توسط Fabien Potencier توسعه داده شده، به صورت خودکار کد شما را نسبت به این استانداردها بررسی می‌کند و تغییرات لازم را انجام می‌دهد، لازم هم نیست شما این کار را به صورت دستی انجام دهید.

انگلیسی زبان اصلی برای تمام نمادها و ساختار کد است. کامنت‌ها می‌توانند به هر زبانی که برنامه‌نویسان در پروژه با آن آشنا هستند، نوشته شوند.

Back to Top

قابلیت‌های زبان

الگوهای برنامه‌نویسی

PHP زبانی انعطاف پذیر و پویا است که از تکنیک‌های برنامه‌نویسی مختلفی پشتیبانی می‌کند. طی سال‌ها تغییرات زیادی در آن ایجاد شده است که می‌توان به موارد زیر اشاره کرد:

برنامه‌نویسی شی‌گرا

ویژگ‌های بسیاری از مدل برنامه‌نویسی شی‌گرا در PHP پشتیبانی می‌شوند از جمله کلاس‌ها (Classes)، کلاس‌های انتزاعی (Abstract Classes)، رابط‌ها (Interfaces)، وراثت (Inheritance)، سازنده‌ها (Constructors)، کپی‌کردن (Cloning)، استثناها (Exceptions) و بسیاری دیگر.

برنامه‌نویسی تابعی

PHP از توابعی پشتیبانی می‌کند که می‌توانند به متغیرها انتساب داده شوند. چه توسط کاربر تعریف شده باشند چه داخلی باشند، می‌توانند توسط یک متغیر فراخوانی شوند. توابع می‌توانند به عنوان یک آرگومان به سایر توابع فرستاده شوند (قابلیتی که به آن توابع مرتبه-بالا گفته می‌شود) و هر تابعی می‌تواند توابعی دیگری را به عنوان خروجی بازگرداند.

بازگشت (Recursion)، قابلیتی که به یک تابع اجازه می‌دهد خود را فراخوانی کند، توسط زبان پشتیبانی می‌شود اما بیشتر کد PHP روی تکرار (Iteration) تاکید دارد.

توابع بی‌نام جدید (که از Closure پشتیبانی می‌کنند) از PHP 5.3 به بعد (۲۰۰۹) وجود دارند.

نسخه‌ی 5.4 از PHP قابلیت اتصال Closure به قلمرو شی (Object’s Scope) را اضافه کرده و همچنین پشتیبانی از فراخوانی‌هایی با توابع بی‌نام را بهبود بخشیده است.

برنامه‌نویسی Meta

از طریق مکانیسم‌هایی مانند Reflection API و Magic Meghods است که PHP از این سبک برنامه‌نویسی پشتیبانی می‌کند. متدهای مختلفی مانند ()get__ و ()set__ و ()clone__ و ()toString__ و ()invoke__ وجود دارند که به توسعه‌دهندگان اجازه می‌دهند رفتار داخلی یک کلاس را تغییر دهند. توسعه‌دهندگان Ruby اغلب می‌گویند PHP از نبود ‘method_missing’ رنج می‌برد در حالی که این عملکرد توسط ()call__ و ()callStatic__ قابل دسترسی است.

فضای نام‌گذاری

همان‌طور که اشاره شد، جامعه‌ی PHP توسعه‌دهندگان زیادی دارد که کدهای فراوانی تولید می‌کنند. این بدان معناست که کد PHP یک کتابخانه (Library) ممکن است از یک نام کلاس در کتابخانه‌ای دیگر استفاده کرده باشد. وقتی این دو کتابخانه در یک فضا استفاده می‌شوند، تداخل آن‌ها مشکل آفرین می‌شود.

فضای نام‌گذاری (Namespace) این مشکل را حل می‌کند. همان‌طور که در راهنمای رسمی PHP توضیح داده شده است، فضای نام‌گذاری در PHP مانند ساختار دایرکتوری در سیستم‌عامل عمل می‌کند. همان‌طور که دو فایل با نام‌های یکسان در دو دایرکتوری می‌توانند وجود داشته باشند، دو کلاس PHP با نام‌های یکسان در دو فضای نام‌گذاری جداگونه می‌توانند وجود داشته باشند. به همین سادگی!

مهم است که شما کد خود را با استفاده از فضای نام‌گذاری شده توسعه دهید تا اگر دیگران قصد استفاده از آن را داشتند، تداخلی به وجود نیاید.

یک روش توصیه شده در استفاده از فضای‌ نام‌گذاری در راهنمای PSR-0 موجود است، که ساختاری استاندارد برای فایل و کلاس ایجاد می‌کند.

در دی ماه ۱۳۹۲ PHP-FIG استانداردی جدید را به وجود آورد: PSR-4 که روزی جایگزین PSR-0 خواهد شد. هم‌اکنون هر دو قابل استفاده هستند با این تفاوت که PSR-4 به PHP 5.3 نیازمند است در حالی بسیاری پروژه‌های مبتنی بر PhP 5.2 از PSR-0 استفاده می‌کنند. اگر قصد استفاده از این استاندارد برای نرم‌افزار جدید خود را دارید بهتر است به PSR-4 نگاهی بیندازید.

کتابخانه‌ی استاندارد PHP

کتابخانه‌ی استاندارد PHP یا همان SPL مجموعه‌ای از کلاس‌ها و رابط‌ها را ارایه می‌دهد. از معمول‌ترین ساختارداده‌های مورد نیاز (پُشته، صَف و …) تشکیل شده است و تکرارشونده‌ها (Iterators) که اجازه می‌دهند این ساختارهای داده مورد پیمایش قرار گیرند یا اینکه کلاس‌های خود شما وظیفه‌ی پیاده‌سازی این عملکرد‌ها را بر عهده می‌گیرند.

رابط خط فرمان

هدف اصلی از توسعه‌ی PHP ایجاد نرم‌افزارهای تحت وب است اما می‌توان از آن در نرم‌افزارهای خط فرمان (CLI) استفاده کرد. برنامه‌های خط فرمان مبتنی بر PHP می‌توانند در تست، توسعه و مدیریت نرم‌افزار، مورد استفاده قرار گیرند.

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

اجرای PHP از خط فرمان:

> php -i

گزینه i- تنظیمات محیط PHP را نمایش می‌دهد درست مانند تابع phpinfo.

گزینه a- یک پوسته (Shell) تعاملی را فراهم می‌آورد، شبیه به IRB در Ruby یا پوسته‌ی تعاملی در Python. همچنین گزینه‌های کاربردی دیگری نیز وجود دارند.

بیایید یک برنامه‌ی ساده “Hello, $name” بنویسیم. جهت آزمایش، فایل hello.php را طبق خطوط زیر ایجاد کنید.

<?php
if ($argc != 2) {
    echo "Usage: php hello.php [name].\n";
    exit(1);
}
$name = $argv[1];
echo "Hello, $name\n";

بر اساس آرگومان‌هایی که اسکریپت شما با آن اجرا می‌شود، PHP دو متغیر مخصوص را راه‌اندازی می‌کند. argc$ یک متغیر عددی که تعداد آرگومان‌ها را مشخص می‌کند و argv$ یک متغیر از نوع آرایه که مقدار هر آرگومان را ذخیره می‌کند. اولین آرگومان همیشه نام فایل اسکریپت است، در اینجا hello.php.

عبارت ()exit به همراه یک عدد غیر صفر به کار رفته است که به پوسته اعلام می‌کند فرمان دریافت‌شده نامعتبر است. کدهای متداول برای این عبارت از این قسمت قابل دسترسی هستند.

برای اجرای اسکریپت بالا، از خط فرمان:

> php hello.php
Usage: php hello.php [name]
> php hello.php world
Hello, world

XDebug

یکی از کاربردی‌ترین ابزارها در توسعه‌ی نرم‌افزار، اشکال‌زدا (Debugger) است. به شما اجازه‌ می‌دهد نحوه‌ی اجرای کد را پیگیری کرده و در هر لحظه محتویات حافظه را ببینید. نرم‌افزاری که در PHP به این منظور استفاده می‌شود، XDebug نام دارد که توسط IDEهای مختلفی پشتیبانی می‌شود. همچنین به ابزارهایی مانند PHPUnit و KCacheGrid اجازه می‌دهد عملیات تحلیل و بررسی کد را انجام دهند.

اگر در کد شما مشکلی به وجود آمده و قادر نیستید با استفاده از var_dump یا print_r خطایابی کنید، شاید زمان آن فرارسیده باشد که از یک اشکال‌زدا استفاده کنید.

نصب XDebug می‌تواند کمی دشوار باشد، اما یکی از مهم‌ترین ویژگی‌های آن “اشکال‌زدایی از راه‌دور” است. اگر کد را در سیستم خود و عملیات آزمایش و اجرا را در یک ماشین مجازی یا سرور دیگری انجام می‌دهید، اشکال‌زدایی از راه‌دور ویژگی‌ای است که به آن نیاز خواهید داشت.

به طور معمول، می‌توانید فایل VirtualHost مربوط به Apache یا فایل htaccess. را اینگونه تنظیم کنید:

php_value xdebug.remote_host=192.168.?.?
php_value xdebug.remote_port=9000

عبارت‌های “remote_host” و “remote_port” مربوط به رایانه‌ی شخصی شما هستند و پورتی که IDE از طریق آن منتظر دریافت پاسخ است. فقط کافی است IDE را طوری تنظیم کنید که به حالت “انتظار” برود و نشانی زیر را بارگذاری کنید:

http://your-website.example.com/index.php?XDEBUG_SESSION_START=1

اکنون IDE شما می‌تواند در لحظه‌ی اجرای اسکریپت، عملیات مختلف اشکال‌زدایی را انجام دهد.

اشکال‌زداهای گرافیکی کار را بسیار آسان می‌کنند تا بتوانید کد را ببینید، متغیرها را شناساسی کنید و حتی به صورت زنده تغییرات را مشاهده کنید. بسیاری از IDEها یا خود از این عملکرد پشیتبانی می‌کنند یا با استفاده از افزونه‌ها امکان ایجاد اشکال‌زداهای گرافیکی را فراهم می‌آورند. برای نمونه، MacGDBp یک ابزار رایگان و جداگانه برای محیط گرافیکی XDebug در سیستم عامل مکینتاش است.

Back to Top

مدیریت وابستگی

کتابخانه‌ها، فریم‌وُرک‌ها و اجزای مختلفی از PHP وجود دارند که می‌توانید از آن‌ها استفاده کنید. به احتمال زیاد پروژه‌ی شما از این اجزا استفاده می‌کند، این‌ها وابستگی‌ (dependency) نام دارند. تا همین اواخر، روش مناسبی برای مدیریت این وابستگی‌ها درPHP وجود نداشت. حتی اگر شما این کار را می‌کردید، باید نگران فراخوانی‌های خودکار (autoloaders) می‌بودید. این روند دیگر ادامه ندارد.

هم اکنون دو مدیر بسته‌ی اصلی برای PHP وجود دارد، Composer و PEAR. کدام یک برای شما مناسب است؟ هر دو.

در حالت کلی، بسته‌های Composer تنها در پروژه‌هایی که شما تعیین می‌کنید وجود خواهند داشت در صورتی که بسته‌های PEAR برای تمام پروژه‌ها در دسترس خواهند بود. در ابتدا ممکن است به نظر برسد استفاده از PEAR مناسب است اما مزایایی در روش پروژه به پروژه وجود دارد که باید به آن‌ها فکر کنید.

Composer و Packagist

Composer یک مدیر بسته‌ی فوق‌العاده برای PHP است. وابستگی‌های پروژه‌ی خود را در یک فایل composer.json فهرست کنید و، با تنها چند فرمان ساده، تمام وابستگی‌ها دانلود شده و به صورت پیش‌فرض فراخوانی می‌شوند.

کتابخانه‌های بسیاری از PHP وجود دارند که با Composer سازگار هستند، که می‌توانید از آن‌ها استفاده کنید. این “بسته‌ها” در مخزن رسمی بسته‌های سازگار با Composer، یعنی Packagist فهرست شده‌اند.

چگونگی نصب خودکار Composer

شما می‌توانید Composer را به صورت محلی (در دایرکتوری فعلی، که توصیه نمی‌شود) یا سراسری (برای نمونه در usr/local/bin/) نصب کنید. فرض کنیم می‌خواهید به صورت محلی نصب کنید. از دایرکتوری اصلی پروژه‌ی خود:

curl -s https://getcomposer.org/installer | php

این فرمان composer.phar (فایل باینری PHP) را دانلود می‌کند. می‌توانید با استفاده از php برای مدیریت وابستگی‌ها در پروژه‌ی خود، از آن استفاده کنید. توجه کنید: اگر به صورت مستقیم کد دانلود شده را به یک مفسر (interpreter) ارجاع دهید، ابتدا از امن بودن کد اطمینان حاصل کنید.

نصب در ویندوز

برای کاربران ویندوز راحت‌ترین روش استفاده از نرم‌افزار ComposerSetup است، که نصب را به صورت سراسری انجام می‌دهد و PATH$ را طوری تنظیم می‌کند که بتوانید از هر دایرکتوری در خط فرمان، composer را فراخوانی کنید.

چگونگی نصب دستی Composer

این روش نصب کمی پیچیدگی دارد; اگرچه، دلایل مختلفی وجود دارد که یک توسعه‌دهنده این روش را نسبت به روش خودکار ترجیح دهد. در نصب خودکار، بررسی می‌شود در محیط PHP شما:

در صورتی که نصب دستی، هیچ کدام از موارد فوق را پوشش نمی‌دهد، البته شما باید تصمیم نهایی را بگیرید. در هر صورت، می‌توانید Composer را به صورت دستی با استفاده از فرمان‌های زیر نصب کنید:

curl -s https://getcomposer.org/composer.phar -o $HOME/local/bin/composer
chmod +x $HOME/local/bin/composer

مسیر HOME/local/bin$ (یا هر دایرکتوری دیگر به انتخاب شما) باید در متغیر محیطی PATH$ وجود داشته باشد. این کار منجر به ایجاد فرمان composer می‌گردد.

وقتی به مستندات مراجعه می‌کنید که می‌گوید Composer را با استفاده از php composer.phar install اجرا کنید، می‌توانید آن را با فرمان زیر جایگزین کنید:

composer install

در ادامه فرض می‌کنیم که Composer را به صورت سراسری نصب کرده‌اید.

ایجاد و نصب وابستگی‌ها

تمام وابستگی‌های پروژه‌ی شما در فایلی با نام composer.json توسط Composer ردیابی می‌شوند. می‌توانید خود آن را مدیریت کنید یا بگذارید Composer این کار را انجام دهد. فرمان composer require یک وابستگی برای پروژه تعریف می‌کند و اگر فایل composer.json وجود نداشته باشد، یکی ساخته می‌شود. برای نمونه، این فرمان Twig را به عنوان یک وابستگی برای پروژه تعریف می‌کند.

composer require twig/twig:~1.8

همچنین فرمان composer init شما را در ایجاد یک فایل کامل composer.json راهنمایی می‌کند. در هر صورت، هر زمان که فایل composer.json ساخته شود می‌توانید به Composer بگویید تمام وابستگی‌های پروژه را در دایرکتوری /vendors دانلود و نصب کند. این شامل پروژه‌هایی هم می‌شود که خود یک فایل composer.json دارند:

composer install

گام بعد اضافه کردن این خط کد در فایل اصلی PHP است; که به PHP می‌گوید از فراخوانی‌های Composer برای مدیریت وابستگی‌ها استفاده کند.

<?php
require 'vendor/autoload.php';

هم اکنون می‌توانید از وابستگی‌های پروژه‌ی خود استفاده کنید و هر زمان لازم باشد به صورت خودکار فراخوانی می‌شوند.

بروزرسانی وابستگی‌ها

وقتی برای اولین بار php composer.phar install را اجرا کردید، Composer فایلی با نام composer.lock را ایجاد می‌کند که نسخه‌ی دقیق هر بسته را در خود نگاه می‌دارد. زمانی که پروژه‌ی خود را با دیگران به اشتراک می‌گذارید و فایل composer.lock نیز همراه آن است، وقتی آن‌ها php composer.phar install را اجرا می‌کنند دقیقا همان نسخه از وابستگی‌ها را دریافت خواهند کرد. برای بروزرسانی وابستگی‌های خود، php composer.phar update را اجرا کنید.

این کار زمانی بسیار مفید است که در انتخاب نسخه‌ی وابستگی‌ها سخت‌گیری خاصی ندارید. برای نمونه، نیازمندی یک نسخه به 1.8~ یعنی “هر چیزی جدیدتر از 1.8.0 ولی قبل از 2.0”. می‌توانید از * نیز در *.1.8 استفاده کنید. حال فرمان php composer.phar update تمام وابستگی‌های شما را با توجه به محدودیتی که برایشان تعریف کرده‌اید، بروزرسانی خواهد کرد.

اطلاعیه‌های بروزرسانی

برای دریافت اطلاعیه درباره‌ی آخرین نسخه‌ها می‌توانید در VersionEye ثبت نام کنید، سرویسی که با مشاهده‌ی فایل composer.json موجود در حساب GitHub و BitBucket شما، با انتشار هر نسخه‌ی جدید با ایمیل به شما خبر می‌دهد.

بررسی مشکلات امنیتی در وابستگی‌ها

سرویس Security Advisories Checker که از خط فرمان نیز قابل اجرا است، با بررسی فایل composer.lock به شما می‌گوید آیا باید وابستگی‌های خود را بروزرسانی کنید یا خیر.

PEAR

مدیر بسته‌ی مشهور دیگری که بسیاری از توسعه‌دهندگان PHP از آن لذت می‌برند PEAR است. شبیه به Composer عمل می‌کند اما تفاوت‌های قابل توجه‌ای دارد.

هر بسته باید ساختار مشخصی داشته باشد، به این معنی که نویسنده‌ی بسته باید آن‌ را مطابق با استانداردهای PEAR آماده کند. استفاده از پروژه‌ای که با PEAR سازگار نیست، غیرممکن است.

تمام بسته‌ها در PEAR به صورت سراسری روی سرور نصب می‌شوند و برای تمام پروژه‌ها قابل استفاده هستند. برای پروژه‌های مختلفی که به یک بسته وابسته هستند راهکار بسیار خوبی است اما زمانی که دو پروژه در یک نسخه تفاوت داشته باشند، مشکل‌ساز خواهد شد.

چگونگی نصب PEAR

شما می‌توانید با دانلود و اجرای فایل phar مربوط به PEAR آن را نصب کنید. مستندات PEAR به جزییات دستورات نصب برای سیستم عامل‌های مختلف اشاره کرده است.

اگر از گنو/لینوکس استفاده می‌کنید، می‌توانید نگاهی به مدیر بسته توزیع خود بیندازید. برای نمونه، دبیان و اوبونتو یک بسته با نام php-pear دارند.

چگونکی نصب یک بسته

اگر بسته‌ی مورد نظر در فهرست بسته‌های PEAR وجود دارد، می‌توانید با اسم رسمی آن را نصب کنید:

pear install foo

اگر بسته در کانال دیگری قرار دارد، ابتدا باید آن کانال را discover کرده و در زمان نصب نام آن را ذکر کنید. برای اطلاعات بیشتر در این مورد، مستندات مربوط به کانال‌ها را مشاهده کنید

مدیریت وابستگی‌ها در PEAR با استفاده از Composer

اگر از Composer استفاده می‌کنید و قصد دارید تعدادی بسته‌ی PEAR هم داشته باشید، می‌توانید از Composer برای مدیریت این بسته‌ها بهره ببرید. این مثال، کد مورد نظر را از pear2.php.net دانلود و نصب می‌کند:

{
    "repositories": [
        {
            "type": "pear",
            "url": "http://pear2.php.net"
        }
    ],
    "require": {
        "pear-pear2/PEAR2_Text_Markdown": "*",
        "pear-pear2/PEAR2_HTTP_Request": "*"
    }
}

اولین بخش که "repositories" نام دارد به Composer می‌گوید باید مخزن مربوط به PEAR را “راه‌اندازی اولیه” (یا همان “discover” در اصطلاح PEAR) کند. سپس بخش "require" نام بسته‌ها را به این صورت تشخیص می‌دهد:

pear-channel/Package

در اینجا از پیشوند “pear” استفاده شده است تا هر گونه تشابه نام با سایر بسته‌ها از بین برود. وقتی این کد اجرا و بسته‌های مورد نیاز نصب شوند از دایرکتوری vendor قابل دسترس خواهد بود و به صورت خودکار توسط فراخوان Composer قابل فراخوانی است:

vendor/pear-pear2.php.net/PEAR2_HTTP_Request/pear2/HTTP/Request.php

به منظور استفاده از این بسته به راحتی آن را فراخوانی کرد:

$request = new pear2\HTTP\Request();

Back to Top

عادت‌های کدنویسی

مفاهیم مقدماتی

زبانی به وسعت PHP نه تنها به تمام برنامه‌نویسان اجازه‌ی کدنویسی سریع، بلکه این کار را بهینه انجام می‌دهد. البته هر چه بیشتر با این زبان آشنا شده و پیش می‌رویم مفاهیم مقدماتی که در ابتدا یاد گرفتیم را بر حسب عادت‌های بد یا روش‌های میانبر، فراموش می‌کنیم. برای مقابله با این مساله، در ادامه این مفاهیم را مرور خواهیم کرد.

تاریخ و زمان

برای خواندن، نوشتن و مقایسه‌ی تاریخ و زمان، از کلاس DateTime در PHP استفاده می‌شود. توابع مختلفی در رابطه با تاریخ و زمان وجود دارند اما ساختار شی‌گرا این کلاس به بیشتر نیازهای ما پاسخ می‌دهد. همچنین توانایی مدیریت منطقه‌های زمانی/جغرافیایی را نیز دارد که خارج از این مقدمه کوتاه است.

برای شروع، تنها کافی است تاریخ و زمان خام را به یک شی با استفاده از متد ()createFromFormat تبدیل کرده یا جهت دریافت تاریخ و زمان فعلی از new \DateTime استفاده کنیم. با استفاده از متد ()format می‌توان شی DateTime را به یک رشته‌ی قابل نمایش تبدیل کرد.

<?php
$raw = '22. 11. 1968';
$start = \DateTime::createFromFormat('d. m. Y', $raw);

echo 'Start date: ' . $start->format('m/d/Y') . "\n";

محاسبات روی DateTime با استفاده از کلاس DateInterval قابل انجام است. کلاس DateTime متدهایی مانند ()add و ()sub دارد که از DateInterval به عنوان آرگومان استفاده می‌کنند. کدی ننویسید که به ازای هر روز تعداد ثانیه‌های ثابتی را درخواست کند چرا که تغییر در منطقه‌های زمانی/جغرافیایی این فرض را باطل می‌کند. در عوض، از بازه‌های زمانی استفاده کرده و برای محاسبه‌ی اختلاف زمانی از متد ()diff استفاده کنید که مقدار بازگشتی آن DateInterval است و به راحتی می‌توان آن را نمایش داد.

<?php
// create a copy of $start and add one month and 6 days
$end = clone $start;
$end->add(new \DateInterval('P1M6D'));

$diff = $end->diff($start);
echo 'Difference: ' . $diff->format('%m month, %d days (total: %a days)') . "\n";
// Difference: 1 month, 6 days (total: 37 days)

روی شی DateTime می‌توانید از مقایسه‌های استاندارد استفاده کنید:

<?php
if ($start < $end) {
    echo "Start is before end!\n";
}

جهت پیمایش بین رخدادهای تکراری از کلاس DatePeriod استفاده کنید که دو شی DateTime را دریافت کرده (start و end) و با استفاده از بازه‌ی زمانی، تمام رخدادهای بین آن‌ها را محاسبه می‌کند.

<?php
// output all thursdays between $start and $end
$periodInterval = \DateInterval::createFromDateString('first thursday');
$periodIterator = new \DatePeriod($start, $periodInterval, $end, \DatePeriod::EXCLUDE_START_DATE);
foreach ($periodIterator as $date) {
    // output each date in the period
    echo $date->format('m/d/Y') . ' ';
}

الگوهای طراحی

زمانی که نرم‌افزار خود را توسعه می‌دهید مرسوم است از الگوهای خاصی در کد و ساختار کلی پروژه استفاده کنید. استفاده از این الگوها بسیار مفید است چرا که نه تنها باعث می‌شود مدیریت کد آسان گردد بلکه درک نرم‌افزار شما برای سایر توسعه‌دهندگان نیز آسان می‌گردد.

اگر از یک فریم‌ورک استفاده می‌کنید پس بیشتر قسمت‌های کدنویسی و ساختار پروژه که بر اساس آن فریم‌ورک است، از پیش برایتان مشخص شده است. اما در نهایت تصمیم با شماست که کد خود را بر اساس آن فریم‌ورک پیش ببرید یا خیر. اگر هم از فریم‌ورک استفاده نمی‌کنید باید خود به دنبال الگوهایی باشید که با نوع و اندازه‌ (حجم) پروژه‌ی شما سازگار باشند.

ادامه‌ی مطالعه درباره‌ی الگوهای طراحی

کار با UTF-8

محتوای اولیه‌ی این بخش توسط Alex Cabal در مجموعه‌ی بهترین عادت‌های کدنویسی در PHP نوشته شده است که در اینجا به عنوان مقدمه‌ی مقاله‌ی ما قرار دارد.

راهکار ثابتی وجود ندارد. دقت کرده، به جزییات توجه کنید و یکپارچه عمل کنید.

هم اکنون PHP در سطح پایین از یونیکد پشتیبانی نمی‌کند. روش‌هایی وجود دارد تا اطمینان حاصل کنیم تمام رشته‌های UTF-8 به درستی پردازش می‌شوند اما این روش‌ها آسان نیستند و لایه‌های مختلفی از یک نرم‌افزار تحت وب را شامل می‌شوند، از HTML به SQL به PHP. در ادامه آن‌ها را توضیح می‌دهیم.

UTF-8 در PHP

عملیات پایه روی رشته‌ها، مانند چسباندن دو رشته به یکدیگر یا تخصیص به متغیرها، به عملکرد خاصی رو UFT-8 احتیاج ندارد. با این وجود، بیشتر توابع رشته‌ای، مانند ()strpos و ()strlen، به توجه خاصی نیازمند هستند. این توابع معمولا یک معادل *_mb نیز دارند: مانند ()mb_strpos و ()mb_strlen. توابع *_mb با استفاده از افزونه‌ی Multibyte String قابل دسترس هستند و به طور خاص برای کار روی رشته‌های یونیکد طراحی شده‌اند.

هر زمان که با رشته‌های یونیکد سروکار دارید باید از توابع *_mb استفاده کنید. اگر از ()substr در یک رشته‌ی UTF-8 استفاده کنید، به احتمال زیاد خروجی شامل کاراکترهای آشفته خواهد بود. در این حالت باید از معادل این تابع یعنی ()mb_substr استفاده کنید.

مشکل اینجاست که باید یادمان باشد در تمام مدت پروژه از توابع *_mb استفاده کنیم. اگر حتی یکبار هم فراموش کنید، احتمال دارد که رشته‌ی یونیکد شما در پردازش‌های بعدی دچار آشفتگی شود.

البته تمام توابع رشته‌ای معادل *_mb ندارند و این از بدشانسی شماست که برای عملکرد مورد نظرتان، این معادل‌ها وجود نداشته باشند.

باید از تابع ()mb_internal_encoding در ابتدای هر اسکریپت PHP (یا اسکریپت سراسری) و از تابع ()mb_http_output درست بعد از اینکه اسکریپت خروجی را به مرورگر می‌فرستد، استفاده کنید. اینکار موجب می‌شود که در آینده از مشکلات بسیاری جلوگیری کنید.

به علاوه، بسیاری از توابع رشته‌ای در PHP یک پارامتر اختیاری دریافت می‌کنند که نحوه‌ی کدگذاری کاراکترها را مشخص می‌کند. اگر این پارامتر را تعریف می‌کنید حتما باید UTF-8 باشد. برای نمونه، ()htmlentities گزینه‌ای برای کدگذاری کاراکتر دارد و شما همیشه باید از UTF-8 برای آن استفاده کنید. توجه کنید که از PHP 5.4.0، کدگذاری پیشفرض کاراکترها برای ()htmlentities و ()htmlspecialchars با استفاده از UTF-8 صورت می‌گیرد.

در نهایت، اگر نرم‌افزار شما در سرورهای مختلفی قرار دارد و اطمینان ندارید که افزونه‌ی mbstring فعال خواهد بود، استفاده از بسته‌ی patchwork/utf8 در Composer را مد نظر قرار دهید. این بسته در صورت فعال بودن mbstring از آن استفاده می‌کند، در غیر اینصورت از توابع عادی رشته‌ای استفاده خواهد کرد.

UTF-8 در MySQL

اگر اسکریپت PHP شما به MySQL دسترسی دارد، احتمال دارد رشته‌های شما به صورت UTF-8 در پایگاه‌داده ذخیره نشوند، هر چند گام‌های بالا را انجام داده باشید.

جهت اطمینان از ذخیره‌سازی رشته‌ها به صورت UTF-8، باید پایگاه‌داده و جدول‌های شما از ساختار utf8mb4 پشتیبانی کنند و در رشته‌ی اتصال PDO نیز از utf8mb4 استفاده کنید. به مثال زیر توجه کنید. این مورد بسیار حایز اهمیت است.

توجه کنید که باید از مجموعه کاراکتر utf8mb4 جهت پشتیبانی کامل از UTF-8 استفاده کنید نه از utf8! به قسمت مطاله‌ی بیشتر مراجعه کنید تا دلیل آن را بدانید.

UTF-8 در مرورگر

از تابع ()mb_http_output استفاده کنید تا اطمینان یابید اسکریپت PHP خروجی را به صورت UTF-8 به مرورگر می‌فرستد.

اینکار باعث می‌شود به مرورگر گفته شود صفحه را با توجه به ساختار UTF-8 نمایش دهد. روش قدیمی برای انجام اینکار استفاده از تگ <meta> به همراه charset بود که در تگ <head> قرار می‌گرفت. این روش هم اکنون نیز معتبر است اما تنظیم این ویژگی در قسمت Content-Type از header بسیار سریع‌تر است.

<?php
// Tell PHP that we're using UTF-8 strings until the end of the script
mb_internal_encoding('UTF-8');
 
// Tell PHP that we'll be outputting UTF-8 to the browser
mb_http_output('UTF-8');
 
// Our UTF-8 test string
$string = 'Êl síla erin lû e-govaned vîn.';
 
// Transform the string in some way with a multibyte function
// Note how we cut the string at a non-Ascii character for demonstration purposes
$string = mb_substr($string, 0, 15);
 
// Connect to a database to store the transformed string
// See the PDO example in this document for more information
// Note the `set names utf8mb4` commmand!
$link = new \PDO(   
                    'mysql:host=your-hostname;dbname=your-db;charset=utf8mb4',
                    'your-username',
                    'your-password',
                    array(
                        \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
                        \PDO::ATTR_PERSISTENT => false
                    )
                );
 
// Store our transformed string as UTF-8 in our database
// Your DB and tables are in the utf8mb4 character set and collation, right?
$handle = $link->prepare('insert into ElvishSentences (Id, Body) values (?, ?)');
$handle->bindValue(1, 1, PDO::PARAM_INT);
$handle->bindValue(2, $string);
$handle->execute();
 
// Retrieve the string we just stored to prove it was stored correctly
$handle = $link->prepare('select * from ElvishSentences where Id = ?');
$handle->bindValue(1, 1, PDO::PARAM_INT);
$handle->execute();
 
// Store the result into an object that we'll output later in our HTML
$result = $handle->fetchAll(\PDO::FETCH_OBJ);

header('Content-Type: text/html; charset=utf-8');
?><!doctype html>
<html>
    <head>
        <title>UTF-8 test page</title>
    </head>
    <body>
        <?php
        foreach($result as $row){
            print($row->Body);  // This should correctly output our transformed UTF-8 string to the browser
        }
        ?>
    </body>
</html>

مطالعه‌ی بیشتر

Back to Top

Dependency Injection

از ویکیپدیا:

Dependency Injection یک الگوی طراحی نرم‌افزار است که اجازه‌ی حذف وابستگی‌هایی را می‌دهد که به صورت دستی در کد وارد شده‌اند، چه در زمان اجرا چه در زمان کامپایل

تعریف بالا درک مفهوم ساده‌ی موجود را بسیار پیچیده می‌کند. Dependency Injection ،وابستگی‌های موجود برای یک شی را از طریق تابع سازنده، فراخوانی متد یا تنظیم ویژگی‌ها انجام می‌دهد، به همین سادگی.

مفهوم پایه

این مفهوم را می‌توان با یک نمونه ساده توضیح داد.

فرض کنید کلاس Database داریم که جهت استفاده از پایگاه‌داده به یک adapter نیاز دارد. adapter را در تابع سازنده نمونه‌سازی می‌کنیم. این کار عملیات آزمایش (test) را دشوار کرده و کلاس Database را به وجود adapter وابسته می‌سازد.

<?php
namespace Database;

class Database
{
    protected $adapter;

    public function __construct()
    {
        $this->adapter = new MySqlAdapter;
    }
}

class MysqlAdapter {}

این کد می‌تواند طوری نوشته شود که این میزان وابستگی را کاهش دهد.

<?php
namespace Database;

class Database
{
    protected $adapter;

    public function __construct(MySqlAdapter $adapter)
    {
        $this->adapter = $adapter;
    }
}

class MysqlAdapter {}

در اینجا برای کلاس Database یک وابستگی تعریف می‌کنیم، به جای آنکه در داخل تابع آن را فراخوانی کنیم. همچنین می‌توانستیم تابع جداگانه‌ای در نظر بگیریم که بر اساس ورودی‌های وابستگی مورد نظر (adapter) عمل کند، یا اگر عملگر adapter$ به صورت public بود می‌توانستیم آن را مستقیم تنظیم کنیم.

مشکل پیچیده

اگر تا به حال درباره‌ی Dependency Injection مطلبی خوانده باشید با عبارت‌هایی مانند “Inversion of Control” یا “Dependency Inversion Principle” مواجه شده‌اید. این‌ها مشکل‌های پیچیده‌ای هستند که Dependency Injection آن‌ها را رفع می‌کند.

Inversion of Control

این عبارت همانطور که از نامش پیداست با جدا نگاه‌داشتن کنترل از تمام شی‌ها، “کنترل را وارونه” می‌سازد. در تعریف Dependency Injection به این معناست که وابستگی‌های موجود را با نمونه‌سازی در قسمت‌های دیگر، ضعیف سازیم.

برای سال‌ها، فریم‌ورک‌های PHP این تکنیک را به کار گرفته‌اند، اگرچه پرسش این است که کدام قسمت کنترل را وارونه می‌سازید و به کجا؟ برای نمونه، فریم‌ورک‌های MVC معمولا یک شی پایه یا کنترل‌کننده‌ی پایه را به وجود می‌آورند که سایر کنترل‌کننده‌ها برای دسترسی به وابستگی‌های آن از این شی پایه ارث‌بری می‌کنند. این همان مفهوم وارونگی کنترل است، اگرچه به جای تضعیف وابستگی‌ها، این روش آن‌ها را منتقل می‌کند.

Dependency Injection به ما کمک می‌کند که این مشکل را با تعریف وابستگی‌هایی که تنها به آن‌ها نیاز داریم، رفع کنیم.

Dependency Inversion Principle

این عبارت همان حرف “D” در مجموعه S.O.L.I.D در رابطه با طراحی شی‌گرا است که بیان می‌کند هر جز از سیستم باید “به انتزاع وابسته باشد، نه به پیاده‌سازی خاص”. ساده‌تر بگوییم، وابستگی‌ها باید Interface یا Abstract Class باشند تا یک پیاده‌سازی خاص. نمونه بالا را می‌توان به سادگی به این مفهوم تبدیل کرد.

<?php
namespace Database;

class Database
{
    protected $adapter;

    public function __construct(AdapterInterface $adapter)
    {
        $this->adapter = $adapter;
    }
}

interface AdapterInterface {}

class MysqlAdapter implements AdapterInterface {}

مزایای بسیاری در این کلاس Database وجود دارد که به یک Interface وابسته است تا به یک پیاده‌سازی خاص.

تصور کنید در تیمی کار می‌کنید که پیاده‌سازی adapter به عهده‌ی عضوی دیگر است. در اولین نمونه، باید منتظر بمانیم تا همکار ما کار روی adapter را تمام کرده سپس ما آزمایش مورد نظر را انجام دهیم. حالا که وابستگی به یک Interface وجود دارد با خیال راحت می‌توانیم به کار خود ادامه دهیم و اطمینان داشته باشیم که ناتمام بودن adapter روی کار ما تاثیر منفی نمی‌گذارد.

مزیت بزرگ دیگری که در این روش وجود دارد این است که کد مقیاس‌پذیری بیشتری دارد. اگر سال بعد تصمیم بگیریم که از یک پایگاه‌داده‌ی دیگر استفاده کنیم تنها کافی است برای آن پایگاه‌داده بر اساس Interface فعلی یک adapter پیاده‌سازی کنیم که از تمام ویژگی‌های فعلی پشتیبانی می‌کند.

ظرف وابستگی

اولین چیزی که باید درباره‌ی ظرف‌های وابستگی بدانید این است که آن‌ها با Dependency Injection تفاوت دارند. یک ظرف وابستگی، ابزاری است که به ما کمک می‌کند Dependency Injection را پیاده‌سازی کنیم، اگرچه از آن‌ها به اشتباه در موارد دیگر (Service Location) استفاده می‌شود که اینکار باعث ایجاد وابستگی‌های بیشتری در نرم‌افزار می‌شود.

اکثر فریم‌ورک‌ها ظرف مربوط به Dependency Injection خود را دارا هستند که به کاربر اجازه می‌دهد درست مانند همان فریم‌ورکی که از آن استفاده می‌کند، نرم‌افزار خود را پیاده‌سازی کند.

مطالعه بیشتر

Back to Top

پایگاه داده

بسیاری از مواقع کد شما از یک پایگاه‌داده استفاده می‌کند تا اطلاعات را ذخیره کند. شما با گزینه‌های مختلفی جهت تعامل با پایگاه‌داده رو‌به‌رو هستید. روش توصیه شده تا نسخه PHP 5.1.0 استفاده از درایورهایی مانند mysqli و pgsql و mssql و … بود.

استفاده از این درایورها بسیار مناسب است به شرط آنکه برنامه‌ی شما تنها با یک پایگاه‌داده سروکار داشته باشد، اگر،‌برای نمونه، به طور همزمان از MySQL و MSSQL استفاده می‌کنید، یا نیاز به برقراری ارتباط با Oracle دارید، آنگاه قادر نخواهید بود از این درایورها استفاده کنید. اینجاست که باید برای هر درایور کد جداگانه‌ای بنویسید — که این کار بیهوده‌ای است.

افزونه‌ی MySQL

افزونه‌ی mysql دیگر توسعه داده نمی‌شود و پایان عمر آن در نسخه PHP 5.5.0 به طور رسمی اعلام شده است، بدین معنی که در نسخه‌های بعدی حذف خواهد شد. اگر در برنامه‌ی خود از تابع‌هایی که با *_mysql شروع می‌شوند استفاده می‌کنید، مانند ()mysql_connect و ()mysql_query، این‌ها در نسخه‌های بعدی PHP قابل استفاده نخواهند بود. این بدان معنی است که باید آن‌ها را با گزینه‌های مناسب‌تری مانند mysqli یا PDO جایگزین کنید و بهتر است که این کار را اکنون انجام دهید تا بعدها مجبور نباشید این تغییرات را با عجله انجام دهید.

اگر از ابتدا نرم‌افزاری را شروع کرده‌اید به طور حتم نباید از افزونه‌ی mysql استفاده کنید: در عوض از افزونه‌ی MySQLi یا PDO استفاده کنید.

افزونه‌ی PDO

PDO یک کتابخانه‌ی انتزاعی جهت برقراری ارتباط با پایگاه‌داده‌های مختلف است — که از نسخه‌ی PHP 5.1.0 قابل دسترس است. برای نمونه، شما می‌توانید از کد یکسانی جهت برقراری ارتباط با MySQL یا SQLite استفاده کنید:

// PDO + MySQL
$pdo = new PDO('mysql:host=example.com;dbname=database', 'user', 'password');
$statement = $pdo->query("SELECT some\_field FROM some\_table");
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo htmlentities($row['some_field']);

// PDO + SQLite
$pdo = new PDO('sqlite:/path/db/foo.sqlite');
$statement = $pdo->query("SELECT some\_field FROM some\_table");
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo htmlentities($row['some_field']);

PDO پرس‌وجوهای SQL را ترجمه نمی‌کند یا ویژگی‌های خاص هر پایگاه‌داده را شبیه‌سازی نمی‌کند; تنها برای اتصال به چند پایگاه‌داده از طریق یک API طراحی شده است.

از همه مهم‌تر، PDO این امکان را می‌دهد تا داده‌های ورودی به نرم‌افزار را با روش‌های امن وارد پایگاه‌داده کنید که اینکار منجر به جلوگیری از حملات SQL Injection می‌گردد.

فرض کنید اسکریپت PHP یک ID از نوع عددی را به عنوان پارامتر می‌پذیرد. از این ID جهت فراخوانی کاربر از پایگاه‌داده استفاده می‌شود. قطعه کد پایین روش اشتباه پیاده‌سازی اینکار است:

<?php
$pdo = new PDO('sqlite:/path/db/users.db');
$pdo->query("SELECT name FROM users WHERE id = " . $_GET['id']); // <-- NO!

اینطور کدنویسی وحشتناک است. شما پارامتری را به طور مستقیم وارد پایگاه‌داده می‌کنید بدون آنکه آن را بررسی کنید. اینکار باعث می‌شود در کسری از ثانیه، مورد حمله قرار بگیرید با استفاده از روشی به نام SQL Injection. فقط تصور کنید فرد مهاجم عبارتی مانند http://domain.com/?id=1%3BDELETE+FROM+users را فراخوانی کند. اینکار متغیر ‍‍GET_$ را با مقدار 1;DELETE FROM users تنظیم می‌کند که باعث می‌شود اطلاعات تمام کاربران شما از بین برود! شما باید با استفاده از انقیاد پارامتر در PDO داده‌ی ورودی را بررسی کنید.

<?php
$pdo = new PDO('sqlite:/path/db/users.db');
$stmt = $pdo->prepare('SELECT name FROM users WHERE id = :id');
$stmt->bindParam(':id', $_GET['id'], PDO::PARAM_INT); // <-- Automatically sanitized by PDO
$stmt->execute();

این کد صحیح است، چرا که با استفاده از انقیاد پارامتر روی عبارت PDO کار می‌کند. اینکار باعث می‌شود داده‌ی ورودی قبل از اینکه وارد پایگاه‌داده شود بررسی شده و احتمال خطر SQL Injection را از بین می‌برد.

باید آگاه باشید که برقراری ارتباط با پایگاه‌داده از منابع سیستم استفاده می‌کند و اگر این ارتباط پایان نیابد، این منابع به صورت خودکار آزاد نمی‌شوند. با استفاده از PDO این اطمینان را دارید که زمان خاتمه‌ی ارتباط، شی مربوط به پایگاه‌داده از بین می‌رود و تمام منابع آن باز می‌گردد. اگر اینکار را به صورت واضح انجام ندهید، PHP به صورت خودکار هنگام خاتمه‌ی اسکریپت ارتباط پایگاه‌داده را قطع می‌کند مگر اینکه ار یک ارتباط پایدار استفاه کرده باشید.

ارتباط با پایگاه‌داده

زمانی که توسعه‌دهندگان شروع به یادگیری PHP می‌کنند، اغلب کد مربوط به بخش پایگاه‌داده را با کد مربوط به بخش نرم‌افزار خود مخلوط می‌کنند، مانند:

<ul>
<?php
foreach ($db->query('SELECT * FROM table') as $row) {
    echo "<li>".$row['field1']." - ".$row['field1']."</li>";
}
</ul>

این روش اشتباهی است بنا به دلایل مختلف، بیشتر به خاطر دشوار بودن عیب‌یابی، آزمایش و خواندن آن، که باعث می‌شود داده‌ی بسیاری به خروجی برود اگر برای آن حد خاصی مشخص نشده باشد.

با توجه به روش‌های دیگری که برای این مساله وجود دارد - مانند برنامه‌نویسی شی‌گرا یا برنامه‌نویسی تابعی - بایستی این فرآیند به صورت جداگانه انجام شود.

ساده‌ترین روش را در نظر بگیرید:

<?php
function getAllSomethings($db) {
    return $db->query('SELECT * FROM table');
}

foreach (getAllFoos() as $row) {
    echo "<li>".$row['field1']." - ".$row['field1']."</li>"; // BAD!!
}

این شروع خوبی است. آن دو مورد را داخل فایل‌های جداگانه قرار دهید تا جدایی بخش‌ها ملموس شود.

با ایجاد یک کلاس که متد شما را در بر می‌گیرد می‌توانید یک “Model” به وجود آورید. یک فایل ساده با پسوند php. جهت قراردادن خروجی خود به وجود آورید تا در اینجا به یک “View” برسید، که تقریبا نزدیک به MVC - یک معماری شی‌گرا برای اکثر فریم‌ورک‌ها است.

foo.php

<?php

$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');

// Make your model available
include 'models/FooModel.php';

// Create an instance
$fooList = new FooModel($db);

// Show the view
include 'views/foo-list.php';

models/FooModel.php

<?php
class Foo()
{
    protected $db;

    public function __construct(PDO $db)
    {
        $this->db = $db;
    }

    public function getAllFoos() {
        return $this->db->query('SELECT * FROM table');
    }
}

views/foo-list.php

<? foreach ($fooList as $row): ?>
    <?= $row['field1'] ?> - <?= $row['field1'] ?>
<? endforeach ?>

این تقریبا مشابه کاری است که تمام فریم‌ورک‌ها انجام می‌دهند البته با کمی تفاوت. شما نیاز ندارید که این گام‌ها را مجدد تکرار کنید، اما زمانی که قصد آزمایش کردن واحدی از نرم‌افزار خود را دارید، قاطی کردن کدهای مختلف با یکدیگر برای شما مشکل‌ساز خواهد شد.

PHPBridge مقاله‌ی فوق‌العاده‌ای دارد با مضمون ایجاد یک کلاس داده‌ای که موضوعی بسیار مشابه به این را پوشش می‌دهد و برای توسعه‌دهندگانی که به تازگی می‌خواهند با پایگاه‌داده کار کنند، بسیار مناسب است.

لایه‌های انتزاعی

بسیاری از فریم‌ورک‌ها لایه‌ی انتزاعی خود جهت برقراری ارتباط با پایگاه‌داده را به وجود می‌آورند که ممکن است بر اساس PDO باشد یا نه. این‌ها اغلب ویژگی‌هایی را که در یک پایگاه‌داده وجود ندارد پیاده‌سازی می‌کنند با قرار دادن پرس‌و‌جو شما در متدهای مختلف PHP، که اینکار امکان برقراری کامل حالت انتزاعی با پایگاه‌داده را فراهم می‌سازد و با عملیات ابتدایی PDO بسیار متفاوت است. اینکار اندکی سربار به وجود می‌آورد اما اگر نرم‌افزار شما نیاز دارد با چندین پایگاه‌داده مختلف ارتباط داشته باشد، این سربار ارزشش را دارد.

برخی از این لایه‌های انتزاعی با استفاده از استانداردهای فضای‌نام‌گذاری PSR-0 یا PSR-4 ساخته شده‌اند و می‌توانند در بسیاری از نرم‌افزارها مورد استفاده قرار بگیرند:

Back to Top

قالب‌ها

قالب‌ها باعث می‌شوند منطق کد شما از قسمت نمایش‌دهنده یا خروجی آن جدا گردد. قالب‌ها بیشتر دربردارنده‌ی HTML نرم‌افزار شما هستند اما می‌توانند ساختارهای دیگری را نیز شامل شوند، مانند XML. قالب‌ها با نام “Views” نیز یاد می‌شوند، دومین بخش الگوی معماری نرم‌افزار MVC.

مزیت‌ها

مزیت اصلی در استفاده از قالب‌ها این است که منطق نرم‌افزار شما از قسمت ظاهری و نمایشی آن جدا می‌شود. قالب‌ها وظیفه‌ی اصلی در نمایش دادن محتوا را دارند. آن‌ها وظیفه‌ی ذخیره‌سازی یا عملیات پیچیده‌ی دیگر روی داده‌ها را ندارند. این موضوع بیشتر در تیم‌های نرم‌افزاری که افراد گوناگون روی قسمت‌های مختلف پروژه کار می‌کنند، تاثیرگذار است، برای نمونه کد سمت سرور (کنترل‌کننده‌ها، مدل‌ها) که توسط توسعه‌دهندگان و کد سمت مرورگر که توسط طراحان نوشته می‌شود.

استفاده از قالب‌ها منجر به بهینه‌شدن کد قسمت ظاهری نرم‌افزار خواهد شد. قالب‌ها معمولا در پوشه‌ی “views” قرار داده می‌شوند، که هر کدام در یک فایل جداگانه قرار دارند. این رویکرد استفاده مجدد از کد را بهینه می‌کند چرا که قسمت‌های بزرگ کد را به بخش‌های کوچک‌تر تبدیل می‌کند. برای نمونه، قسمت header و footer سایت شما می‌تواند توسط قالب تعریف شود، که این قالب‌ها قبل و بعد از قالب اصلی نرم‌افزار قرار می‌گیرند.

در نهایت، بر اساس کتابخانه‌ای که از آن استفاده می‌کنید، قالب‌ها می‌توانند امنیت بیشتری ایجاد کنند چرا که محتوای تولید شده توسط کاربر را به صورت خودکار امن می‌سازند (به عبارت دیگر escape می‌کنند). برخی کتابخانه‌ها محیط‌های امنی را در اختیار طراحان قالب قرار می‌دهند که تنها به بخشی از متغیرها و توابع دسترسی دارند.

قالب‌های خام PHP

این قالب‌ها تنها دربردارنده‌ی کد PHP هستند. از آنجا که PHP خود زبانی است که بر اساس template ساخته شده،‌این قالب‌ها انتخاب پیش‌فرض هستند. این بدان معنی است که به راحتی می‌توانید کد PHP را داخل HTML یا سایر کدها قرار دهید. این مزیت برای توسعه‌دهندگان PHP بسیار کاربردی است چرا که نیاز به یادگرفتن مفاهیم پیچیده‌تر ندارند. به تمام توابع مورد نیاز خود دسترسی دارند و IDE آن‌ها از قابلیت‌های مختلف جهت پشتیبانی از این ساختار حمایت می‌کند. علاوه بر این، این قالب‌ها بسیار سریع هستند چرا که به عملیات کامپایل نیازی ندارند.

هر فریم‌ورک پیشرفته‌ی PHP امروزه از یک ساختار قالب مانند استفاده می‌کند، که اکثر آن‌ها از قالب‌های خام بهره می‌برند. جدا از این فریم‌ورک‌ها، کتابخانه‌هایی مانند Plates یا Aura.View کار با قالب‌های خام را تسهیل می‌کنند با ارایه‌ی عملکردهای پیشرفته‌ای مانند وراثت، ساختارها و قابلیت توسعه‌ی بیشتر.

نمونه‌ای از یک قالب خام PHP (که از کتابخانه‌ی Plates استفاده می‌کند):

<?php $this->insert('header', ['title' => 'User Profile']) ?>

<h1>User Profile</h1>
<p>Hello, <?=$this->escape($name)?></p>

<?php $this->insert('footer') ?>

قالب‌های کامپایل شدنی

درست است که PHP به عنوان یک زبان برنامه‌نویسی شی‌گرا پیشرفت زیادی داشته است اما به عنوان یک زبان که از ساختار templating پشتیبانی می‌کند پیشرفت چندانی نداشته است. قالب‌های کامپایل شدنی مانند Twig یا Smarty این فضای خالی را با ارایه‌ی ساختاری جدید پر می‌کنند، که به طور خاص به این منظور طراحی شده است. قالب‌های کامپایل شدنی آسان‌تر نوشته، تمیزتر خوانده و امن‌تر استفاده می‌شوند چرا که از قابلیت‌هایی مانند بررسی خودکار محتوای کاربر، پشتیبانی از وراثت و ساختار داده‌های مناسب استفاده می‌کنند. این قالب‌ها حتی می‌توانند بین چند زبان برنامه‌نویسی به اشتراک گذاشته شوند که Mustache نمونه‌ای از آن‌ها است. از آن‌جایی که این قالب‌ها کامپایل می‌شوند درصدی مشکل در سرعت به وجود می‌آورند که اگر از ساختار Caching مناسب استفاده شود این مشکل رفع می‌گردد.

نمونه‌ای از یک قالب کامپایل شدنی (که از کتابخانه‌ی Twig استفاده می‌کند):

{% include 'header.html' with {'title': 'User Profile'} %}

<h1>User Profile</h1>
<p>Hello, {{ name }}</p>

{% include 'footer.html' %}

مطالعه‌ی بیشتر

مقاله‌های آموزشی

کتابخانه‌ها

Back to Top

خطا و استثنا

خطا

در زبان‌های برنامه‌نویسی که “خطایابی سنگین” دارند، هر زمان خطایی رخ دهد یک استثنا به وجود می‌آید. البته این روش ماندگاری جهت انجام کارها است اما PHP یک زبان برنامه‌نویسی با “خطایابی سبک” است. اگرچه دارای عملیات خطایابی است و قسمت بزرگی از هسته (Zend Engine) برای کار با شی‌های مختلف از آن بهره می‌برد، اما در بسیاری عملیات دیگر، PHP به ادامه‌ی پردازش برنامه ادامه می‌دهد مگر اینکه یک خطای مهلک رخ داده باشد.

برای نمونه:

$ php -a
php > echo $foo;
Notice: Undefined variable: foo in php shell code on line 1

این خطا از نوع اعلان است و PHP با آن کاری ندارد. این امر ممکن است برای افرادی که با مکانیزم خطایابی سایر زبان‌های برنامه‌نویسی آشنا هستند، گیج‌کننده باشد. برای نمونه، ارجاع به یک متغیر تعریف‌نشده در پایتون منجر به ایجاد یک استثنا می‌شود:

$ python
>>> print foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'foo' is not defined

تنها تفاوت این است که در پایتون کوچکترین خطا منجر به ایجاد یک استثنا می‌شود که اینکار به توسعه‌دهندگان اطمینان خاطر می‌دهد تمام حالت‌های نامطلوب در یک برنامه قابل رسیدگی هستند، اما PHP در برخورد با چنین خطاهایی به کار خود ادامه می‌دهد مگر اینکه آن خطا مهلک باشد که در این نقطه اجرای برنامه متوقف و خطا گزارش می‌شود.

شدت خطا

سطح‌های مختلفی از شدت خطا در PHP وجود دارد که سه سطح خطا، اعلان و هشدار بسیار مرسوم هستند که با استفاده از E_NOTICE، E_ERROR و E_WARNING تعریف شده‌اند. خطاها، در زمان اجرا رخ می‌دهند و مهلک هستند و معمولا منشا در کد اصلی برنامه دارند که منجر به توقف اجرای آن می‌شوند. اعلان‌ها، پیام‌هایی هستند که توجه نکردن به آن‌ها ممکن است منجر به توقف برنامه بشود یا نشود و اجرای برنامه را متوقف نمی‌کنند. هشدارها خطاهایی غیر مهلک هستند که منجر به توقف برنامه نمی‌شوند.

نوع دیگری از این پیام‌ها که در زمان کامپایل رخ می‌دهند، پیام‌های E_STRICT است. این پیام‌ها به شما پیشنهادهایی درباره تغییر کد فعلی می‌دهند تا نرم‌افزار شما با نسخه‌های بعدی PHP سازگاری بیشتری داشته باشد.

تغییر روش گزارش‌دهی خطا در PHP

گزارش‌دهی خطا با استفاده از تنظیمات سراسری PHP یا فراخوانی برخی توابع قابل تغییر است. با استفاده از تابع ()error_reporting می‌توانید سطح خطایی را که در زمان اجرای اسکریپت رخ می‌دهد با استفاده از متغیرهای ثابت، تنظیم کنید. بدین معنی که اگر می‌خواهید تنها خطاها و هشدارها را مشاهده کنید - و نه اعلان‌ها - بدین شکل آن را تنظیم کنید:

error_reporting(E_ERROR | E_WARNING);

همچنین می‌توانید نحوه‌ی نمایش خطا روی نمایشگر (مناسب زمان توسعه)، عدم نمایش آن و ثبت شدن (مناسب زمان اجرا) آن را کنترل کنید. برای اطلاعات بیشتر در این مورد بخش گزارش‌دهی خطا را مشاهده کنید.

جلوگیری از نمایش خطا

با استفاده از عملگر کنترل خطا @ می‌توانید از به وجود آمدن برخی خطاها جلوگیری کنید. با قرار دادن این عملگر در ابتدای عبارت اگر خطایی از آن عبارت به وجود آید، گزارش داده نمی‌شود.

echo @$foo['bar'];

خروجی این دستور در صورت وجود ['bar']foo$ خواهد بود، اما اگر متغیر foo$ یا کلید 'bar' وجود نداشته باشند خروجی null باز می‌گرداند یا چیزی چاپ نمی‌شود. بدون استفاده از عملگر کنترل خطا، این عبارت می‌توانست یک خطای PHP Notice: Undefined variable: foo یا PHP Notice: Undefined index: bar به وجود آورد.

ممکن است ایده‌ی خوبی به نظر بیاید اما ممکن است نتایج نامطلوبی در پی داشته باشد. عبارت‌هایی که شامل عملگر @ هستند سرعت اجرای کمتری نسبت به سایر عبارت‌ها دارند. بهینه‌سازی پیش از موعد (قبل از اجرای نهایی برنامه) از مباحث ریشه‌ای در مناظره‌های برنامه‌نویسی به حساب می‌آید، اما اگر کارایی و قابلیت اجرای بالا برای برنامه‌ی شما مهم است، درک صحیحی از کارایی پایین برنامه با استفاده از عملگر کنترل خطا مورد نیاز شما است.

از طرف دیگر، عملگر کنترل خطا به صورت کامل خطا را محو می‌سازد. خطا نه تنها نمایش داده نمی‌شود بلکه جایی نیز ثبت نمی‌گردد. همچنین در محیط‌های فعال PHP (مانند سرورها)، راهی برای غیرفعال کردن این عملگر وجود ندارد. ممکن است در مرحله‌ی اول خطایی که می‌بینید بدون ضرر باشد، اما همان نیز نمایش داده نمی‌شود و جایی ثبت نمی‌گردد.

اگر راهی برای غیرفعال کردن این عملگر وجود دارد باید از آن بهره گیرید. برای نمونه، کد بالا می‌تواند بدین شکل نوشته شود:

echo isset($foo['bar']) ? $foo['bar'] : '';

یکی از نمونه‌هایی که این عملگر در آن کاربرد دارد تابع ()fopen است که نمی‌تواند فایل مورد نظر را بارگیری کند. قبل از بارگیری فایل می‌توانید وجود یا عدم وجود آن را بررسی کنید، اما اگر فایل بلافاصله پس از بررسی شما پاک شود آنگاه ()fopen مقدار false و یک خطا باز می‌گرداند. البته این مشکلی است که PHP باید حل کند اما جزو مواردی به حساب می‌آید که عملگر کنترل خطا می‌تواند کاربرد داشته باشد.

پیشتر اشاره کردیم که در محیط‌های فعال PHP امکان غیرفعال‌سازی این عملگر وجود ندارد. اگرچه، xDebug یک تنظیم xdebug.stream دارد که این عملگر را غیرفعال می‌سازد. می‌توانید با استفاده از فایل php.ini آن را تنظیم کنید.

xdebug.scream = On

همچنین می‌توانید در زمان اجرا و با استفاده از تابع ini_set آن را تنظیم کنید

ini_set('xdebug.scream', '1')

افزونه‌ی “Scream” برای PHP عملکرد مشابهی مانند xDebug دارد با این تفاوت که نام آن scream.enabled است.

این برای زمانی مفید است که احساس می‌کنید جلوگیری از نمایش خطا، اطلاعات مفیدی را از شما پنهان می‌سازد. از این افزونه با احتیاط و به عنوان یک ابزار کمکی جهت خطایابی استفاه کنید. کدهای فراوانی از کتابخانه‌ی PHP وجود دارند که با خاموش بودن کامل این عملگر کار نخواهند کرد.

ErrorException

برای اینکه PHP به یک زبان برنامه‌نویسی با قابلیت “خطایابی سنگین” تبدیل شود تنها اضافه شدن چند خط کد کافی است. می‌توانید با استفاده از کلاس ErrorException که خود از کلاس Exception مشتق شده است، “خطا”های خود را به عنوان “استثنا” در نظر بگیرید.

این تکنیک متدوالی است که توسط اکثر چارچوب‌های نرم‌افزاری مدرن مانند Symfony یا Laravel پیاده‌سازی شده است. Laravel به صورت پیش‌فرض تمام خطاها را به صورت استثنا با استفاده از بسته‌ی نرم‌افزاری Whoops! نمایش می‌دهد در صورتی که گزینه‌ی app.debug فعال باشد و در صورت غیرفعال بودن آن‌ها را پنهان می‌سازد.

با تبدیل خطاها به استثناها در زمان تولید نرم‌افزار، می‌توانید آن‌ها را بهتر از حالت اولیه‌شان مدیریت کنید و اگر در این زمان به یک استثنا برخورد کردید می‌توانید به راحتی آن را با استفاده از دستور catch بررسی کنید. با بررسی هر استثنا در این زمینه، برنامه‌ی شما به مرور زمان پایدارتر خواهد شد.

اطلاعات بیشتر در مورد ErrorException و نحوه‌ی بررسی خطا در کلاس ErrorException قابل دسترس است.

استثنا

استثناها بخشی استاندارد در اکثر زبان‌های برنامه‌نویسی هستند، اما اغلب در PHP نادیده گرفته می‌شوند. زبان‌هایی مانند روبی که دارای خطایابی سنگین هستند، هر زمان اتفاقی در آن‌ها بیفتد (یک درخواست HTTP ناقص به پایان برسد، پرس و جو از پایگاه داده اشتباه باشد یا حتی یک فایل تصویری پیدا نشود) بلافاصله با ایجاد و نمایش آن خطا شما را مطلع می‌سازند.

اما PHP با اینطور مسائل به روشی سهل‌انگارانه برخورد می‌کند، مانند فراخوانی تابع ()file_get_contents که در صورت پیدا نکردن فایل یک عبارت FALSE و یک هشدار باز می‌گرداند. بسیاری از چارچوب‌های نرم‌افزاری قدیمی‌ PHP مانند CodeIgniter تنها یک مقدار false باز می‌گردانند یا آن را در سیستم داخلی خود ذخیره کرده و در نهایت با استفاده از متدی مانند ()this->upload->get_error$ کاربر را در جریان خطا قرار می‌دهند. مشکل اینجاست برای اینکه درک کنید این متد چه نوع خطایی را گزارش می‌دهد باید در مستندات دنبال آن بگردید به جای اینکه از اسم و روش نامگذاری آن متوجه نوع خطا شوید.

مشکل دیگر با کلاس‌هایی است که به صورت خودکار خطا را در نمایشگر نشان می‌دهند و بلافاصله فرآیند اجرا خاتمه می‌یابد. با اینکار شما توانایی مدیریت خطا توسط سایر توسعه‌دهندگان را نادیده می‌گیرید. استثناها باید ایجاد شوند تا یک توسعه‌دهنده از بروز خطا آگاهی یابد، سپس آن‌ها هستند که تصمیم می‌گیرند چگونه خطا را مدیریت کنند. برای نمونه:

<?php
$email = new Fuel\Email;
$email->subject('My Subject');
$email->body('How the heck are you?');
$email->to('guy@example.com', 'Some Guy');

try
{
    $email->send();
}
catch(Fuel\Email\ValidationFailedException $e)
{
    // The validation failed
}
catch(Fuel\Email\SendingFailedException $e)
{
    // The driver could not send the email
}
finally
{
    // Executed regardless of whether an exception has been thrown, and before normal execution resumes
}

استثناها در کتابخانه‌ی استاندارد PHP

کلاس عمومی Exception زمینه‌ی خطایابی محدودی برای توسعه‌دهنده ایجاد می‌کند. اگرچه، برای غلبه بر این محدودیت، این امکان وجود دارد از کلاس اصلی Execption ارث‌بری کنیم:

<?php
class ValidationException extends Exception {}

این بدان معنی است که می‌توانید حالت‌های مختلفی جهت بررسی خطا در این کلاس تعریف کنید. این کار منجر به تولید بسیاری موارد استثنا خواهد شد، که برخی از آن‌ها به صورت کلی توسط افزونه SPL نادیده گرفته می‌شوند.

برای نمونه اگر از تابع ()call__ استفاده کنید و طی آن یک متد نامعتبر فراخوانی شود به جای اینکه یک استثنا از نوع استاندارد ایجاد شود، می‌توانید به راحتی از استثنایی مانند throw new BadMethodCallException استفاده کنید.

Back to Top

امنیت

امنیت در نرم‌افزار وب

افراد مختلفی وجود دارند که می‌توانند از نرم‌افزار وب شما سواستفاده کنند و این وظیفه‌ی شماست که اقدامات لازم جهت هرچه امن‌تر شدن نرم‌افزار را انجام دهید. خوشبختانه، افراد حاضر در پروژه‌ی امنیت نرم‌افزارهای تحت وب، چارچوبی را به عنوان سند برای پیاده‌سازی روش‌های امنیت اطلاعات در نرم‌افزارهای تحت وب فراهم ساخته‌اند. این سند، برای توسعه‌دهندگانی که به امنیت نرم‌افزار خود اهمیت می‌دهند بسیار مفید است.

ایمن‌سازی گذرواژه

به طور طبیعی، یکی از فرآیندهای موجود نرم‌افزارهای وب مبتنی بر PHP استفاده از نام کاربری و گذرواژه جهت ایجاد حساب کاربری است که این اطلاعات در پایگاه‌داده ذخیره می‌شوند تا برای احراز هویت کاربران مورد استفاده قرار گیرند.

بسیار مهم است که گذرواژه‌ها را قبل از ذخیره‌سازی، hash کنید. این یک عمل بازگشت‌ناپذیر است که گذرواژه‌ی کاربر را به رشته‌ای با طول ثابت تبدیل می‌کند که این رشته قابل بازگشت به گذرواژه‌ی اولیه نباشد. این بدان معناست که می‌توانید دو مقدار را با یکدیگر بررسی کنید تا مشخص شود آیا از یک گذرواژه‌ی یکسان تولید شده‌اند یا خیر در حالی که نمی‌توانید رشته‌ی اولیه (گذرواژه‌) را تشخیص دهید. اگر این اقدام مهم را انجام ندهید و پایگاه‌داده‌ی شما در اختیار شخص دیگری قرار گیرد آنگاه اطلاعات ورود کاربران شما فاش خواهد شد. در نظر داشته باشید برخی کاربران از یک گذرواژه‌ (متاسفانه) برای سرویس‌های دیگر نیز استفاده می‌کنند. به همین خاطر، مهم است که این مسایل را جدی بگیرید.

کاربرد تابع password_hash

این تابع در 5.5 PHP معرفی شد و در حال حاضر از الگوریتم BCrypt، که قوی‌ترین الگوریتم موجود در PHP است، استفاده می‌کند. در صورت نیاز به الگوریتم‌های قوی‌تر، در آینده بروزرسانی خواهد شد. همچنین کتابخانه‌ی password_compat برای نسخه‌های قدیمی‌تر مانند 5.3.7 به بالا، به وجود آمده است.

در ادامه، با استفاده از این تابع یک رشته را hash کرده و با یک رشته‌ی دیگر مقایسه می‌کنیم. از آنجایی که دو رشته‌ی ورودی متفاوت هستند، عملیات ورود ناموفق خواهد بود.

<?php
                      
require 'password.php';

$passwordHash = password_hash('secret-password', PASSWORD_DEFAULT);

if (password_verify('bad-password', $passwordHash)) {
    // Correct Password
} else {
    // Wrong password
}

بررسی داده‌ی ورودی

هیچگاه و به هیچ عنوان به داده‌ی ورودی از طرف کاربر اطمینان نکنید. قبل از اینکه داده را در کد مورد استفاده قرار دهید، همیشه آن را بررسی و کنترل کنید. با استفاده از توابع filter_var و filter_input می‌توانید از صحت داده‌ی ورودی اطمینان حاصل کنید (مانند ایمیل و …).

داده‌ی ورودی شامل طیف گسترده‌ای است: متغیرهای GET_$ و POST_$ از طریق فرم، برخی مقادیر درون متغیر SERVER_$ و حتی درخواست HTTP با استفاده از fopen('php://input', 'r'). به یاد داشته باشید که داده‌ی ورودی تنها از طریق فرم‌هایی که کاربران پر می‌کنند به دست نمی‌آید و مواردی مانند دانلود و آپلود فایل، مقدارهای موجود در session، داده cookie و داده‌ی مربوط به سرویس‌های دیگر، همگی از این طیف گسترده هستند.

هرچند داده‌ی ورودی قابل ذخیره‌سازی، ترکیب و دسترسی در زمان دیگر است، کماکان داده‌ی ناامن به حساب می‌آید. هر زمان که قصد پردازش، خروجی‌گرفتن، الحاق کردن یا استفاده از آن را در کد داشتید از خود بپرسید آیا می‌توان به این داده اطمینان کرد یا خیر.

هر نوع داده‌ای با توجه به کاربردش می‌تواند به یک شکل فیلتر شود. برای نمونه، زمانی که داده‌ی ورودی بدون بررسی و کنترل به صورت مستقیم در ساختار HTML قرار می‌گیرد این تهدید وجود دارد که عملیات غیرمجازی را توسط JavaScript روی وبسایت شما انجام دهد! این نوع آسیب‌پذیری، Cross-Site Scripting یا XSS نامیده می‌شود که یکی از خطرناکترین حملات متداول است. یک روش برای جلوگیری از این حمله، بررسی و کنترل داده‌ی ورودی کاربر قبل از قرار گرفتن در ساختار نهایی صفحه است که می‌تواند با استفاده از تابع strip_tags صورت پذیرد. برای نادیده گرفتن برخی کاراکترهای خاص توابعی مانند htmlentities و htmlspecialchars مورد استفاده قرار می‌گیرند.

نمونه‌ی دیگر استفاده از داده‌ی ورودی جهت اجرا در محیط خط فرمان است. این کار بسیار خطرناک (و در عین حال اصلا توصیه نمی‌شود) است اما می‌توان از تابع escapeshellarg برای بررسی و کنترل داده‌ی ارسالی استفاده کرد.

به عنوان نمونه‌ی آخر به دریافت فایل توسط کاربر از روی سرور اشاره می‌کنیم. این کار می‌تواند با تغییر نام فایل به مسیر فایل صورت بگیرد که در صورت بررسی نکردن داده‌ی ورودی، اطلاعات مهم سرور در اختیار دیگران قرار می‌گیرد. برای جلوگیری از این امر باید کاراکترهای “/”، “/..”، و null bytes یا سایر کاراکترها را حذف کرد تا منجر به نمایش مکان‌های مخفی در سرور نشوند.

پاکسازی داده‌ی ورودی

این فرآیند، با حذف یا نادیده‌گرفتن برخی کاراکترهای ناامن از داده‌ی ورودی، صورت می‌گیرد.

برای نمونه، قبل از قرار دادن داده‌ی ورودی در خروجی نهایی یا درج آن در پایگاه‌داده باید آن را از کاراکترهای غیرمجاز پاکسازی کنید. عمل تخصیص پارامتر به یک پرس‌وجو توسط PDO اینکار را برای شما انجام می‌دهد.

گاهی اوقات لازم است به برخی تگ‌های امن HTML اجازه‌ی قرارگیری در صفحه داده شود. مدیریت این فرآیند گاهی بسیار دشوار می‌شود تا جایی که برخی ترجیح می‌دهند از پیش‌پردازنده‌هایی مانند Markdown یا BBCode استفاده کنند و کتابخانه‌هایی مانند HTML Purifier به همین منظور وجود دارند.

مشاهده‌ی فیلترهای به کار رفته در پاکسازی داده‌ی ورودی

اعتبارسنجی

این فرآیند به شما کمک می‌کند از صحت اطلاعات ورودی اطمینان حاصل کنید. برای نمونه، هنگام پردازش یک فرم ثبت‌نام، شاید بخواهید ایمیل، شماره تلفن یا سن فرد را بررسی و کنترل کنید.

مشاهده‌ی فیلترهای به کار رفته در اعتبارسنجی داده‌ی ورودی

فایل‌های پیکربندی

هنگام به وجود آوردن فایل‌های پیکربندی برای نرم‌افزار خود بهتر است به برخی اصول بنیادی پایبند باشید:

استفاده از متغیرهای سراسری

تذکر: از نسخه‌ی PHP 5.4.0 به بالا پیکربندی register_globals حذف و غیرقابل استفاده است و در فرآیند برورزسانی یک نرم‌افزار قدیمی به صورت یک اخطار نمایش داده می‌شود.

زمانی که این پیکربندی فعال باشد، منجر به در دسترس بودن تمام متغیرهای سراسری (مانند GET_$، POST_$، و REQUEST_$) در تمام حوزه‌های نرم‌افزار شما خواهد بود که این امر به مشکلات امنیتی بسیار دامن می‌زند و هیچ روشی وجود ندارد که بتوان تعیین کرد داده‌ی ورودی از کدام قسمت وارد نرم‌افزار شده است.

برای نمونه: متغیر $_GET['foo'] با استفاده از foo$ نیز قابل دسترسی است، که ممکن است منجر به تعریف متغیرهای نامشخص گردد. اگر از PHP 5.4.0 به پایین استفاده می‌کنید اطمینان حاصل کنید که register_globals غیرفعال باشد.

گزارش خطا

ثبت و گزارش خطا روشی مناسب جهت عیب‌یابی نرم‌افزار است اما در صورتی که اقدامات لازم جهت محرمانه بودن این خطاها صورت نگیرد می‌تواند منجر به فاش شدن ساختار نرم‌افزار شما گردد. برای اینکه این مشکل به وجود نیاید باید تنظیمات متفاوتی در محیط توسعه در مقایسه با محیط نهایی نرم‌افزار داشته باشید.

محیط توسعه

جهت نمایش تمام خطاهای موجود در محیط توسعه، تنظیمات زیر را در فایل php.ini انجام دهید:

display_errors = On
display_startup_errors = On
error_reporting = -1
log_errors = On

استفاده از 1- تمام خطاهای موجود را نمایش می‌دهد، حتی آن‌هایی که در نسخه‌های بعدی PHP به وجود بیایند. ثابت E_ALL رفتاری مشابه به این عملکرد را در نسخه‌ی PHP 5.4 دارد. - php.net

سطح خطا E_STRICT در نسخه‌ی 5.3.0 معرفی شد و قسمتی از E_ALL نیست، اگرچه در نسخه‌ی 5.4.0 به قسمتی از E_ALL تبدیل شد. این به چه معناست؟ در نسخه‌ی 5.3 اگر بخواهید تمام خطاهای موجود را ببینید باید از 1- یا E_ALL | E_STRICT استفاه کنید.

گزارش خطا با توجه به نسخه‌های مختلف PHP

محیط نهایی

جهت پنهان‌سازی تمام خطاهای موجود در محیط نهایی، تنظیمات زیر را در فایل php.ini انجام دهید:

display_errors = Off
display_startup_errors = Off
error_reporting = E_ALL
log_errors = On

با استفاده از این تنظیمات، خطاها کماکان در سرور ثبت می‌شوند اما به کاربر نمایش داده نمی‌شوند. برای اطلاعات بیشتر درباره‌ی این تنظیمات، راهنمای رسمی PHP را مشاهده کنید:

Back to Top

آزمون

نوشتن آزمون‌های خودکار برای کد PHP یک عادت خوب محسوب می‌شود که منجر به تولید برنامه‌های خوش‌ساخت می‌گردد. آزمون‌های خودکار ابزارهای قدرتمندی هستند که زمان تغییر در برنامه اطمینان حاصل کنید چیزی به هم نمی‌ریزد یا در زمان اضافه‌کردن امکانات جدید، بخش‌های قبلی به کار خود ادامه می‌دهند.

ابزارها یا چارچوب‌های مختلفی در این زمینه برای PHP وجود دارد که هر یک رویکرد متفاوتی پیش گرفته‌اند - ولی همه‌ی آن‌ها سعی دارند جلوی آزمون‌های دستی را گرفته و نیاز گروه‌هایی که مرتبط با تضمین کیفیت نرم‌افزار هستند را برآورده سازند، مهم‌تر اینکه تغییرات جدید عملکرد فعلی نرم‌افزار را مختل نسازند.

توسعه مبتنی بر آزمون

از ویکیپدیا:

توسعه مبتنی بر آزمون یا TDD یک فرآیند توسعه‌ی نرم‌افزار است که از چرخه‌های بسیار کوتاه تشکیل شده است: توسعه‌دهنده نخست یک آزمون خودکار که منجر به شکست شود را طراحی کرده و بر اساس کاری که آن آزمون باید انجام دهد کد واقعی را می‌نویسد و در نهایت کد نوشته شده را بهبود می‌بخشد.Kent Beck ، کسی که توسعه یا ‘بازآفرینی’ این تکنیک منسوب به اوست در سال ۲۰۰۳ اعلام کرده است TDD مشوق طراحی‌های ساده و الهام‌بخش، اعتماد است

انواع مختلفی از آزمون‌نویسی وجود دارد که می‌توان از آن‌ها در برنامه‌های خود استفاده کرد.

آزمون‌نویسی واحد

این سبک برنامه‌نویسی روشی است جهت اطمینان از اینکه تمام توابع، کلاس‌ها و متدها در طول چرخه‌ی نرم‌افزار همانگونه که مد نظر است کار کنند. با بررسی داده‌های ورودی و خروجی به/از توابع و متدها، می‌توان از منطق داخلی نرم‌افزار اطمینان حاصل کرد. با استفاده از Dependency Injection و نمونه‌سازی از کلاس‌ها می‌توان استفاده‌ی صحیح از وابستگی‌های موجود در نرم‌افزار را مورد بررسی قرار داد.

زمانی که یک کلاس یا تابع به وجود می‌آورید باید برای هر عملکردی که از آن مد نظر است نیز یک آزمون بنویسید. به عنوان اولین گام، باید اطمینان حاصل کنید هنگام دریافت ورودی اشتباه، خطا و هنگام دریافت ورودی صحیح، خروجی باز می‌گردد. این تکنیک به شما کمک می‌کند هر زمان تغییری در این کلاس یا تابع به وجود بیاورید عملکرد سابق آن به قوت خود باقی است. تنها جایگزین این روش استفاده از تابع ()var_dump در فایل test.php است، که در عمل روش درستی برای تولید نرم‌افزار نیست - چه آن نرم‌افزار کوچک باشد چه بزرگ.

کاربرد دیگر این سبک آزمون‌نویسی مشارکت در پروژه‌های آزاد است. اگر می‌توانید آزمونی بنویسید که نواقص بخشی از یک نرم‌افزار را مشخص کند، پس بهتر است آن را بر طرف کرده و آزمون دیگری بنویسید که نشان دهد مشکل رفع شده است چرا که تولید وصله، بیشتر مورد استقبال قرار می‌گیرد. اگر پروژه‌ای دارید که به صورت عمومی درخواست دیگران را جهت مشارکت می‌پذیرد باید این عملکرد را به عنوان یک پیشنیاز مطرح کنید.

PHPUnit مهم‌ترین چارچوب استاندارد آزمون‌نویسی در PHP است، اما راه حل‌های دیگری نیز وجود دارند:

آزمون‌نویسی یکپارچه

از ویکیپدیا:

آزمون‌نویسی یکپارچه (که یکپارچگی یا آزمون‌نویسی نیز خوانده می‌شود، به طور مخفف “I&T”) مرحله‌ای از آزمون نرم‌افزار است که قسمت‌های مختلف را با در کنار هم قرار دادن، بررسی می‌کند. معمولا پس از آزمون‌نویسی واحد و قبل از آزمون‌نویسی اعتبارسنجی صورت می‌گیرد. این روش، ورودی خود را یک افزونه از نرم‌افزار قرار می‌دهد، آن‌ها را گروه‌بندی می‌کند و روی گروه تشکیل شده آزمون‌های مورد نظر را اعمال می‌کند.

بسیاری از ابزارهای مورد استفاده در آزمون‌نویسی واحد، در این سبک نیز کاربرد دارند و بسیاری از قوانین آن‌ها نیز اینجا صادق است.

آزمون‌نویسی کاربردی

این سبک از آزمون‌نویسی از مجموعه ابزاری تشکیل شده است که در عمل نرم‌افزار نهایی را مورد آزمون قرار می‌دهند نه تنها بخش‌های کوچکی از آن را. این ابزارها معمولا با ایجاد داده‌های واقعی و شبیه‌سازی محیط حقیقی نرم‌افزار، به این کار می‌پردازند.

ابزارهای مورد استفاده در آزمون‌نوسی کاربردی

توسعه مبتنی بر رفتار

دو نوع مختلف از توسعه‌ی مبتنی بر رفتار (BDD) وجود دارد: SpecBDD و StoryBDD . تمرکز SpecBDD بر جنبه‌ی فنی کد است، در حالی که تمرکز StoryBDD بر جنبه‌ی منطق یا ویژگی‌های بارز کد است. PHP برای هر کدام راه حلی دارد.

با StoryBDD ، شما داستان‌هایی می‌نویسید که عملکرد نرم‌افزار را مشخص می‌کنند. این داستان‌ها می‌توانند به عنوان آزمون حقیقی در نرم‌افزار اجرا شوند. چارچوبی که در PHP از آن برای StoryBDD استفاده می‌شود Behat نام دارد، که از پروژه‌ی Cucumber مربوط به روبی الهام گرفته شده است و زبان Gherkin را پیاده‌سازی می‌کند.

با SpecBDD ، شما استانداردی تعیین می‌کند که چگونه کد شما باید عمل کند، جدای اینکه چه کاری انجام می‌دهد. بجای آزمون یک تابع یا متد، شما توضیح می‌دهید که آن تابع یا متد چگونه کار می‌کند. چارچوبی که PHP از آن برای SpecBDD استفاه می‌کند، PHPSpec نام دارد که از پروژه‌ی RSpec project مربوط به روبی الهام گرفته شده است.

پیوندهای مفید

ابزار مکمل برای آزمون‌نویسی

علاوه بر چارچوب‌های معرفی شده، ابزارهای دیگری نیز برای آزمون‌نویسی وجود دارد که در ادامه به آن‌ها اشاره می‌کنیم.

پیوند به ابزارها

Back to Top

سرورها و توسعه‌ی آن‌ها

برنامه‌های PHP به روش‌های متفاوتی روی سرورهای حقیقی می‌توانند اجرا شوند یا توسعه یابند.

Platform as a Service یا (PaaS)

بستر PaaS معماری سیستم و شبکه‌ی مورد نیاز جهت اجرای برنامه‌های PHP را فراهم می‌کند. این بدان معناست که تغییرات ناچیزی جهت اجرای برنامه‌های PHP یا چارچوب‌های نرم‌افزاری PHP در این بستر، مورد نیاز است.

اخیرا بستر PaaS به روشی متداول جهت توسعه، میزبانی و مقیاس‌پذیری برنامه‌های PHP در ابعاد مختلف تبدیل شده است. شما می‌توانید فهرستی از فراهم‌آورندگان بستر PaaS برای PHP را در قسمت منابع مشاهده کنید.

سرورهای مجازی یا اختصاصی

اگر با مدیریت سیستم آشنا هستید یا قصد یادگیری آن را دارید، سرورهای مجازی یا اختصاصی قدرت کامل در اختیار گرفتن محیط اجرای برنامه‌ها را، به شما می‌دهند.

nginx و PHP-FPM

ماژول قدرتمندی در PHP وجود دارد با نام مدیر فرآیند FastCGI یا FPM و قابلیت انطباق بالایی با nginx دارد که وب‌سروری است سبک و با قابلیت اجرایی بسیار بالا. نسبت به آپاچی از حافظه‌ی کمتری استفاده می‌کند و بهتر می‌تواند درخواست‌های همزمان را مدیریت کند. این امر درباره‌ی سرورهای مجازی که از حافظه‌ی کمتری استفاده می‌کنند اهمیت بسیار زیادی دارد.

Apache و PHP

تاریخچه‌ی طولانی بین PHP و آپاچی وجود دارد. آپاچی قابلیت تنظیم بالایی دارد و برای اینکار از ماژول‌های بسیاری بهره می‌گیرد. در بین سرورهای اشتراکی بسیار محبوب است و به سادگی می‌توان روی آن بسیاری از چارچوب‌های نرم‌افزاری PHP و برنامه‌های اُپن‌سورس مانند دروپال و وُردپِرس را راه‌اندازی کرد. متاسفانه‌، آپاچی از منابع بیشتری نسبت به nginx استفاده می‌کند به خوبی آن نمی‌تواند بازدیدکنندگان همزمان با تعداد بالا را مدیریت کند.

آپاچی پیکربندی‌های متفاوتی جهت اجرای PHP دارد. معمول‌ترین آن‌ها برای راه‌اندازی prefork MPM با استفاده از ماژول mod_php5 است. با اینکه بهینه‌ترین روش جهت مدیریت حافظه نیست اما ساده‌ترین آن‌ها برای استفاده است. اگر قصد ندارید به جنبه‌های مختلف مدیریت سیستم بپردازید، این روش مناسب شماست. به یاد داشته باشید استفاده از ماژول mod_php5 مستلزم استفاده از prefork MPM است.

از طرف دیگر، اگر قصد بهره‌گیری از قدرت اجرای بالاتر و پایدارتر شدن آپاچی را دارید می‌توانید از همان سیستم FPM موجود در nginx که در آپاچی با ماژول‌های worker MPM یا event MPM و با استفاده از mod_fastcgi یا mod_fcgid پیاده‌سازی شده است، استفاده کنید. این پیکربندی مصرف حافظه را بهبود بخشیده و سرعت بالایی به همراه می‌آورد اما زمان بیشتری جهت پیکربندی خواهد برد.

سرورهای اشتراکی

سرورهای اشتراکی بسیاری، برای اجرای PHP به خاطر محبوبیت آن وجود دارند. به ندرت می‌توان سرویس میزبانی پیدا کرد که از PHP پشتیبانی نکند، اما باید توجه کرد از نسخه‌ی پایدار آن بهره گیرد. سرورهای اشتراکی به شما و سایر توسعه‌دهندگان اجازه می‌دهند وب‌سایت‌های خود را روی یک و تنها یک ماشین مجزا راه‌اندازی کنید. این سرورها باعث شده‌اند تجارت‌های بسیاری به سمت نرم‌افزارهای تحت وب کشیده شوند چرا که هزینه‌ی پایینی برایشان به همراه دارد. از طرفی شما هیچگاه متوجه نمی‌شوید همسایه‌تان (فردی که از همان سرور اشتراکی استفاده می‌کند و به همان منابع دسترسی دارد) قصد انجام چه کاری دارد. بار اضافه روی سرور گذاشتن و ایجاد حفره‌های امنیتی، مهمترین دغدغه‌‌های این نوع سرورها هستند. اگر بودجه‌ی پروژه‌ی شما این اجازه را می‌دهد که از سرورهای بهتر استفاده کنید، پس حتما این کار را بکنید.

ایجاد و راه‌اندازی نرم‌افزار خود

اگر تغییرات مربوط به پایگاه‌داده را دستی انجام می‌دهید یا آزمون‌های نوشته شده را به صورت دستی اجرا می‌کنید، بهتر است دوباره بیندیشید! با انجام هر کار به صورت دستی در هر نسخه‌ از نرم‌افزار خود احتمال بروز خطای مهلک افزایش می‌یابد. خواه تغییر کوچکی اعمال کنید یا با یک فرآیند ساخت پیچیده روبه‌رو باشید، خودکارسازی فرآیند تولید به کمک شما می‌آید.

از میان کارهایی که قصد خودکارسازی آن‌ها را دارید می‌توان به موارد زیر اشاره کرد:

ابزارهای خودکارسازی فرآیند تولید

این ابزارها معمولا از تعدادی اسکریپت تشکیل شده‌اند که فرآیند توسعه‌ی نرم‌افزار را آسان می‌کنند. ابزار تولید، بخشی از نرم‌افزار شما نیست، بلکه از بیرون آن را مدیریت می‌کند.

ابزارهای اُپِن سورس بسیاری در این رابطه وجود دارند، که برخی از آن‌ها نیز با PHP نوشته شده‌اند. این نباید منجر به استفاده نکردن از آن‌ها شود، اگر برای کار خاصی مورد نیاز باشند. چند نمونه عبارتند از:

Phing متداول‌ترین ابزار مورد استفاده در خودکارسازی فرآیند تولید است که در دنیای PHP بسیار مورد استفاده قرار می‌گیرد. با استفاده از Phing شما می‌توانید کنترل بسته‌بندی، راه‌اندازی و اجرای آزمون‌ها را تنها از یک فایل XML مدیریت کنید. این ابزار (که مبتنی بر Apache Ant است) فعالیت‌های بسیاری را جهت نصب و بروزرسانی نرم‌افزار تحت وب فراهم می‌آورد و امکان توسعه‌پذیری بالایی دارد، که می‌توان با استفاده از خود PHP اینکار را انجام داد.

Capistrano یک سیستم متوسط-به-بالا برای برنامه‌نویسان است که اجازه‌ی اجرای فرما‌ن‌های مختلف را به روشی ساخت‌یافته، روی یک یا چند ماشین می‌دهد. اگرچه به منظور توسعه‌ی برنامه‌های Ruby on Rails ایجاد شده است اما بسیاری موفق شده‌اند PHP را روی آن توسعه دهند. استفاده کاربردی از Capistrano مستلزم داشتن دانش کافی درباره‌ی Ruby on Rails است.

برای توسعه‌دهندگانی که قصد استفاده از Capistrano روی نرم‌افزار PHP خود را دارند، نوشته‌ی Dave Gardner با عنوان توسعه‌ی PHP با Capistrano نقطه‌ی آغاز مناسبی است.

Chef بیش از یک چارچوب راه‌اندازی کاربرد دارد، یک سیستم بسیار قدرتمند براساس Ruby است که نه تنها برای توسعه‌ی نرم‌افزار کاربرد دارد بلکه زیرساخت اولیه یک یا چند سرور را می‌تواند پیاده‌سازی کند.

منابع Chef برای توسعه‌دهندگان PHP:

مطالعه‌ی بیشتر:

Continuous Integration

یک فرآیند توسعه‌ی نرم‌افزار است که طی آن اعضای یک تیم کار روزانه‌ی خود را با سایر اعضا یکپارچه می‌سازند، که ممکن است این عمل چند مرتبه در روز صورت گیرد. بسیاری از تیم‌ها به این نتیجه رسیده‌اند که این عمل منجر به یکپارچگی بیشتری در محصول نهایی خواهد شد و به تیم این اجازه را می‌دهد که در زمان کوتاه‌تری فرآیند توسعه را سپری کنند.

– Martin Fowler

روش‌های مختلفی جهت پیاده‌سازی این فرآیند در PHP وجود دارد. اخیرا Travis CI موفق شده است این تکنیک را در بسیاری از پروژه‌ها پیاده‌سازی کند، حتی پروژه‌های کوچک. Travis CI یک سرویس آنلاین است که در اختیار جامعه‌ی اِپِن سورس قرار دارد. این ابزار با GitHub یکپارچه شده است و پشتیبانی خوبی از زبان‌های برنامه‌نویسی موجود، از جمله PHP دارد.

مطالعه‌ی بیشتر:

Back to Top

ذخیره‌سازی موقت

به صورت پیش فرض PHP زبان سریعی است اما ممکن است گاهی اوقات گلوگاه‌هایی ایجاد شود که منجر به کند شدن نرم‌افزار گردند مانند اتصال به سرورهای دیگر، بارگیری فایل و موارد دیگر. خوشبختانه، ابزارهای مختلفی وجود دارند که می‌توانند به قسمتی از نرم‌افزار شما سرعت بخشند یا باعث پیشگیری از تعداد دفعاتی شوند که عملیات زمان‌بر نام برده، کل نرم‌افزار را تحت تاثیر قرار می‌دهند.

ذخیره‌سازی Bytecode

زمانی که یک فایل PHP اجرا می‌شود، در پشت صحنه ابتدا به یک فایل bytecode یا opcode کامپایل شده، سپس این فایل bytecode اجرا می‌شود. اگر فایل PHP تغییر نکند، خروجی bytecode همیشه ثابت خواهد بود. این بدان معناست که عملیات کامپایل در این صورت فقط منابع پردازنده را هدر می‌دهد.

این دقیقا جایی است که ذخیره‌سازی Bytecode به میان می‌آید. این عمل منجر به نگهداری فایل bytecode در حافظه شده و از کامپایل مجدد و بیهوده‌ی آن جلوگیری می‌کند. پیاده‌سازی این نوع ذخیره‌سازی تنها چند دقیقه زمان می‌برد و بعد از آن متوجه افزایش سرعت نرم‌افزار خواهید شد. حقیقتا دلیلی وجود ندارد که از آن استفاده نکنیم.

با انتشار PHP 5.5، یک ذخیره‌ساز درونی به نام OPcache وجود دارد. البته برای نسخه‌های قبل از آن نیز موجود بود.

سایر ذخیره‌سازهای Bytecode عبارتند از:

ذخیره‌سازی Object

شرایطی وجود دارد که طی آن نیاز باشد یک شی منحصربه‌فرد را به صورت جداگانه در حافظه ذخیره کنیم، مانند حالتی که فراخوانی از پایگاه‌داده بسیار پرهزینه و خروجی آن نیز تغییر چندانی نداشته باشد. شما می‌توانید از نرم‌افزارهایی که به این منظور طراحی شده‌اند جهت ذخیره‌سازی یک شی خاص در حافظه برای دسترسی‌های سریع‌تر در آینده استفاده کنید. اگر این گزینه‌ها را در یک انبار داده ذخیره کنید، سپس طی درخواست‌های بعد آن‌ها را از حافظه فراخوانی کنید، مقدار قابل توجهی به سرعت نرم‌افزار شما اضافه خواهد شد و بار اضافی نیز به سمت پایگاه‌داده روانه نمی‌شود.

بسیاری از راه‌حل‌های مبتنی بر ذخیره‌سازی bytecode اجازه‌ی ذخیره‌سازی داده‌های سفارشی را نیز می‌دهند، پس دلایل بیشتری برای استفاده کردن از آن‌ها وجود دارد. از جمله ابزارهایی که با ارایه‌ی رابط برنامه‌نویسی اجازه‌ی اینکار را به شما می‌دهند عبارتند از APCu و XCache و WinCache.

متداول‌ترین ابزارهای مورد استفاده در این زمینه عبارتند از APCu و memcached. برای ذخیره‌سازی شی، APCu ابزار فوق‌العاده‌ای است که با یک رابط برنامه‌نویسی ساده اجازه می‌دهد داده‌ی سفارشی خود را در آن ذخیره کنید. یکی از محدودیت‌های APCu این است که وابسته به سروری است که روی آن نصب و راه‌اندازی شده است. از طرف دیگر، Memcached روی سرویس جداگانه‌ای قابل نصب است که از طریق شبکه می‌توان به آن رسید. به این معنا که شما می‌توانید داده‌های خود را در یک محیط مرکزی ذخیره‌سازی کنید و سایر سرورها از این محیط جهت فراخوانی داده استفاده کنند.

به یاد داشته باشید زمانی که PHP به عنوان یک نرم‌افزار FastCGI در وب‌سرور اجرا می‌شود، هر فرآیند آن حافظه‌ی مربوط به خود را دارد. به همین دلیل داده‌های APCu قابلیت اشتراک‌گذاری بین چند فرآیند را ندارند. در اینگونه شرایط شاید بخواهید از memcached استفاده کنید، که وابسته به فرآیند‌های PHP نیست.

در یک پیکربندی مبتنی بر شبکه، APCu بهتر از memcached عمل می‌کند، اما memcached قابلیت بهتری برای مقیاس‌پذیری و افزایش سرعت دارد. اگر نرم‌افزار شما در چند سرور مختلف اجرا نمی‌شود یا به قابلیت‌های اضافه‌ی memcached نیاز ندارد، در این صورت APCu گزینه‌ی مناسبی برای شماست.

نمونه‌ای از کاربرد APCu:

<?php
// check if there is data saved as 'expensive_data' in cache
$data = apc_fetch('expensive_data');
if ($data === false) {
    // data is not in cache; save result of expensive call for later use
    apc_add('expensive_data', $data = get_expensive_data());
}

print_r($data);

نکته اینکه تا قبل از PHP 5.5، نرم‌افزار APC هر دو ذخیره‌سازی object و bytecode را ارایه می‌داد. بنابراین APCu به پروژه‌ای تبدیل شد که ذخیره‌سازی object از APC را برای PHP 5.5 به بالا به ارمغان آورد، چرا که PHP به صورت پیش‌فرض یک ذخیره‌ساز bytecode به نام OPcache دارد.

درباره‌ی سیستم‌‌های محبوب ذخیره‌سازی شی بیشتر بدانید:

Back to Top

منابع

مستندات رسمی

چه کسانی را دنبال کنم؟

آموزش دادن

فراهم‌آورندگان بستر PaaS برای PHP

چارچوب‌های نرم‌افزاری

بسیاری از توسعه‌دهندگان PHP به جای اینکه تمام کار را از ابتدا خود انجام دهند، از چارچوب‌های نرم‌افزاری یا فِریم‌وُرک موجود استفاده می‌کنند. این ابزارها بسیاری از پیچیدگی‌های سطح پایین را از بین برده و با در اختیار گذاشتن رابط‌های برنامه‌نویسی گوناگون، طیف گسترده‌ای از مشکلات را حل می‌کنند.

برای هر پروژه‌ای هم نیاز به استفاده از این چارچوب‌ها وجود ندارد. گاهی اوقات کدنویسی اولیه مشکل را حل می‌کند، اما اگر به یک چارچوب نرم‌افزاری نیاز داشتید بدانید که از سه خانواده‌ی مختلف تشکیل شده‌اند:

چارچوب‌های نرم‌افزاری کوچک حقیقتا یک دربرگیرنده یا wrapper هستند که درخواست‌های HTTP را به کنترل‌کننده‌ها و متدهای خاصی ارجاع می‌دهند و گاهی اوقات ممکن است این فرآیند را در سمت پایگاه‌داده نیز انجام دهند. از آن‌ها بیشتر برای ایجاد سرویس‌های مبتنی بر HTTP استفاده می‌شود.

بسیاری از چارچوب‌های نرم‌افزاری دیگر امکانات بیشتری را به دسته‌ی اول اضافه می‌کنند که به آن‌ها تمام عیار یا Full Stack اطلاق می‌شود. قابلیت‌هایی مانند ORMs، بسته‌های احراز هویت و موارد دیگر.

دسته‌ی سوم از مجموعه کتابخانه‌هایی برای اهداف خاص منظوره تشکیل شده است. با ترکیب این چارچوب‌ها با یکدیگر می‌توان به دو دسته‌ی قبلی رسید.

بسته‌ها

همان‌طور که اشاره شد “بسته‌ها” رویکرد دیگری برای ایجاد، توزیع و پیاده‌سازی یک هدف مشخص هستند. مخازن گوناگونی برای نگهداری از این بسته‌ها وجود دارند، دو تا از اصلی‌ترین این مخازن عبارتند از:

هر کدام از این مخازن دارای ابزار مدیریت قدرتمندی در خط فرمان هستند که اجازه‌ی نصب و بروزرسانی تمام بسته‌های مورد نیاز را به شما می‌دهند، این مخازن پیش‌تر در قسمت مدیریت وابستگی توضیح داده شدند.

دسته‌ی دیگری از بسته‌ها وجود دارند که در این مخازن نگهداری نمی‌شوند اما هیچ وابستگی هم به سایر بسته‌ها یا چارچوب‌های نرم‌افزاری دیگر ندارند.

برای نمونه، می‌توانید از بسته‌ی اعتبارسنجی FuelPHP بدون استفاده از چارچوب نرم‌افزاری FuelPHP استفاده کنید.

بسته‌ی Illuminate components مربوط به Laravel با جدا شدن از این پروژه، در حال بهتر شدن است. هم اکنون، تنها بسته‌هایی که از این پروژه جدا شده‌اند در فهرست بالا آمده‌اند.

کتاب‌ها

کتاب‌های بسیاری درباره‌ی PHP وجود دارند که تعداد زیادی از آن‌ها قدیمی شده و حاوی اطلاعات جدید نیستند. کتاب‌هایی هم هستند درباره‌ی PHP 6 که اصلا وجود ندارد، و ممکن است که هم اکنون به خاطر این کتاب‌ها به وجود نیامده است.

این قسمت به عنوان یک سند فعال درباره‌ی کتاب‌هایی است که به توسعه‌ی PHP می‌پردازند. اگر قصد دارید کتاب خود را معرفی کنید، یک درخواست PR ارسال کنید تا پس از بازبینی در این قسمت منتشر شود.

کتاب‌های آزاد (رایگان)

کتاب‌های غیرآزاد (خریدنی)

Back to Top

جامعه‌کاربری

جامعه‌ی PHP از طیف افراد گوناگونی با قابلیت‌های گوناگون به وجود آمده است و همیشه آماّده‌ی پذیرش برنامه‌نویسان جدید است. سعی کنید در گروه کاربری PHP شهر خود (PUG) شرکت کنید تا دانش مطرح شده در این وبسایت را بهتر درک کنید. همچنین در شبکه‌ی IRC و کانال phpc# روی irc.freenode.com می‌توانید حضور داشته باشید و حساب کاربری phpc@ در توییتر را دنبال کنید. به محفل آن‌ها بپیوندید، با توسعه‌دهندگان جدیدی آشنا شوید، مباحث تازه‌ای فرا گیرید و از همه مهم‌تر، دوستان جدیدی پیدا کنید! سایر شبکه‌ها عبارتند از گوگل‌پلاس php-programmers-gplus و StackOverflow

مطالعه‌ی تقویم رویدادهای رسمی PHP

گروه‌های کابران PHP

اگر در شهر بزرگی زندگی می‌کنید، به احتمال زیاد یک گروه کاربران PHP در آن حوالی است. اگرچه فهرست رسمی از این گروه‌ها وجود ندارد اما می‌توانید با جستجو در گوگل و Meetup.com یا PHP.ug آن‌ها را پیدا کنید. اگر در شهر کوچکی زندگی می‌کنید و گروه کاربران نیز ندارید، خوب دست به کار بشید و یکی بسازید!

درباره‌ی گرو‌ه‌های کاربران در ویکی PHP بیشتر بخوانید

کنفرانس‌های PHP

جامعه‌ی PHP میزبان کنفرانس‌های کوچک و بزرگ در نقاط مختلف دنیا است. اعضای شناخته‌شده‌ی این جامعه، بیشتر در این کنفرانس‌ها سخن می‌گویند، پس فرصت خوبی است که به صورت مستقیم از این پیشتازان PHP مطالب جدید را بیاموزیم.

یک کنفرانس PHP پیدا کنید

Back to Top

PHPDoc

یک روش غیر رسمی برای درج توضیحات در کد PHP است. تگ‌های بسیار زیادی جهت استفاده در کد وجود دارند. فهرست کاملی از این تگ‌ها و نمونه‌های مربوط به آن‌ها در [راهنمای PHPDoc][http://www.phpdoc.org/docs/latest/index.html] آورده شده است.

در ادامه، نمونه‌ای آمده است که نشان می‌دهد چطور می‌توان برای یک کلاس و متدهای مربوط به آن توضیحات نوشت:

<?php
/**
 * @author A Name <a.name@example.com>
 * @link http://www.phpdoc.org/docs/latest/index.html
 * @package helper
 */
class DateTimeHelper
{
    /**
     * @param mixed $anything Anything that we can convert to a \DateTime object
     *
     * @return \DateTime
     * @throws \InvalidArgumentException
     */
    public function dateTimeFromAnything($anything)
    {
        $type = gettype($anything);

        switch ($type) {
            // Some code that tries to return a \DateTime object
        }

        throw new \InvalidArgumentException(
            "Failed Converting param of type '{$type}' to DateTime object"
        );
    }

    /**
     * @param mixed $date Anything that we can convert to a \DateTime object
     *
     * @return void
     */
    public function printISO8601Date($date)
    {
        echo $this->dateTimeFromAnything($date)->format('c');
    }

    /**
     * @param mixed $date Anything that we can convert to a \DateTime object
     */
    public function printRFC2822Date($date)
    {
        echo $this->dateTimeFromAnything($date)->format('r');
    }
}

مستندسازی کلاس در اولین قدم با یک تگ author@ آغاز می‌شود، که از این تگ برای تشخیص اینکه چه افرادی این کد را نوشته‌اند، استفاده می‌شود. سپس یک تگ link@ آمده است که ارتباط بین کد موجود و وبسایت اصلی را نشان می‌دهد. در نهایت یک تگ package@ جهت طبقه‌بندی کد آورده شده است.

درون کلاس، اولین متد یک تگ param@ دارد که نوع، نام و توضیحات پارامترهای مورد نیاز متد را دربر دارد. همچنین دارای تگ return@ و throws@ است که جهت مستندسازی مقدار بازگشتی و روش مدیریت خطا استفاده می‌شود.

متدهای دوم و سوم به نسبت ساده هستند و همان تگ param@ را دارند که در متد اول مورد استفاده قرار گرفت. تفاوت مهم بین متدهای دو و سه چگونگی به کارگیری/حذف تگ return@ است. return void@ به صورت واضح بیان می‌کند که خروجی وجود ندارد.

Back to Top