اطلاعات بسیار قدیمی موجود در وب باعث میشود کاربران جدید پیاچپی دچار سرگردانی شده و عادتهای بد کدنوشتن (از جمله نا امن بودن کد) را در آنها ایجاد میکند. پیاچپی: از راه درستش یک راهنمای ساده و جامع از بهترین روشهای کدنویسی در پیاچپی است، که به بسیاری از راهنماهای معتبر در وب پیوند دارد که اکثر آنها شامل بهترین روشهای کدنویسی هستند.
استفاده از پیاچپی استاندارد خاصی ندارد. هدف این وبسایت معرفی موضوعاتی برای توسعهدهندگان پیاچپی است که تا به حال با آن برخورد نکردهاند، همچنین معرفی ایدههایی برای افراد حرفهای است که ممکن است سالها از این ایدهها استفاده کرده بدون اینکه به یاد داشته باشند. این وبسایت شما را به استفاده از یک ابزار خاص سوق نمیدهد بلکه گزینههای مختلفی پیش روی شما میگذارد، که هر زمان لازم باشد تفاوت بین آنها گفته میشود.
این یک سند فعال و در حال تغییر است که طی بازههای زمانی با اطلاعات جدید و کاربردی جایگزین میشود.
وبسایت پیاچپی: از راه درستش به زبانهای مختلفی ترجمه شده است (یا در حال ترجمه است):
کمک کنید تا این وبسایت را به بهترین منبع برای برنامهنویسان پیاچپی (مخصوصا تازه واردها) تبدیل کنیم! مشارکت در Github
وبسایت پیاچپی: از راه درستش بنرهایی مخصوص وب دارد که میتوانید در سایت خود قرار دهید. پشتیبانی کنید و بگذارید تازهواردهای PHP به منابع خوب دسترسی داشته باشند.
اگر تازه با 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 میتوانید یک ماشین مجازی ساده را در کوتاهترین زمان آماده کنید. این بستههای پایه به صورت دستی قابل نصب هستند، یا میتوانید از نرمافزارهایی مانند Puppet یا Chef جهت پیادهسازی اولیهی آنها برای شما، استفاده کنید. استفاده از این ابزارها برای ایجاد بستههای پایه روش مناسبی است جهت اطمینان حاصل کردن از این مورد که تمام بستهها در محیطهای متفاوت، عمکرد یکسانی خواهند داشت. همچنین میتوانید بستهی پایهی خود را “نابود” کرده و دوباره آن را بسازید، بدون آنکه این کار را دستی انجام دهید.
Vagrant پوشههایی را جهت اشتراکگذاری کد شما روی ماشین شما و ماشین مجازی ایجاد میکند، که به این معنی است شما فایلهای خود را در ماشین خود ایجاد یا ویرایش میکنید و برنامهی شما در ماشین مجازی اجرا میشود.
اگر در استفاده از Vagrant به کمی راهنمایی نیاز دارید سه سرویس مختلف وجود دارند که شما را یاری میرسانند:
جامعهی PHP بزرگ و پراکنده است که از کتابخانهها، فریمورکها و اجزای گوناگونی تشکیل شده است. برای توسعهدهندگان PHP امری طبیعی است که بخشی از این ابزار را در پروژههای خود به کار ببرند. از این رو، بسیار مهم است که کد PHP از یک سبک استاندارد (تا آنجا که امکان دارد) طبعیت کند تا توسعهدهندگان بتوانند به سادگی از کتابخانههای مختلف در پروژهی خود استفاده کنند.
گروه تعاملی فریمورک PHP مجموعهای از سبکها را تهیه و آماده کرده است. تمام آنها مربوط به کدنویسی نمیشوند، اما آنهایی که هستند عبارتند از:
این توصیهها تقریبا مجموعهای از قوانین هستند که پروژههایی نظیر Drupal، Zend، Symfony، CakePHP و بسیاری دیگر از آنها استفاده میکنند. شما میتوانید از آنها در پروژههای خود استفاده کنید، یا همان سبک کدنویسی خود را ادامه دهید.
در حقیقت باید طوری کد بنویسید که از یک استاندارد شناختهشده طبعیت کند. این استاندارد میتواند هر ترکیبی از PSRها یا یکی از استانداردهای ایجاد شده توسط PEAR یا Zend باشد. این بدان معنی است که سایر توسعهدهندگان به سادگی بتوانند با کد شما ارتباط برقرار کنند، و نرمافزارهایی که از اجزای جداگانه تشکیل شدهاند با یکدیگر سازگاری داشته باشند.
شما میتوانید از ابزاری مانند PHP CodeSniffer برای بررسی هر یک از این استانداردها، یا از افزونههایی برای ویرایشگرهای متن مانند Sublime Text 2 استفاده کنید.
همچنین ابزار PHP Coding Standards Fixer که توسط Fabien Potencier توسعه داده شده، به صورت خودکار کد شما را نسبت به این استانداردها بررسی میکند و تغییرات لازم را انجام میدهد، لازم هم نیست شما این کار را به صورت دستی انجام دهید.
انگلیسی زبان اصلی برای تمام نمادها و ساختار کد است. کامنتها میتوانند به هر زبانی که برنامهنویسان در پروژه با آن آشنا هستند، نوشته شوند.
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) را اضافه کرده و همچنین پشتیبانی از فراخوانیهایی با توابع بینام را بهبود بخشیده است.
از طریق مکانیسمهایی مانند 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 یا همان 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
یکی از کاربردیترین ابزارها در توسعهی نرمافزار، اشکالزدا (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 در سیستم عامل مکینتاش است.
کتابخانهها، فریموُرکها و اجزای مختلفی از PHP وجود دارند که میتوانید از آنها استفاده کنید. به احتمال زیاد پروژهی شما از این اجزا استفاده میکند، اینها وابستگی (dependency) نام دارند. تا همین اواخر، روش مناسبی برای مدیریت این وابستگیها درPHP وجود نداشت. حتی اگر شما این کار را میکردید، باید نگران فراخوانیهای خودکار (autoloaders) میبودید. این روند دیگر ادامه ندارد.
هم اکنون دو مدیر بستهی اصلی برای PHP وجود دارد، Composer و PEAR. کدام یک برای شما مناسب است؟ هر دو.
در حالت کلی، بستههای Composer تنها در پروژههایی که شما تعیین میکنید وجود خواهند داشت در صورتی که بستههای PEAR برای تمام پروژهها در دسترس خواهند بود. در ابتدا ممکن است به نظر برسد استفاده از PEAR مناسب است اما مزایایی در روش پروژه به پروژه وجود دارد که باید به آنها فکر کنید.
Composer یک مدیر بستهی فوقالعاده برای PHP است. وابستگیهای پروژهی خود را در یک فایل composer.json
فهرست کنید و، با تنها چند فرمان ساده، تمام وابستگیها دانلود شده و به صورت پیشفرض فراخوانی میشوند.
کتابخانههای بسیاری از PHP وجود دارند که با Composer سازگار هستند، که میتوانید از آنها استفاده کنید. این “بستهها” در مخزن رسمی بستههای سازگار با Composer، یعنی Packagist فهرست شدهاند.
شما میتوانید Composer را به صورت محلی (در دایرکتوری فعلی، که توصیه نمیشود) یا سراسری (برای نمونه در usr/local/bin/) نصب کنید. فرض کنیم میخواهید به صورت محلی نصب کنید. از دایرکتوری اصلی پروژهی خود:
curl -s https://getcomposer.org/installer | php
این فرمان composer.phar
(فایل باینری PHP) را دانلود میکند. میتوانید با استفاده از php
برای مدیریت وابستگیها در پروژهی خود، از آن استفاده کنید. توجه کنید: اگر به صورت مستقیم کد دانلود شده را به یک مفسر (interpreter) ارجاع دهید، ابتدا از امن بودن کد اطمینان حاصل کنید.
برای کاربران ویندوز راحتترین روش استفاده از نرمافزار ComposerSetup است، که نصب را به صورت سراسری انجام میدهد و PATH$
را طوری تنظیم میکند که بتوانید از هر دایرکتوری در خط فرمان، composer
را فراخوانی کنید.
این روش نصب کمی پیچیدگی دارد; اگرچه، دلایل مختلفی وجود دارد که یک توسعهدهنده این روش را نسبت به روش خودکار ترجیح دهد. در نصب خودکار، بررسی میشود در محیط PHP شما:
phar
به درستی اجر شوندphp.ini
وجود داشته باشنددر صورتی که نصب دستی، هیچ کدام از موارد فوق را پوشش نمیدهد، البته شما باید تصمیم نهایی را بگیرید. در هر صورت، میتوانید 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
به شما میگوید آیا باید وابستگیهای خود را بروزرسانی کنید یا خیر.
مدیر بستهی مشهور دیگری که بسیاری از توسعهدهندگان PHP از آن لذت میبرند PEAR است. شبیه به Composer عمل میکند اما تفاوتهای قابل توجهای دارد.
هر بسته باید ساختار مشخصی داشته باشد، به این معنی که نویسندهی بسته باید آن را مطابق با استانداردهای PEAR آماده کند. استفاده از پروژهای که با PEAR سازگار نیست، غیرممکن است.
تمام بستهها در PEAR به صورت سراسری روی سرور نصب میشوند و برای تمام پروژهها قابل استفاده هستند. برای پروژههای مختلفی که به یک بسته وابسته هستند راهکار بسیار خوبی است اما زمانی که دو پروژه در یک نسخه تفاوت داشته باشند، مشکلساز خواهد شد.
شما میتوانید با دانلود و اجرای فایل phar مربوط به PEAR آن را نصب کنید. مستندات PEAR به جزییات دستورات نصب برای سیستم عاملهای مختلف اشاره کرده است.
اگر از گنو/لینوکس استفاده میکنید، میتوانید نگاهی به مدیر بسته توزیع خود بیندازید. برای نمونه، دبیان و اوبونتو یک بسته با نام php-pear
دارند.
اگر بستهی مورد نظر در فهرست بستههای PEAR وجود دارد، میتوانید با اسم رسمی آن را نصب کنید:
pear install foo
اگر بسته در کانال دیگری قرار دارد، ابتدا باید آن کانال را discover
کرده و در زمان نصب نام آن را ذکر کنید. برای اطلاعات بیشتر در این مورد، مستندات مربوط به کانالها را مشاهده کنید
اگر از 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();
زبانی به وسعت 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') . ' ';
}
زمانی که نرمافزار خود را توسعه میدهید مرسوم است از الگوهای خاصی در کد و ساختار کلی پروژه استفاده کنید. استفاده از این الگوها بسیار مفید است چرا که نه تنها باعث میشود مدیریت کد آسان گردد بلکه درک نرمافزار شما برای سایر توسعهدهندگان نیز آسان میگردد.
اگر از یک فریمورک استفاده میکنید پس بیشتر قسمتهای کدنویسی و ساختار پروژه که بر اساس آن فریمورک است، از پیش برایتان مشخص شده است. اما در نهایت تصمیم با شماست که کد خود را بر اساس آن فریمورک پیش ببرید یا خیر. اگر هم از فریمورک استفاده نمیکنید باید خود به دنبال الگوهایی باشید که با نوع و اندازه (حجم) پروژهی شما سازگار باشند.
محتوای اولیهی این بخش توسط Alex Cabal در مجموعهی بهترین عادتهای کدنویسی در PHP نوشته شده است که در اینجا به عنوان مقدمهی مقالهی ما قرار دارد.
هم اکنون PHP در سطح پایین از یونیکد پشتیبانی نمیکند. روشهایی وجود دارد تا اطمینان حاصل کنیم تمام رشتههای UTF-8 به درستی پردازش میشوند اما این روشها آسان نیستند و لایههای مختلفی از یک نرمافزار تحت وب را شامل میشوند، از HTML به SQL به 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
از آن استفاده میکند، در غیر اینصورت از توابع عادی رشتهای استفاده خواهد کرد.
اگر اسکریپت PHP شما به MySQL دسترسی دارد، احتمال دارد رشتههای شما به صورت UTF-8 در پایگاهداده ذخیره نشوند، هر چند گامهای بالا را انجام داده باشید.
جهت اطمینان از ذخیرهسازی رشتهها به صورت UTF-8، باید پایگاهداده و جدولهای شما از ساختار utf8mb4
پشتیبانی کنند و در رشتهی اتصال PDO نیز از utf8mb4
استفاده کنید. به مثال زیر توجه کنید. این مورد بسیار حایز اهمیت است.
توجه کنید که باید از مجموعه کاراکتر utf8mb4
جهت پشتیبانی کامل از UTF-8 استفاده کنید نه از utf8
! به قسمت مطالهی بیشتر مراجعه کنید تا دلیل آن را بدانید.
از تابع ()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>
از ویکیپدیا:
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 آنها را رفع میکند.
این عبارت همانطور که از نامش پیداست با جدا نگاهداشتن کنترل از تمام شیها، “کنترل را وارونه” میسازد. در تعریف Dependency Injection به این معناست که وابستگیهای موجود را با نمونهسازی در قسمتهای دیگر، ضعیف سازیم.
برای سالها، فریمورکهای PHP این تکنیک را به کار گرفتهاند، اگرچه پرسش این است که کدام قسمت کنترل را وارونه میسازید و به کجا؟ برای نمونه، فریمورکهای MVC معمولا یک شی پایه یا کنترلکنندهی پایه را به وجود میآورند که سایر کنترلکنندهها برای دسترسی به وابستگیهای آن از این شی پایه ارثبری میکنند. این همان مفهوم وارونگی کنترل است، اگرچه به جای تضعیف وابستگیها، این روش آنها را منتقل میکند.
Dependency Injection به ما کمک میکند که این مشکل را با تعریف وابستگیهایی که تنها به آنها نیاز داریم، رفع کنیم.
این عبارت همان حرف “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 خود را دارا هستند که به کاربر اجازه میدهد درست مانند همان فریمورکی که از آن استفاده میکند، نرمافزار خود را پیادهسازی کند.
بسیاری از مواقع کد شما از یک پایگاهداده استفاده میکند تا اطلاعات را ذخیره کند. شما با گزینههای مختلفی جهت تعامل با پایگاهداده روبهرو هستید. روش توصیه شده تا نسخه PHP 5.1.0 استفاده از درایورهایی مانند mysqli و pgsql و mssql و … بود.
استفاده از این درایورها بسیار مناسب است به شرط آنکه برنامهی شما تنها با یک پایگاهداده سروکار داشته باشد، اگر،برای نمونه، به طور همزمان از MySQL و MSSQL استفاده میکنید، یا نیاز به برقراری ارتباط با Oracle دارید، آنگاه قادر نخواهید بود از این درایورها استفاده کنید. اینجاست که باید برای هر درایور کد جداگانهای بنویسید — که این کار بیهودهای است.
افزونهی mysql دیگر توسعه داده نمیشود و پایان عمر آن در نسخه PHP 5.5.0 به طور رسمی اعلام شده است، بدین معنی که در نسخههای بعدی حذف خواهد شد. اگر در برنامهی خود از تابعهایی که با *_mysql
شروع میشوند استفاده میکنید، مانند ()mysql_connect
و ()mysql_query
، اینها در نسخههای بعدی PHP قابل استفاده نخواهند بود. این بدان معنی است که باید آنها را با گزینههای مناسبتری مانند mysqli یا PDO جایگزین کنید و بهتر است که این کار را اکنون انجام دهید تا بعدها مجبور نباشید این تغییرات را با عجله انجام دهید.
اگر از ابتدا نرمافزاری را شروع کردهاید به طور حتم نباید از افزونهی mysql استفاده کنید: در عوض از افزونهی MySQLi یا 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 ساخته شدهاند و میتوانند در بسیاری از نرمافزارها مورد استفاده قرار بگیرند:
قالبها باعث میشوند منطق کد شما از قسمت نمایشدهنده یا خروجی آن جدا گردد. قالبها بیشتر دربردارندهی HTML نرمافزار شما هستند اما میتوانند ساختارهای دیگری را نیز شامل شوند، مانند XML. قالبها با نام “Views” نیز یاد میشوند، دومین بخش الگوی معماری نرمافزار MVC.
مزیت اصلی در استفاده از قالبها این است که منطق نرمافزار شما از قسمت ظاهری و نمایشی آن جدا میشود. قالبها وظیفهی اصلی در نمایش دادن محتوا را دارند. آنها وظیفهی ذخیرهسازی یا عملیات پیچیدهی دیگر روی دادهها را ندارند. این موضوع بیشتر در تیمهای نرمافزاری که افراد گوناگون روی قسمتهای مختلف پروژه کار میکنند، تاثیرگذار است، برای نمونه کد سمت سرور (کنترلکنندهها، مدلها) که توسط توسعهدهندگان و کد سمت مرورگر که توسط طراحان نوشته میشود.
استفاده از قالبها منجر به بهینهشدن کد قسمت ظاهری نرمافزار خواهد شد. قالبها معمولا در پوشهی “views” قرار داده میشوند، که هر کدام در یک فایل جداگانه قرار دارند. این رویکرد استفاده مجدد از کد را بهینه میکند چرا که قسمتهای بزرگ کد را به بخشهای کوچکتر تبدیل میکند. برای نمونه، قسمت header و footer سایت شما میتواند توسط قالب تعریف شود، که این قالبها قبل و بعد از قالب اصلی نرمافزار قرار میگیرند.
در نهایت، بر اساس کتابخانهای که از آن استفاده میکنید، قالبها میتوانند امنیت بیشتری ایجاد کنند چرا که محتوای تولید شده توسط کاربر را به صورت خودکار امن میسازند (به عبارت دیگر escape میکنند). برخی کتابخانهها محیطهای امنی را در اختیار طراحان قالب قرار میدهند که تنها به بخشی از متغیرها و توابع دسترسی دارند.
این قالبها تنها دربردارندهی کد 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' %}
در زبانهای برنامهنویسی که “خطایابی سنگین” دارند، هر زمان خطایی رخ دهد یک استثنا به وجود میآید. البته این روش ماندگاری جهت انجام کارها است اما 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 یا فراخوانی برخی توابع قابل تغییر است. با استفاده از تابع ()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 وجود دارند که با خاموش بودن کامل این عملگر کار نخواهند کرد.
برای اینکه 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
}
کلاس عمومی Exception
زمینهی خطایابی محدودی برای توسعهدهنده ایجاد میکند. اگرچه، برای غلبه بر این محدودیت، این امکان وجود دارد از کلاس اصلی Execption
ارثبری کنیم:
<?php
class ValidationException extends Exception {}
این بدان معنی است که میتوانید حالتهای مختلفی جهت بررسی خطا در این کلاس تعریف کنید. این کار منجر به تولید بسیاری موارد استثنا خواهد شد، که برخی از آنها به صورت کلی توسط افزونه SPL نادیده گرفته میشوند.
برای نمونه اگر از تابع ()call__
استفاده کنید و طی آن یک متد نامعتبر فراخوانی شود به جای اینکه یک استثنا از نوع استاندارد ایجاد شود، میتوانید به راحتی از استثنایی مانند throw new BadMethodCallException
استفاده کنید.
افراد مختلفی وجود دارند که میتوانند از نرمافزار وب شما سواستفاده کنند و این وظیفهی شماست که اقدامات لازم جهت هرچه امنتر شدن نرمافزار را انجام دهید. خوشبختانه، افراد حاضر در پروژهی امنیت نرمافزارهای تحت وب، چارچوبی را به عنوان سند برای پیادهسازی روشهای امنیت اطلاعات در نرمافزارهای تحت وب فراهم ساختهاند. این سند، برای توسعهدهندگانی که به امنیت نرمافزار خود اهمیت میدهند بسیار مفید است.
به طور طبیعی، یکی از فرآیندهای موجود نرمافزارهای وب مبتنی بر 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 یا سایر کاراکترها را حذف کرد تا منجر به نمایش مکانهای مخفی در سرور نشوند.
filter_var
بیشتر بدانیدfilter_input
بیشتر بدانیداین فرآیند، با حذف یا نادیدهگرفتن برخی کاراکترهای ناامن از دادهی ورودی، صورت میگیرد.
برای نمونه، قبل از قرار دادن دادهی ورودی در خروجی نهایی یا درج آن در پایگاهداده باید آن را از کاراکترهای غیرمجاز پاکسازی کنید. عمل تخصیص پارامتر به یک پرسوجو توسط PDO اینکار را برای شما انجام میدهد.
گاهی اوقات لازم است به برخی تگهای امن HTML اجازهی قرارگیری در صفحه داده شود. مدیریت این فرآیند گاهی بسیار دشوار میشود تا جایی که برخی ترجیح میدهند از پیشپردازندههایی مانند Markdown یا BBCode استفاده کنند و کتابخانههایی مانند HTML Purifier به همین منظور وجود دارند.
مشاهدهی فیلترهای به کار رفته در پاکسازی دادهی ورودی
این فرآیند به شما کمک میکند از صحت اطلاعات ورودی اطمینان حاصل کنید. برای نمونه، هنگام پردازش یک فرم ثبتنام، شاید بخواهید ایمیل، شماره تلفن یا سن فرد را بررسی و کنترل کنید.
هنگام به وجود آوردن فایلهای پیکربندی برای نرمافزار خود بهتر است به برخی اصول بنیادی پایبند باشید:
php.
ذخیره سازید. حتی اگر اسکریپت به صورت مستقیم فراخوانی شود، خروجی آن به صورت متن نمایش داده نمیشود.تذکر: از نسخهی 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
-1
یا E_ALL
-1
یا E_ALL | E_STRICT
-1
یا E_ALL
جهت پنهانسازی تمام خطاهای موجود در محیط نهایی، تنظیمات زیر را در فایل php.ini
انجام دهید:
display_errors = Off
display_startup_errors = Off
error_reporting = E_ALL
log_errors = On
با استفاده از این تنظیمات، خطاها کماکان در سرور ثبت میشوند اما به کاربر نمایش داده نمیشوند. برای اطلاعات بیشتر دربارهی این تنظیمات، راهنمای رسمی PHP را مشاهده کنید:
نوشتن آزمونهای خودکار برای کد 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 مربوط به روبی الهام گرفته شده است.
علاوه بر چارچوبهای معرفی شده، ابزارهای دیگری نیز برای آزموننویسی وجود دارد که در ادامه به آنها اشاره میکنیم.
برنامههای PHP به روشهای متفاوتی روی سرورهای حقیقی میتوانند اجرا شوند یا توسعه یابند.
بستر PaaS معماری سیستم و شبکهی مورد نیاز جهت اجرای برنامههای PHP را فراهم میکند. این بدان معناست که تغییرات ناچیزی جهت اجرای برنامههای PHP یا چارچوبهای نرمافزاری PHP در این بستر، مورد نیاز است.
اخیرا بستر PaaS به روشی متداول جهت توسعه، میزبانی و مقیاسپذیری برنامههای PHP در ابعاد مختلف تبدیل شده است. شما میتوانید فهرستی از فراهمآورندگان بستر PaaS برای PHP را در قسمت منابع مشاهده کنید.
اگر با مدیریت سیستم آشنا هستید یا قصد یادگیری آن را دارید، سرورهای مجازی یا اختصاصی قدرت کامل در اختیار گرفتن محیط اجرای برنامهها را، به شما میدهند.
ماژول قدرتمندی در PHP وجود دارد با نام مدیر فرآیند FastCGI یا FPM و قابلیت انطباق بالایی با nginx دارد که وبسروری است سبک و با قابلیت اجرایی بسیار بالا. نسبت به آپاچی از حافظهی کمتری استفاده میکند و بهتر میتواند درخواستهای همزمان را مدیریت کند. این امر دربارهی سرورهای مجازی که از حافظهی کمتری استفاده میکنند اهمیت بسیار زیادی دارد.
تاریخچهی طولانی بین PHP و آپاچی وجود دارد. آپاچی قابلیت تنظیم بالایی دارد و برای اینکار از ماژولهای بسیاری بهره میگیرد. در بین سرورهای اشتراکی بسیار محبوب است و به سادگی میتوان روی آن بسیاری از چارچوبهای نرمافزاری PHP و برنامههای اُپنسورس مانند دروپال و وُردپِرس را راهاندازی کرد. متاسفانه، آپاچی از منابع بیشتری نسبت به nginx استفاده میکند به خوبی آن نمیتواند بازدیدکنندگان همزمان با تعداد بالا را مدیریت کند.
آپاچی پیکربندیهای متفاوتی جهت اجرای PHP دارد. معمولترین آنها برای راهاندازی prefork MPM با استفاده از ماژول mod_php5 است. با اینکه بهینهترین روش جهت مدیریت حافظه نیست اما سادهترین آنها برای استفاده است. اگر قصد ندارید به جنبههای مختلف مدیریت سیستم بپردازید، این روش مناسب شماست. به یاد داشته باشید استفاده از ماژول mod_php5 مستلزم استفاده از prefork MPM است.
از طرف دیگر، اگر قصد بهرهگیری از قدرت اجرای بالاتر و پایدارتر شدن آپاچی را دارید میتوانید از همان سیستم FPM موجود در nginx که در آپاچی با ماژولهای worker MPM یا event MPM و با استفاده از mod_fastcgi یا mod_fcgid پیادهسازی شده است، استفاده کنید. این پیکربندی مصرف حافظه را بهبود بخشیده و سرعت بالایی به همراه میآورد اما زمان بیشتری جهت پیکربندی خواهد برد.
اگر تغییرات مربوط به پایگاهداده را دستی انجام میدهید یا آزمونهای نوشته شده را به صورت دستی اجرا میکنید، بهتر است دوباره بیندیشید! با انجام هر کار به صورت دستی در هر نسخه از نرمافزار خود احتمال بروز خطای مهلک افزایش مییابد. خواه تغییر کوچکی اعمال کنید یا با یک فرآیند ساخت پیچیده روبهرو باشید، خودکارسازی فرآیند تولید به کمک شما میآید.
از میان کارهایی که قصد خودکارسازی آنها را دارید میتوان به موارد زیر اشاره کرد:
این ابزارها معمولا از تعدادی اسکریپت تشکیل شدهاند که فرآیند توسعهی نرمافزار را آسان میکنند. ابزار تولید، بخشی از نرمافزار شما نیست، بلکه از بیرون آن را مدیریت میکند.
ابزارهای اُپِن سورس بسیاری در این رابطه وجود دارند، که برخی از آنها نیز با 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:
مطالعهی بیشتر:
یک فرآیند توسعهی نرمافزار است که طی آن اعضای یک تیم کار روزانهی خود را با سایر اعضا یکپارچه میسازند، که ممکن است این عمل چند مرتبه در روز صورت گیرد. بسیاری از تیمها به این نتیجه رسیدهاند که این عمل منجر به یکپارچگی بیشتری در محصول نهایی خواهد شد و به تیم این اجازه را میدهد که در زمان کوتاهتری فرآیند توسعه را سپری کنند.
– Martin Fowler
روشهای مختلفی جهت پیادهسازی این فرآیند در PHP وجود دارد. اخیرا Travis CI موفق شده است این تکنیک را در بسیاری از پروژهها پیادهسازی کند، حتی پروژههای کوچک. Travis CI یک سرویس آنلاین است که در اختیار جامعهی اِپِن سورس قرار دارد. این ابزار با GitHub یکپارچه شده است و پشتیبانی خوبی از زبانهای برنامهنویسی موجود، از جمله PHP دارد.
مطالعهی بیشتر:
به صورت پیش فرض PHP زبان سریعی است اما ممکن است گاهی اوقات گلوگاههایی ایجاد شود که منجر به کند شدن نرمافزار گردند مانند اتصال به سرورهای دیگر، بارگیری فایل و موارد دیگر. خوشبختانه، ابزارهای مختلفی وجود دارند که میتوانند به قسمتی از نرمافزار شما سرعت بخشند یا باعث پیشگیری از تعداد دفعاتی شوند که عملیات زمانبر نام برده، کل نرمافزار را تحت تاثیر قرار میدهند.
زمانی که یک فایل PHP اجرا میشود، در پشت صحنه ابتدا به یک فایل bytecode یا opcode کامپایل شده، سپس این فایل bytecode اجرا میشود. اگر فایل PHP تغییر نکند، خروجی bytecode همیشه ثابت خواهد بود. این بدان معناست که عملیات کامپایل در این صورت فقط منابع پردازنده را هدر میدهد.
این دقیقا جایی است که ذخیرهسازی Bytecode به میان میآید. این عمل منجر به نگهداری فایل bytecode در حافظه شده و از کامپایل مجدد و بیهودهی آن جلوگیری میکند. پیادهسازی این نوع ذخیرهسازی تنها چند دقیقه زمان میبرد و بعد از آن متوجه افزایش سرعت نرمافزار خواهید شد. حقیقتا دلیلی وجود ندارد که از آن استفاده نکنیم.
با انتشار PHP 5.5، یک ذخیرهساز درونی به نام OPcache وجود دارد. البته برای نسخههای قبل از آن نیز موجود بود.
سایر ذخیرهسازهای Bytecode عبارتند از:
شرایطی وجود دارد که طی آن نیاز باشد یک شی منحصربهفرد را به صورت جداگانه در حافظه ذخیره کنیم، مانند حالتی که فراخوانی از پایگاهداده بسیار پرهزینه و خروجی آن نیز تغییر چندانی نداشته باشد. شما میتوانید از نرمافزارهایی که به این منظور طراحی شدهاند جهت ذخیرهسازی یک شی خاص در حافظه برای دسترسیهای سریعتر در آینده استفاده کنید. اگر این گزینهها را در یک انبار داده ذخیره کنید، سپس طی درخواستهای بعد آنها را از حافظه فراخوانی کنید، مقدار قابل توجهی به سرعت نرمافزار شما اضافه خواهد شد و بار اضافی نیز به سمت پایگاهداده روانه نمیشود.
بسیاری از راهحلهای مبتنی بر ذخیرهسازی 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 دارد.
دربارهی سیستمهای محبوب ذخیرهسازی شی بیشتر بدانید:
بسیاری از توسعهدهندگان PHP به جای اینکه تمام کار را از ابتدا خود انجام دهند، از چارچوبهای نرمافزاری یا فِریموُرک موجود استفاده میکنند. این ابزارها بسیاری از پیچیدگیهای سطح پایین را از بین برده و با در اختیار گذاشتن رابطهای برنامهنویسی گوناگون، طیف گستردهای از مشکلات را حل میکنند.
برای هر پروژهای هم نیاز به استفاده از این چارچوبها وجود ندارد. گاهی اوقات کدنویسی اولیه مشکل را حل میکند، اما اگر به یک چارچوب نرمافزاری نیاز داشتید بدانید که از سه خانوادهی مختلف تشکیل شدهاند:
چارچوبهای نرمافزاری کوچک حقیقتا یک دربرگیرنده یا wrapper هستند که درخواستهای HTTP را به کنترلکنندهها و متدهای خاصی ارجاع میدهند و گاهی اوقات ممکن است این فرآیند را در سمت پایگاهداده نیز انجام دهند. از آنها بیشتر برای ایجاد سرویسهای مبتنی بر HTTP استفاده میشود.
بسیاری از چارچوبهای نرمافزاری دیگر امکانات بیشتری را به دستهی اول اضافه میکنند که به آنها تمام عیار یا Full Stack اطلاق میشود. قابلیتهایی مانند ORMs، بستههای احراز هویت و موارد دیگر.
دستهی سوم از مجموعه کتابخانههایی برای اهداف خاص منظوره تشکیل شده است. با ترکیب این چارچوبها با یکدیگر میتوان به دو دستهی قبلی رسید.
همانطور که اشاره شد “بستهها” رویکرد دیگری برای ایجاد، توزیع و پیادهسازی یک هدف مشخص هستند. مخازن گوناگونی برای نگهداری از این بستهها وجود دارند، دو تا از اصلیترین این مخازن عبارتند از:
هر کدام از این مخازن دارای ابزار مدیریت قدرتمندی در خط فرمان هستند که اجازهی نصب و بروزرسانی تمام بستههای مورد نیاز را به شما میدهند، این مخازن پیشتر در قسمت مدیریت وابستگی توضیح داده شدند.
دستهی دیگری از بستهها وجود دارند که در این مخازن نگهداری نمیشوند اما هیچ وابستگی هم به سایر بستهها یا چارچوبهای نرمافزاری دیگر ندارند.
برای نمونه، میتوانید از بستهی اعتبارسنجی FuelPHP بدون استفاده از چارچوب نرمافزاری FuelPHP استفاده کنید.
بستهی Illuminate components مربوط به Laravel با جدا شدن از این پروژه، در حال بهتر شدن است. هم اکنون، تنها بستههایی که از این پروژه جدا شدهاند در فهرست بالا آمدهاند.
کتابهای بسیاری دربارهی PHP وجود دارند که تعداد زیادی از آنها قدیمی شده و حاوی اطلاعات جدید نیستند. کتابهایی هم هستند دربارهی PHP 6 که اصلا وجود ندارد، و ممکن است که هم اکنون به خاطر این کتابها به وجود نیامده است.
این قسمت به عنوان یک سند فعال دربارهی کتابهایی است که به توسعهی PHP میپردازند. اگر قصد دارید کتاب خود را معرفی کنید، یک درخواست PR ارسال کنید تا پس از بازبینی در این قسمت منتشر شود.
جامعهی PHP از طیف افراد گوناگونی با قابلیتهای گوناگون به وجود آمده است و همیشه آماّدهی پذیرش برنامهنویسان جدید است. سعی کنید در گروه کاربری PHP شهر خود (PUG) شرکت کنید تا دانش مطرح شده در این وبسایت را بهتر درک کنید. همچنین در شبکهی IRC و کانال phpc# روی irc.freenode.com میتوانید حضور داشته باشید و حساب کاربری phpc@ در توییتر را دنبال کنید. به محفل آنها بپیوندید، با توسعهدهندگان جدیدی آشنا شوید، مباحث تازهای فرا گیرید و از همه مهمتر، دوستان جدیدی پیدا کنید! سایر شبکهها عبارتند از گوگلپلاس php-programmers-gplus و StackOverflow
مطالعهی تقویم رویدادهای رسمی PHP
اگر در شهر بزرگی زندگی میکنید، به احتمال زیاد یک گروه کاربران PHP در آن حوالی است. اگرچه فهرست رسمی از این گروهها وجود ندارد اما میتوانید با جستجو در گوگل و Meetup.com یا PHP.ug آنها را پیدا کنید. اگر در شهر کوچکی زندگی میکنید و گروه کاربران نیز ندارید، خوب دست به کار بشید و یکی بسازید!
دربارهی گروههای کاربران در ویکی PHP بیشتر بخوانید
جامعهی PHP میزبان کنفرانسهای کوچک و بزرگ در نقاط مختلف دنیا است. اعضای شناختهشدهی این جامعه، بیشتر در این کنفرانسها سخن میگویند، پس فرصت خوبی است که به صورت مستقیم از این پیشتازان PHP مطالب جدید را بیاموزیم.
یک روش غیر رسمی برای درج توضیحات در کد 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@
به صورت واضح بیان میکند که خروجی وجود ندارد.