الدوال المساعدة والدوال العامة

الدوال المساعدة السبع والعشرون ضمن فضاء الأسماء، وطريقة استيرادها، والتفعيل الاختياري Globals::register() الذي يضيف أسماء عامة قصيرة دون أن يستبدل أسماءك.

في هذه الصفحة
  1. لماذا توجد الدوال المساعدة داخل فضاء أسماء
  2. استخدام الدوال المساعدة
  3. جميع الدوال المساعدة
    1. التقاويم
    2. الأرقام والأعداد
    3. النصوص
    4. التحقق من الصحة: نعم/لا
    5. التحقق من الصحة: نتيجة منظَّمة
    6. العطل وأوقات الصلاة
  4. الأسماء العامة الاختيارية: Globals::register()
    1. مثال على التعارض
  5. أي أسلوب أختار؟

لماذا توجد الدوال المساعدة داخل فضاء أسماء#

أسماء مثل is_mobile() أو ordinal() أو to_english() قصيرة وعامة. ولا توجد في PHP طريقة «لاستبدال» دالة عامة: إذا أعلنت حزمتان (أو تطبيقك وإحدى الحزم) عن الاسم العام نفسه، فإن الإعلان الثاني خطأ فادح. لذلك قد تعطّل المكتبة التي تعرّف دوالَّ عامة دون شرط تطبيقًا كان يعمل قبل تثبيتها.

يتجنب RTLY-Kit هذه المشكلة بحكم التصميم:

  • الدوال المساعدة السبع والعشرون كلها معرّفة في فضاء الأسماء RtlyKit. يحمّلها Composer تلقائياً، ولا يمكن أن تتعارض مع أي شيء.
  • الأسماء العامة القصيرة اختيارية عبر \RtlyKit\Globals::register()، التي لا تعرّف إلا الأسماء التي ما زالت حرة.
  • مزوّد الخدمة في Laravel لا يسجّل دوالَّ عامة هو الآخر. راجع إعداد Laravel.

استخدام الدوال المساعدة#

استورد ما تحتاجه بـ use function ثم استدعِه باسمه القصير. أو استدعِه بالاسم الكامل:

use function RtlyKit\jdate;
use function RtlyKit\is_national_code;

echo jdate('2025-03-21')->format('Y/m/d');       // 1404/01/01
var_dump(is_national_code('0013542419'));         // bool(true)
echo \RtlyKit\to_persian_digits(1404);            // ۱۴۰۴

// عدة دوال دفعة واحدة (use المجمّع في PHP):
use function RtlyKit\{hdate, hebrew_date, number_to_words};
echo hdate('2025-03-21')->format('Y/m/d');       // 1446/09/21
echo hebrew_date('2025-03-21')->format('Y/m/d'); // 5785/06/21
echo number_to_words(1404);                       // یک هزار و چهارصد و چهار

الدوال المساعدة أغلفة رقيقة: كل منها يستدعي الصنف المقابل، فيمكنك دائمًا استخدام الصنف مباشرة عندما تحتاج إلى تحكم أكبر (مثل Jalali::create() مع منطقة زمنية).

جميع الدوال المساعدة#

أنواع المعاملات وأنواع الإرجاع هي نفسها الموجودة في الشيفرة المصدرية تمامًا. المدخلات من النوع mixed لا ترمي استثناءً أبدًا: المدخل غير الصالح يعطي ببساطة false أو Result غير صالح.

التقاويم#

الدالةالتوقيعتفوّض إلى
jdatejdate(DateTimeInterface|string|int|null $time = null, ?DateTimeZone $timezone = null): JalaliJalali::make()، راجع التقويم الجلالي
hdatehdate(DateTimeInterface|string|int|null $time = null, ?DateTimeZone $timezone = null): HijriHijri::make()، راجع التقويم الهجري
hebrew_datehebrew_date(DateTimeInterface|string|int|null $time = null, ?DateTimeZone $timezone = null): HebrewHebrew::make()، راجع التقويم العبري

