یوشا

وبگاه دست نوشته ها و تجربیات شخصی

یوشا

وبگاه دست نوشته ها و تجربیات شخصی

یوشا

دکتر مصطفی چمران: می گویند تقوا از تخصص لازمتر است، آنرا می پذیرم، اما می گویم: آنکس که تخصص ندارد و کاری را می پذیرد، بی تقواست!

بایگانی
تبلیغات
Blog.ir بلاگ، رسانه متخصصین و اهل قلم، استفاده آسان از امکانات وبلاگ نویسی حرفه‌ای، در محیطی نوین، امن و پایدار bayanbox.ir صندوق بیان - تجربه‌ای متفاوت در نشر و نگهداری فایل‌ها، ۳ گیگا بایت فضای پیشرفته رایگان Bayan.ir - بیان، پیشرو در فناوری‌های فضای مجازی ایران

 

در ادامه مقاله قبلیم که شماره یک "نکات و اصول مهم در برنامه نویسی PHP" بود، در این مقاله شماره دو همین موضوع رو ارائه میدم...

 

1- هنگام Multi-thread کردن کدهاتون فراموش نکنید برای دسترسی به اشیاء lazy-initialize(یا همون load on demand) وضعیت نهایی شی باید synchronize باشه تا با مشکل race condition مواجه نشید.

 

2- برای نرمال سازی ستونها و جلوگیری از افزونگی/redundancy داده باید از اصول زیر پیروی کنید:

- هیچ ستونی نباید بیشتر از یک نوع/type داده رو نگهداری کنه. (مثل int + char + float...)

- هیچ ستونی نباید داده های تکراری/مشابه به دیگر ستون ها رو در خودش نگهداری کنه.

- داده هارو در جداول مختلف نگهداری کنید و درصورت لزوم اونهارو توسط کلید خارجی/foreign key بهم متصل کنید.

 

3- جهت افزایش پرفورمنس، همیشه کلاس والد و اینترفیس رو در خطوط قبل از کلاس ارث بر تعریف کنید. در غیراینصورت موتور PHP برای پیدا و پردازش کردن کلاس والد مجبور به انجام عملیات های اضافی خواهد شد. (بر اساس OpCode تولید شده)

interface IData 
{
}

class MyClass implements IData
{
}

نکته: حتی اگر در فایلهای جداگانه تعریفشون می کنید این قائده باز هم باید رعایت بشه.

 

4- یادتون باشه که Dependency Injection نه تنها از طریق Constructor، بلکه از طریق Setter, Interface و Property هم قابل انجامه.

نکته: زمانی از نوع Constructor استفاده کنید که کل کلاس نیازمند به اون dependency هستش یا شی dependency نباید در طول life time تغییر بکنه.

 

5- آیا می دونید تابع runkit_function_remove علاوه بر حذف قید تابع(function table)، مقدار حافظه اشغال شده توسط تابع رو هم آزاد می کنه؟

6- برای حل مشکل PHP Fatal error: Class 'PHPUNIT_Framework_TestCase' not found هنگام کار با PHPUnit  راه های زیر رو دنبال کنید:

- از کد زیر استفاده کنید تا سازگاری با نسخ مختلف فراهم بشه:

if (!class_exists('\PHPUnit\Framework\TestCase') && class_exists('\PHPUnit_Framework_TestCase'))
{
   class_alias('\PHPUnit_Framework_TestCase', '\PHPUnit\Framework\TestCase');
}

- مطمعن بشید که از آخرین نسخه Composer و PHPUnit استفاده می کنید. (بخاطر نصب بصورت global)
- مطمعن بشید گه در پوشه pear داخل PHP تون PHPUnit دیگری وجود نداشته باشه.

 

7- چه زمانی باید از الگوی Facade استفاده بشه؟

1. زمانی که نیاز به کپسوله سازی(encapsulation) قابلیت های سیستم داریم.

2. نیاز هست هم از تمام قابلیت های فعلی سیستم استفاده کنیم و هم تعدادی قابلیت جدید به سیستم اضافه کنیم.

3. نیاز نیست از تمام قابلیت ها و پیچیدگی های سیستم استفاده بشه. بنابراین API جدید درست شده از API فعلی سیستم ساده تر و محدودتر خواهد بود.

 

8- نکاتی درباره تابع filter_var و مقدار FILTER_VALIDATE_URL

اینکه این تابع استاندارد و مناسب برای همه نوع کاراکتر حتی فارسی و unicode هستش... اما چطور؟

