در این صفحه
دو سبک برای شکست#
هر تابع RTLY-Kit یکی از این دو سبک را دارد. پس همیشه میدانید کجا باید مراقب باشید:
- اعتبارسنجها هیچوقت خطا پرتاب نمیکنند.
NationalCode،Sheba،BankCard،Mobile،PostalCodeوVehiclePlate(و توابع کمکیis_*وvalidate_*) هر مقداری را قبول میکنند و باfalseیا یکResultنامعتبر جواب میدهند. مرور اعتبارسنجها را ببینید. - بقیهٔ توابع خطا پرتاب میکنند. برای ورودیای که نمیپذیرند، یک
RtlyKit\Exceptions\RtlyKitException(یا زیرکلاسش) میگیرید. برای ورودی بد،TypeErrorوValueErrorوDateMalformed*خود PHP بیرون نمیآید. اگر دیدید، باگ کتابخانه است. لطفاً گزارش بدهید.
سلسلهمراتب خطاها#
\InvalidArgumentException
└─ RtlyKit\Exceptions\RtlyKitException implements RtlyKitThrowable
├─ InvalidDateException
├─ InvalidNumberException
├─ InvalidPrayerConfigException
└─ UnsupportedLocaleException
RtlyKitThrowable یک اینترفیس نشانه است که getErrorCode(): ErrorCode و getContext(): array را دارد. اگر آن را (یا RtlyKitException را) بگیرید، با یک catch کل کتابخانه را پوشش دادهاید. چون RtlyKitException از \InvalidArgumentException ارث میبرد، کدهای قدیمی که catch (\InvalidArgumentException) یا catch (\LogicException) دارند هنوز کار میکنند.
| خطا | چه وقت پرتاب میشود |
|---|---|
InvalidDateException | تاریخ غیرممکن، سال بیرون از بازه، رشتهٔ خالی یا غیرقابل خواندن، مقدار غیرمنطقی در add*() و sub*()، زمان یونیکس بیرون از بازه، الگوی قالببندی خیلی بلند، گزینهٔ نادرست در HolidayCalendar |
InvalidNumberException | ورودی غیرعددی یا اعشاری، NaN و INF، ورودی یا عدد خیلی بزرگ، واژهٔ عددی ناشناخته، گزینهٔ نادرست برای عدد به حروف عربی |
InvalidPrayerConfigException | روش محاسبه یا شهر ناشناخته، ضریب عصر نامعتبر، تنظیم دستی نادرست در withTune() |
UnsupportedLocaleException | زبانی که تابع پشتیبانی نمیکند (مثلاً number_to_words(5, 'de')) |
خود RtlyKitException | آرگومانهای نامعتبر دیگر، مثل جداکنندهٔ بد یا متن UTF-8 خراب در Slugify::make() یا نبودن جدول داده |
کدهای خطا#
متن پیام برای آدمهاست و ممکن است در هر نسخه عوض شود. بخش پایدار کد خطا است: یک enum رشتهای به نام ErrorCode. نام caseها و مقدارهایش جزو API عمومی است (پایداری API).
| Case | مقدار | معنا |
|---|---|---|
InvalidArgument | invalid_argument | آرگومان نامعتبری که کد دقیقتری ندارد |
InvalidDate | invalid_date | تاریخ یا زمان نادرست، غیرممکن یا غیرقابل خواندن (ماه ۱۳، ۳۰ اسفند در سال غیرکبیسه، 'not a date'، رشتهٔ خالی) |
DateOutOfRange | date_out_of_range | سال، تاریخ، زمان یونیکس یا مقدار add*() و sub*() بیرون از بازه (سقفها) |
InvalidNumber | invalid_number | مقدار را نمیشود عدد (صحیح) خواند |
NumberTooLarge | number_too_large | عدد از بیشترین مقدار پشتیبانیشده بزرگتر است |
NonFiniteNumber | non_finite_number | جایی که عدد متناهی لازم است، NaN یا INF داده شده |
InvalidNumberWords | invalid_number_words | واژهٔ عددی ناشناخته یا نادرست در NumberToWords::fromWords() |
InputTooLong | input_too_long | ورودی رشتهای از سقف مشخصشده بلندتر است |
InvalidPrayerConfig | invalid_prayer_config | شهر، روش محاسبه، ضریب عصر یا تنظیم دستی نادرست |
UnsupportedLocale | unsupported_locale | زبانی که پشتیبانی نمیشود |
DataUnavailable | data_unavailable | یک جدول داده در بسته نیست یا خراب است (مشکل بستهبندی است، نه اشتباه کاربر) |
Result::errors() میدهد (invalid_format، invalid_checksum، invalid_type و ...) رشتههای ساده و مخصوص اعتبارسنجها هستند، نه caseهای ErrorCode. این enum فقط برای خطاهای پرتابشده است.خواندن کد و context#
هر خطای کتابخانه getErrorCode() و getContext() دارد. context آرایهای از اطلاعات ماشینخوان دربارهٔ شکست است (یک سقف، زبان پشتیبانینشده، نام آرگومان). چیز محرمانهای در آن نیست و ممکن است خالی باشد. این اسکریپت پنج ورودی بد را به number_to_words() میدهد:
<?php
require __DIR__.'/vendor/autoload.php';
use function RtlyKit\number_to_words;
use RtlyKit\Exceptions\RtlyKitThrowable;
foreach ([1.5, NAN, 'abc', str_repeat('9', 22), str_repeat('1', 5000)] as $input) {
try {
number_to_words($input);
} catch (RtlyKitThrowable $e) {
echo (new ReflectionClass($e))->getShortName(), ' ',
$e->getErrorCode()->value, ' ',
json_encode($e->getContext()), "\n";
}
}
// InvalidNumberException invalid_number []
// InvalidNumberException non_finite_number []
// InvalidNumberException invalid_number []
// InvalidNumberException number_too_large {"limit":"10^21 - 1"}
// InvalidNumberException input_too_long {"limit":4096}
الگوهای گرفتن خطا#
بر اساس کد تصمیم بگیرید، نه متن پیام. از match با شاخهٔ default استفاده کنید، چون ممکن است در نسخهٔ فرعی caseهای تازه اضافه شود.
<?php
require __DIR__.'/vendor/autoload.php';
use RtlyKit\Calendar\Jalali;
use RtlyKit\Exceptions\{ErrorCode, InvalidDateException, RtlyKitThrowable};
function category(RtlyKitThrowable $e): string
{
return match ($e->getErrorCode()) {
ErrorCode::InvalidDate, ErrorCode::DateOutOfRange => 'date',
ErrorCode::InputTooLong => 'too-long',
default => 'other',
};
}
try {
Jalali::create(1404, 13, 1); // ماه ۱۳ وجود ندارد
} catch (RtlyKitThrowable $e) {
echo category($e), "\n"; // date
}
$e = InvalidDateException::because(ErrorCode::DateOutOfRange, 'Year is out of range', ['year' => 99999]);
echo $e->getErrorCode()->value, ' ', json_encode($e->getContext()), "\n";
// date_out_of_range {"year":99999}
try {
Jalali::create(1404, 13, 1);
} catch (\InvalidArgumentException $e) { // catch قدیمی هنوز کار میکند
echo get_class($e), ' ', $e instanceof RtlyKitThrowable ? 'is RtlyKitThrowable' : '', "\n";
// RtlyKit\Exceptions\InvalidDateException is RtlyKitThrowable
}
RtlyKitException::because(ErrorCode, string $message, array $context = [], ?Throwable $previous = null) سازندهٔ خود کتابخانه برای ساختن خطا با کد مشخص است. میتوانید برای خطاهای خودتان هم به کار ببرید، ولی خطاهای ساختهشده توسط شما جزو تعهد کتابخانه نیست.
در لاگ، کد و context را بنویسید، نه متن پیام را:
catch (RtlyKitThrowable $e) {
error_log($e->getErrorCode()->value.' '.json_encode($e->getContext()));
}
چه چیزی هیچوقت خطا نمیدهد#
اعتبارسنجها هر مقدار PHP را قبول میکنند. برای ورودی بد، با هر نوع و هر اندازه، خطا پرتاب نمیکنند:
<?php
require __DIR__.'/vendor/autoload.php';
use function RtlyKit\validate_national_code;
use RtlyKit\Validation\Sheba;
var_dump(Sheba::isValid(null)); // bool(false)
echo json_encode(validate_national_code([])->errors()), "\n"; // ["invalid_type"]
echo json_encode(validate_national_code(str_repeat('1', 5000))->errors()), "\n"; // ["input_too_long"]
echo json_encode(validate_national_code('0013542418')->errors()), "\n"; // ["invalid_checksum"]
var_dump(validate_national_code('0013542419')->isValid()); // bool(true)
| ورودی اعتبارسنج | نتیجه |
|---|---|
| رشته تا ۴۰۹۶ بایت | طبق معمول بررسی میشود (رقم فارسی و عربی قبول است) |
int و float صحیح و متناهی | به رشته تبدیل و بعد بررسی میشود (صفرهای اول int از قبل از بین رفتهاند) |
null، bool، آرایه، شیء، NaN، INF، float اعشاری | نامعتبر، با invalid_type |
| رشتهٔ بیشتر از ۴۰۹۶ بایت | نامعتبر، با input_too_long |
| UTF-8 خراب | نامعتبر (معمولاً invalid_format) |
قانونهای اعتبارسنجی Laravel و Globals::register() هم همین اصل را دارند. قانونها یک مقدار بولی میدهند و Globals::register() هیچوقت خطا پرتاب نمیکند (نامهای ردشده را برمیگرداند).
سقف ورودیها#
هر جا متن نامطمئن بیاید سقف اندازه دارد، تا ورودی مخرب هزینهٔ زیادی نسازد. عبور از سقف input_too_long میدهد، به شکل خطای پرتابشده یا خطای اعتبارسنج. فهرست کامل در سقفها است.
| کجا | سقف | اگر ردش کنید |
|---|---|---|
| اعتبارسنجها | ۴۰۹۶ بایت برای هر رشته | Result نامعتبر با input_too_long |
ورودی رشتهای NumberToWords::convert() و fromWords() و Format | ۴۰۹۶ بایت برای هر رشته | InvalidNumberException |
Format::withSeparator() و format_number() | ۱۰۰۰ نویسه در عدد اعشاری ساده | InvalidNumberException |
جداکنندهٔ Slugify::make() | ۶۴ بایت، UTF-8 معتبر | RtlyKitException |
الگوی format() (جلالی، هجری، عبری) | ۲۵۶ بایت (MAX_FORMAT_LENGTH در هر کلاس) | InvalidDateException |
قاعدهٔ بازهٔ تقویم#
هر راه ورود به تقویم (make، create، createFromFormat، زمان یونیکس، add* و sub*، توابع کمکی و ماکروهای Carbon) یا تاریخ معتبر میدهد یا InvalidDateException. چیزی سرریز نمیکند و خطای از نوع دیگری هم نمیآید. بازهها: جلالی -۶۲۰ تا ۹۳۷۷، هجری ۱ تا ۹۶۶۵ و عبری ۳۷۶۲ تا ۱۳۷۵۹، که همه در سالهای میلادی ۱ تا ۹۹۹۹ جا میشوند. سقفها را ببینید.
یک نمونهٔ کامل#
use function RtlyKit\jdate;
use function RtlyKit\number_to_words;
use RtlyKit\Exceptions\InvalidDateException;
use RtlyKit\Exceptions\RtlyKitThrowable;
try {
$date = jdate($userInput);
$words = number_to_words($userAmount);
} catch (InvalidDateException $e) {
echo "لطفاً تاریخ معتبر وارد کنید.\n";
} catch (RtlyKitThrowable $e) {
error_log($e->getErrorCode()->value.' '.json_encode($e->getContext()));
}