الأرقام والأعداد#

الدالةالتوقيعمثال
to_persian_digits(string|int|float $value): stringto_persian_digits(1404) تعطي ۱۴۰۴
to_english_digits(string $value): stringto_english_digits('۱۴۰۴') تعطي 1404
to_persian(string|int|float $value): stringاسم مختصر بديل لـ to_persian_digits؛ to_persian('12.5') تعطي ۱۲.۵
to_english(string $value): stringاسم مختصر بديل لـ to_english_digits؛ to_english('٣٤') تعطي 34
number_to_words(int|float|string $number, string $locale = 'fa'): stringnumber_to_words(25, 'ar') تعطي خمسة وعشرون
format_number(int|float|string $number): stringformat_number(1234567) تعطي ۱٬۲۳۴٬۵۶۷
ordinal(int|float $number): stringordinal(3) تعطي سوم

انظر الأرقام والتنسيق والأعداد بالكلمات والأعداد بالحروف العربية. الدالة number_to_words() لا تأخذ خيارات؛ وللجنس والحالة الإعرابية والحركات استدعِ NumberToWords::convert() مع ArabicOptions.

النصوص#

الدالةالتوقيعمثال
normalize_text(string $text): stringnormalize_text('كتاب ي') تعطي کتاب ی (الكاف والياء العربيتان تصبحان فارسيتين)
contains_rtl(string $text): boolcontains_rtl('abc سلام') تعطي true
text_direction(string $text): stringtext_direction('سلام') تعطي rtl، وtext_direction('hello') تعطي ltr

راجع أدوات النصوص.

التحقق من الصحة: نعم/لا#

كل منها يُرجع bool ويقبل mixed.

الدالةالتوقيعمثال
is_national_code(mixed $value): boolis_national_code('0013542419') تعطي true
is_sheba(mixed $value): boolis_sheba('IR062960000000100324200001') تعطي true
is_bank_card(mixed $value): boolis_bank_card('6037997535328737') تعطي true
is_mobile(mixed $value): boolis_mobile('09123456789') تعطي true
is_postal_code(mixed $value): boolis_postal_code('1676543210') تعطي true
is_vehicle_plate(mixed $value): boolis_vehicle_plate('12ب345-67') تعطي true

التحقق من الصحة: نتيجة منظَّمة#

كل منها يُرجع RtlyKit\Validation\Result بالدوال valid() وinvalid() وisValid() وerrors() وdetails(). راجع نظرة عامة على أدوات التحقق.

الدالةالتوقيع
validate_national_code(mixed $value): Result
validate_sheba(mixed $value): Result
validate_bank_card(mixed $value): Result
validate_mobile(mixed $value): Result
validate_postal_code(mixed $value): Result
validate_vehicle_plate(mixed $value): Result
$r = \RtlyKit\validate_national_code('1234567890');
var_dump($r->isValid());   // bool(false)

العطل وأوقات الصلاة#

الدالةالتوقيعملاحظات
is_iran_holiday(Jalali|int $year, ?int $month = null, ?int $day = null): boolتغلّف IranHolidays::isHoliday() فتستعمل تقويم العطل الافتراضي؛ is_iran_holiday(1404, 11, 22) تعطي true. انظر العطل وتقويم العطل القابل للتعديل.
prayer_times(string $city = 'tehran', string $method = 'Tehran'): arrayأوقات اليوم بحسب المنطقة الزمنية للمدينة، بالشكل {"fajr", "sunrise", "dhuhr", "asr", "maghrib", "isha"}. المدينة أو الطريقة المجهولة ترمي InvalidPrayerConfigException. راجع أوقات الصلاة.

المجموع إذن 3 + 7 + 3 + 6 + 6 + 2 = 27 دالة مساعدة، وهي القائمة نفسها التي تحملها Globals::NAMES.

الأسماء العامة الاختيارية: Globals::register()#