- بر اساس قوائد RFC، نوع کاراکتر استاندارد URL همیشه US-ASCII بوده و هر نوعی دیگه نامعتبر/invalid هستش.
لذا مرورگرها برای سازگاری با انواع متون غیر ASCII اونهارو encode می کنن... مثلا واژه "سلام" تبدیل میشه به "%d8%b3%d9%84%d8%a7%d9%85" (که اکنون استاندارد/valid میشه) و بعد فرستاده میشه سمت سرور.

- بنابراین تابع filter_var با پارامتر FILTER_VALIDATE_URL دقیق هستش و بررسیش رو بدرستی انجام میده... پس کافیه URL فارسی ورودی رو توسط تابع urlencode یا rawurlencode انکود کنید و بعد با VALIDATE_URL بررسیش کنید.

 

9- تفاوت تابع urlencode با تابع rawurlencode

- تابع urlencode متون رو encode میکنه، فاصله رو به + تبدیل میکنه، در آخر رشته بایت /0 قرار میده و بهتره برای query string استفاده بشه.
- تابع rawurlencode متون رو encode میکنه، فاصله رو به 20% تبدیل می کنه و بهتره برای path استفاده بشه.

echo ('http://domain/' . rawurlencode('my/path to/somewhere with space/') . 
      '/article.php?title=' . urlencode('how to be a foo'));

 

10- همیشه در محیط development مقدار تنظیم opcache.revalidate_freq در فایل php.ini رو 0 قرار بدید. تا OpCache در هر درخواست/request، کش سورسهای شمارو update کنه و تغییرات جدید رو اعمال کنه. (این تنظیم درواقع زمان expire شدن cache رو مشخص میکنه)

توجه: با غیرفعال کردن تنظیم opcache.validate_timestamps در فایل php.ini، مقدار تنظیم opcache.revalidate_freq هم نادیده گرفته خواهد شد.

 

11- نکته جزیی: آیا می دونید تابع str_replace باینری safe هستش و از UTF-8 بخوبی پشتیبانی می کنه؟

 

12- همیشه در مسیر دهی فایلها از نوع absolute/کامل استفاده کنید. اینکار سرعت پیمایش PHP برای پیدا کردن فایل رو افزایش میده.

 

13- تابع iconv_strlen یا تابع mb_strlen؟ توابع iconv بهتره برای هندل کردن رشته های Binary استفاده بشن، چون همیشه خروجی رو در byte تحویل میدن، در عوض توابع mb بازه بیشتری دارن و مناسبترین الگوریتم رو برای هندل کردن غیر ASCII ها دارن، حتی با کاراکترهای خاص هم سازگاری داره.

 

14- نکته ویندوزی: درصورت استفاده از سیستم کش OpCache و بروز خطای 500 internal error یا Base address marks unusable memory region یا خاموش شدن وب سرور یکی از راه های زیر رو انجام بدید:

- مقدار تنظیم opcache.mmap_base در فایل php.ini رو 0x20000000 قرار بدید.

- یا کش روی فایل رو فعال کنید: (PHP 7 به بعد)

opcache.file_cache="C:\Windows\temp\php_opcache"
opcache.file_cache_fallback=1

 

15- هنگام طراحی کلاس Singletone توجه داشته باشید که:

- متد __construct() با دسترسی protected تعریف بشه تا از ساخت شی new کلاس از خارج کلاس جلوگیری بشه.

- متد __clone() با دسترسی private تعریف بشه تا از clone شدن instance کلاس جلوگیری بشه.

- متد __wakeup() با دسترسی private تعریف بشه تا جلوی unserialize شدن instance کلاس جلوگیری بشه.

- و نهایتاً instance کلاس بصورت static برای subclass شدن ساخته بشه.

 

16- نکاتی راجب mb_internal_encoding و mb_http_output با UTF-8:

- اینکه تابع mb_internal_encoding برای تنظیم global هه encoding در همه توابع mb_* هستش. (و هیچ تاثیری بر روی Database ها نداره)

- تابع mb_http_output برای تنظیم output مرورگر با انکودینگ مشخص شده هستش.

- اینکه استفاده متاتگ زیر در HTML

<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

برابره با استفاده از دستور

header('Content-Type: text/html; charset=utf-8');

در کدهای PHP.

 

17- در فایل سورس(نه توابع)، فقط در مواقعی از return false/true; استفاده کنید که از خروجی فایل جاری include شده توسط متغیر استفاده می کنید. مثال:

$myVariable = include 'filename.php';

در غیر اینصورت برای اتمام پردازش فایل سورس، استفاده از دستور exit(1) یا exit یا پرتاب Exception بهترین گزینست.

 

18- توسط اسکریپت PHPMD - PHP Mass Detector می تونید باگ ها، مشکلات و قوائد رعایت نشده در پروژه تون رو پیدا و رفع کنید.

 

19- نکاتی کوتاه راجب DAL, DAO, DBAL, ODBC

  • Database abstraction layer یا DBAL یا middleware

- یک کتابخانه/لایه برای ارتباط بین "برنامه و دیتابیس" هستش
- بکمکش می شه  براحتی با همه MsSQL, MySQL, Oracle, PgSQL و... ارتباط برقرار کرد
- یک لایه فیزیکی(مثل DLL یا SO) برای کار با هر نوع دیتابیس هستش. بدون - - اینکه درگیر مسایل مختص به هر دیتابیس بشید
و...
مثال: ODBC مایکروسافت، JODBC, GNOME-DB، unixODBC, PHP-PDO...

  • Data access layer یا DAL

- یک سبک architecture/معماری هستش.
- درواقع لایه ای بین "منطق کدها(Bussiness logic layer) و داده" هستش
- از دستکاری دیتا بصورت مستقیم(مثل نوشتن کوئری برای هر INSERT) جلوگیری میکنه

- میشه گفت wrapper ای برای استفاده از توابع native دیتابیس هستش
- این سبک معماری میتونه دیتابیس independent باشه یا حتی صددرصد OO باشه(مثل ORM ها)

در DAL عملیات دیتابیس فقط در لایه ای پنهان میشن(مثلاً یک تابع یا کلاس).

و...
مثل: function createNewUser, function deleteAccount, class MySQL 

که بجای نوشتن کوئری و دستورات بصورت مستقیم، بواسطه لایه ها اینکار انجام میشه.

  • Data access object یا DAO

- یک نوع pattern/الگو در برنامه نویسی هستش
- درواقع OOP شده ی DAL هستش
- درواقع abstraction ای با خروجی "شی" برای دسترسی به دیتا هستش (شی ای برای دسترسی به دیتا)
- به لایه دیتا نزدیکه
- فقط توسط اشیا با دیتا کار میکنه
- بیشتر مربوط به مباحث .Net و جاوا هستش

نکته: ORM بخشی از برنامه هستش که لایه ای از نوع شی بین دیتابیس و برنامه ایجاد میکنه. و زیر مجموعه DAO هستش.

 

20- آیا میدونید برای موتور PHP همه classinterface و trait ها از یک نوع هستن و به یک شکل(zend_class_entry) مدیریت میشن؟

$class_interface_trait = <<<'MYCODE'
class Test { }
MYCODE;
$m = memory_get_usage();
eval($class_interface_trait);
echo memory_get_usage() - $m; // ~900 bytes
$class_interface_trait = <<<'MYCODE'
interface Test { }
MYCODE;
$m = memory_get_usage();
eval($class_interface_trait);
echo memory_get_usage() - $m; // ~900 bytes
و OpCode تولید شده هم برای همشون یکی هستش.
 

21- نکته جزیی: در زبانهای برنامه نویسی استاندارد، method فقط اگر داخل کلاس قرار گرفته باشه method خونده میشه. اما اگر خارج از کلاس قرار گرفته باشه، function یا procedure خونده میشه.

نکته: function زمانی function خونده میشه که مقداری رو بازگشت/return بده، درغیر اینصورت procedure خونده میشه.

نکته 2: در زبانهای شی گرا مثل Java، واژه ای بنام function/procedure وجود نداره و همگی method هستن.

 

22- نکاتی راجب collate و charset در دیتابیس ها:

- charset چگونگی انکود کردن کاراکترها رو تعیین می کنه و چطور در حافظه جای بگیرن. مثل € که توسط ISO-8859-15 انکود میشه به 0xa4 اما توسط UTF-8 انکود میشه به 0xe282ac

- collate چگونگی مقایسه کاراکترها رو تعیین می کنه. مثل é که توسط utf8_general_ci برابره(=) با e اما توسط utf8_bin برابر نیست(=!) با e

نکته: در حال حاضر UTF-8 در MySQL بصورت واقعی/کامل پشتیبانی نمیشه. اما این مساله در PHP حل شدست و PHP با برخورد به هر یک از این انواع، از UTF-8 کامل/استاندارد استفاده می کنه.