إذا كنت تفضّل الأسماء العامة القصيرة (مثلًا في قاعدة شيفرة قديمة أو محرك قوالب أو سكربت)، فاستدعِ هذا مرة واحدة أثناء الإقلاع:

$skipped = \RtlyKit\Globals::register();

الضمانات التي تقدمها:

  • لا تُعرَّف إلا الأسماء الحرة. لا يُعرَّف الاسم إلا إذا لم توجد دالة بهذا الاسم. ولا تُستبدل دالة موجودة أبدًا.
  • تُبلغ عمّا تخطّته. القيمة المرجعة list<string> بالأسماء التي لم تُعرَّف لأن دالة أخرى تستخدمها. القائمة الفارغة تعني أن كل شيء سُجّل.
  • لا ترمي استثناءً أبدًا ولا تسبب خطأ إعادة إعلان، مهما كان الوضع.
  • إعادة الاستدعاء آمنة (idempotent). استدعِها كما تشاء. الاسم الذي هو تعريف RTLY-Kit السابق نفسه لا يُعدّ متخطًّى، فيعطي الاستدعاء الثاني القائمة نفسها التي أعطاها الأول.
  • الدوال ضمن فضاء الأسماء تعمل دائمًا، سواء تُخطّي اسم عام أم لا.
  • \RtlyKit\Globals::NAMES ثابت يسرد الأسماء السبعة والعشرين كلها.

مثال على التعارض#

لدى التطبيق دالته الخاصة is_mobile() (فحص user-agent). الحزمة لا تعطّلها ولا تستبدلها، وتخبرك بذلك:

require 'vendor/autoload.php';

// التطبيق يملك أصلاً دالة عامة بالاسم نفسه.
function is_mobile(string $ua): bool { return str_contains($ua, 'Mobi'); }

$skipped = \RtlyKit\Globals::register();
var_dump($skipped);
// array(1) { [0]=> string(9) "is_mobile" }

var_dump(is_mobile('Mozilla/5.0 (iPhone) Mobile'));   // bool(true)   دالة التطبيق نفسه
var_dump(\RtlyKit\is_mobile('09123456789'));           // bool(true)   فحص رقم الجوال الإيراني، متاح دائماً
echo jdate('2025-03-21')->format('Y/m/d'), "\n";       // 1404/01/01   اسم حر: سُجّل كدالة عامة
var_dump(\RtlyKit\Globals::register());                // آمنة عند التكرار: القائمة نفسها، array(1) { [0]=> string(9) "is_mobile" }

السياسة المعقولة هي تسجيل القائمة في السجل ثم المتابعة:

$skipped = \RtlyKit\Globals::register();
if ($skipped !== []) {
    error_log('RTLY-Kit globals skipped: ' . implode(', ', $skipped));
}
ملاحظة. إعلانات الدوال في المستوى الأعلى من ملف PHP تُرفَع إلى أعلى الملف (hoisting)، فالدالة العامة المعلنة بعد الاستدعاء في الملف نفسه تُحسب مع ذلك «معرّفة مسبقًا». إذا كان اسم ما مهمًا لك، فاعلنه قبل استدعاء register()، أو اكتفِ بالدالة ضمن فضاء الأسماء.

أي أسلوب أختار؟#

  • المكتبات والتطبيقات الجديدة: الاستيراد من فضاء الأسماء (use function RtlyKit\jdate;). فهو صريح وسهل البحث ولا يسبب تعارضًا.
  • الشيفرة القديمة والسكربتات والقوالب: استدعِ Globals::register() مرة واحدة وأبقِ على الأسلوب القصير القديم.
  • Laravel: كلاهما مناسب؛ فمزوّد الخدمة لا يضيف دوالَّ عامة، فاستدعِ Globals::register() في AppServiceProvider::register() إن أردتها، أو استورد الدوال ضمن فضاء الأسماء في Blade وفي الأصناف.