لذا برای MySQL 5.5.3 به بعد:

برای فقط زبان فارسی: utf8_persian_ci

برای همه زبان ها اما کند: جامع ترین و کاملترین collate، نوع utf8mb4_unicode_ci یا utf8mb4_general_ci و کاملترین charset نوع utf8mb4 هستش.

برای MySQL 5.5.2 به قبل:
برای فقط زبان فارسی: utf8_persian_ci

برای بعضی زبانها و زبان فارسی اما کند: utf8_general_ci (در این حالت حروف "کچپژ" در آخر و بعد از حرف "ی" قرار دارند)

برای بیشتر زبانها و زبان فارسی اما کندتر: utf8_unicode_ci

 

23- نکته جزیی: همیشه در حالت development(قبل از تحویل پروژه به مشتری) مقدار تنظیم default_charset در فایل php.ini رو خالی "" بذارید.

چون در صورت تعیین مقدار برای این تنظیم، encoding پیشفرض همه توابع htmlentities, html_entity_decode, htmlspecialchars, iconv, mb_* تغییر خواهد کرد. همچنین موتور PHP یک header مجزا(content-type) با مقدار تعیین شده به سمت کلاینت ارسال میکنه.

 

24- نکته ویندوزی: توسط برنامه editbin موجود در برنامه VS و nasm32 قادرید ظرفیت حافظه stack برنامه PHP.exe رو جهت جلوگیری از stackoverflow افزایش بدید.

 

25- برای حل مشکل IPv6 در MySQL و مقدار بازگشتی منفی تابع ip2long میتونید از توابع INET_ATON و INET_NTOA موجود در MySQL استفاده کنید.

 

26- نکته جزیی: برای موتور PHP هیچ فرقی بین function و method نیست و هردو به یک شکل(zend_function) پردازش میشن!

 

27- مهمترین تفاوت الگوی Adapter و الگوی Facade:

الگوی Adapter عمل تبدیل(convert) کلاس رو انجام میده اما الگوی Facade عمل ساده/خلاصه سازی(simplify) کلاس رو انجام میده.

- الگوی Adapter در نهایت یک کلاس رو پوشش میده اما الگوی Facade چندین کلاس رو پوشش میده.

 

28- درصورت خالی گذاشتن مقدار opcache.preferred_memory_model در فایل php.ini، موتور PHP مدل مموری mmap رو برای map کردن opcache در shared memory انتخاب میکنه.

 

29- اگر هنگام اجرای Apache HTTPD در لینوکس با خطای segmentation fault مواجه شدید میتونید با افزایش ظرفیت حافظه Stack آپاچی توسط مقدار تنظیم ThreadStackSize در فایل httpd-mpm.conf مشکل رو برطرف کنید. (در بیشتر موارد)

 

30- اگر هنگام اجرای Apache HTTPD در ویندوز با خطای The application was unable to start correctly 0xc0000142 مواجه شدید راه های زیر رو دنبال کنید:

- تاریخ سیستم رو به میلادی بروز کنید.

- اگر از ویندوز 64bit استفاده می کنید باید 2012-2015 VC++ Runtime نسخه 32 بیتی و 64 بیتی رو نصب کنید. (هر دو)

- یک scandisk روی درایو مورد نظر انجام بدید تا مطمعن شید فایلهای binary سیستم خراب/corrupt نشده باشن.

- از نسخه آپاچی مطمعن بشید و در سایت آپاچی، Runtime مورد نیازش رو پیدا و نصب کنید. 

- نهایتاً به برنامه EventViewer ویندوز نگاهی بندازید و توضیحات دقیقتر این خطا رو پیدا کنید.

 

31- برای حل مشکل The program cant start because php7.dll is missing from your computer در XAMP کافیه پکیچ PHP7 non-threadsafe رو دانلود و در محل نصب فعلی PHP کپی کنید.

نکته: به 32bit و 64bit بودن PHP دقت کنید و مطمعن بشید که نسخه ای که دانلود می کنید با نسخه فعلی نصب شده یکی باشه.

 

32- دلیل خطای The procedure entry point X could not be located in the dynamic link library php7.dll عدم سازگاری php.exe با php7.dll هستش... برای حل این مشکل:

- پکیچ کامل php رو مجدداً دانلود و نصب کنید.

- یا Visual C++ Redistributable 2015 نسخه 64 و 32 بیتی رو دانلود و نصب کنید.

 

33- نکته جزیی: هرگز بیش از یک اکستنشن برای cache کردن OpCode استفاده نکنید، چون باعث فساد کش و کرش PHP خواهد شد.

 

34- توسط VisualPHPUnit میتونید PHPUnit رو با رابط گرافیکی تجربه کنید!

 

35- نکته جزیی: فراموش نکنید که collation ها در MySQL فقط بر روی دیتای نوع string (مثل VARCHAR, CHAR, ENUM, SET, TEXT...) تاثیر دارن و نه دیتای نوع number (مثل INT, FLOAT, DEC).

 

36- همیشه در محیط production مقدار تنظیم opcache.validate_timestamps در فایل php.ini رو 0 قرار بدید.

توجه: درصورت تغییر فایلهای PHP در سرور(محیط production) باید وبسرور رو ریستارت کنید تا تغییرات اعمال بشن.

 

37- نکته جزیی: در HTML4 به قبل، charset صفحات HTML باید در 512 بایت اول نوشته و تنظیم بشه اما در HTML5 میتونه در 1024 بایت اول نوشته بشه. یعنی در HTML4:

<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>

و در HTML5:

<head>
<title>My Website</title>
<meta charset="UTF-8">

 

38- نکته جزیی: آیا میدونید استفاده از type-casting نوع object از stdClass بهینه تر و با سرعت بیشتری همراهه؟

 

39- هنگام مقایسه رشته ها بجای استفاده از دستور LOWER() در زبان SQL، کافیست collation جدول یا فیلد رو به *_ci تغییر بدید... درغیر اینصورت از collation های *_bin استفاد کنید.

 

40- ​برای تنظیم بهتر مقدار تنظیم opcache.memory_consumption در فایل php.ini (برای استفاده شخصی) میتونید دستور opcache_get_status(TRUE) رو در آخرین فایل سورس پروژه تون اجرا و نسبت به خروجی(memory_consumption) داده شده تنظیمش کنید... 

نکته: این مقدار در سرور واقعی باید روی چند گیگابایت تنظیم بشه.

توجه: درصورتی که از code generator یا سیستم کش مبتنی بر فایل PHP استفاده می کنید(مثل Symfony, Doctrine Annotations یا FLOW3) باید بیش از مقدار مورد نظرتون opcache.memory_consumption رو تنظیم کنید.

 

۹۶/۱۰/۲۱

نظرات (۵)

It's an awesome piece of writing in support of all the online
people
۲۲ دی ۹۶ ، ۱۵:۵۳ فاروق کریمی زاده
یعنی زبان انگلیسی ساخته شده برای اصطلاحات فنی و فارسی برای هنری/ادبی؟
البته منظور شما این نبود اما یک زمانی هم زبان فارسی و عربی اصطلاحات فنی داشتند و اونها ترجمه میکردند، همزمان زبان فارسی یک زبان هنری/ادبی هم بود.
۲۲ دی ۹۶ ، ۱۴:۵۸ فاروق کریمی زاده
مشکلی نداره، فقط همون انگلیسی سنگین‌تر میبود!
البته مشکل از شما نیست کلا همینجوریه، یه مقدار که بحث فنی بشه دیگه زبان فارسی جوابگو نیست.
البته multi-thread رو میتونستی چند ریسمانی بنویسی(توی یک کتاب دیدم)
پاسخ:
موافقم

به هرحال زبان فارسی یک زبان ادبی/هنری هستش، برای همین اصطلاحات "جدید" فنی داخلش جایگاهی نداره
برای همین منم سعی میکنم از همون واژه های انگلیسی استفاده کنم و ترجمه نکنم
۲۲ دی ۹۶ ، ۱۲:۰۰ فرهاد حسن پور
ممنون یوشا نکات ریز اما مهمی بودند.
تشکر
۲۱ دی ۹۶ ، ۲۲:۲۹ فاروق کریمی زاده
خودت یکبار ۱ رو بخون.
کاربران بیان میتوانند بدون نیاز به تأیید، نظرات خود را ارسال کنند.
اگر قبلا در بیان ثبت نام کرده اید لطفا ابتدا وارد شوید، در غیر این صورت می توانید ثبت نام کنید.
شما میتوانید از این تگهای html استفاده کنید:
<b> یا <strong>، <em> یا <i>، <u>، <strike> یا <s>، <sup>، <sub>، <blockquote>، <code>، <pre>، <hr>، <br>، <p>، <a href="" title="">، <span style="">، <div align="">