Skip to the guide
All guides

Laravel setup

How RTLY-Kit plugs into Laravel. Package auto-discovery, what the service provider registers, the Jalali facade, the optional config file and the fa, en and ar validation messages.

app RTLY-Kit 0.2.0checked reading 7 minutes

On this page

Install and auto-discovery

You need nothing beyond Composer. The package lists its provider and facade alias in composer.json under extra.laravel. Laravel's package discovery registers them on the next composer install or composer update.

Bash
composer require tsi/rtly-kit

The integration uses the Laravel components illuminate/support, illuminate/translation, illuminate/validation and illuminate/database, which a Laravel application already has. The test suite runs against these components in versions 11, 12 and 13 (Laravel 13 needs PHP 8.3 or newer). The library itself needs only PHP 8.2 and works without Laravel.

Note. The integration tests use the real container, translator, validation factory and Eloquent model classes, not a full application skeleton. The code samples on these pages were run the same way.

If your application turns discovery off for this package ("dont-discover": ["tsi/rtly-kit"]), register the provider yourself. In Laravel 11 and later, add it to bootstrap/providers.php:

PHP
return [
    App\Providers\AppServiceProvider::class,
    RtlyKit\Laravel\RtlyKitServiceProvider::class,
];

On older application layouts, add the same class to the providers array in config/app.php. The config file is optional (see Configuration), and there is no migration.

What the service provider does

RtlyKit\Laravel\RtlyKitServiceProvider has these jobs:

  • register() binds a singleton under the container key rtly-kit.jalali , a RtlyKit\Laravel\JalaliFactory . This object stands behind the facade. It also merges the default rtly-kit config and binds RtlyKit\Holiday\HolidayCalendar as a singleton, built from rtly-kit.holidays the first time it is requested.
  • boot() installs the Carbon macros (see Carbon macros ), loads the package translations under the rtly-kit namespace, offers the config file for publishing, and registers the validation rules when the container has a validation factory (see Validation and the cast ).

Note. The provider registers no global functions. A test boots it and checks that none of the 27 short helper names exists afterwards. If you want the short global names, call \RtlyKit\Globals::register() yourself. See Helpers and globals.

If the container's validator is not an Illuminate\Validation\Factory (a custom replacement), the provider leaves it alone and skips the rules.

The Jalali facade

The alias Jalali (class RtlyKit\Laravel\Facades\Jalali) forwards to the factory. It has four methods that mirror the static constructors of RtlyKit\Calendar\Jalali:

PHP
use RtlyKit\Laravel\Facades\Jalali;

echo Jalali::create(1404, 1, 1)->format('Y/m/d l');   // 1404/01/01 جمعه
echo Jalali::make('2025-03-21')->toDateString();       // 1404/01/01
echo get_class(Jalali::now());                         // RtlyKit\Calendar\Jalali
// Jalali::today() is also available

Every call returns an ordinary immutable Jalali object, so everything on the Jalali calendar page applies. The factory is a singleton, so a repeated app('rtly-kit.jalali') returns the same instance.

The facade is optional. In classes you can import the class directly or use the namespaced helper \RtlyKit\jdate(). In tests there is nothing to fake, because the factory keeps no state.

Translations: fa, en, ar

The provider calls loadTranslationsFrom() with the rtly-kit namespace. The messages live in rtly-kit::validation.* and follow the application locale. There are three complete sets, one line per rule:

Keyfaenar
national_code:attribute کد ملی معتبر نیست.The :attribute is not a valid Iranian national code.:attribute ليس رقماً وطنياً إيرانياً صالحاً.
sheba:attribute شماره شبا معتبر نیست.The :attribute is not a valid Iranian Sheba (IBAN).:attribute ليس رقم شبا (IBAN) إيرانياً صالحاً.
bank_card:attribute شماره کارت بانکی معتبر نیست.The :attribute is not a valid Iranian bank card.:attribute ليس رقم بطاقة مصرفية إيرانية صالحاً.
iran_mobile, mobile:attribute شماره موبایل معتبر نیست.The :attribute is not a valid Iranian mobile number.:attribute ليس رقم هاتف محمول إيرانياً صالحاً.
postal_code:attribute کد پستی معتبر نیست.The :attribute is not a valid Iranian postal code.:attribute ليس رمزاً بريدياً إيرانياً صالحاً.
vehicle_plate:attribute پلاک خودرو معتبر نیست.The :attribute is not a valid Iranian vehicle plate.:attribute ليست لوحة مركبة إيرانية صالحة.

The Arabic file is resources/lang/ar/validation.php in the package, with the same keys. The same rule in three locales:

PHP
// field named national_code, value '1234567890', rule national_code
// locale fa: national code کد ملی معتبر نیست.
// locale en: The national code is not a valid Iranian national code.
// locale ar: national code ليس رقماً وطنياً إيرانياً صالحاً.

Laravel turns the field name national_code into the label "national code". Give the field a proper label in the attributes translations to get a natural sentence.

If the active locale has no line, Laravel's normal fallback locale (app.fallback_locale) is used. If no translation is found at all, the built-in English text is the last resort.

Overriding a message

You do not need to publish anything. Choose the way that fits, from the narrowest to the widest:

  1. Per validation call. Pass custom messages to the validator or to $request->validate() in the usual way, for example the key postal_code or zip.postal_code . A custom message always wins.
  2. For the whole application. Add the line of the rule to your own lang/fa/validation.php . The key is the rule name, for example 'sheba' => 'شبای :attribute اشتباه است.' . The validation.<rule> line of the application is preferred over the package line.
  3. Replace the package texts. Create lang/vendor/rtly-kit/fa/validation.php (or en , ar ). Laravel's standard vendor override loads it over the package file. You need only the keys you change.

Output of options 2 and 3 with the locale fa:

PHP
// lang/vendor/rtly-kit/fa/validation.php  ->  ['national_code' => 'کد ملی :attribute درست نیست.']
// lang/fa/validation.php                  ->  ['sheba' => 'شبای :attribute اشتباه است.']
// custom message on the call              ->  ['postal_code' => 'کد پستی :attribute نادرست']
//
// national_code: کد ملی x درست نیست.
// sheba:         شبای x اشتباه است.
// postal_code:   کد پستی x نادرست

The field in these examples is named x, which is why x appears in the sentences. In a real form, set readable labels in the attributes array of your validation.php.

Configuration

The config file is optional. Without it, everything works with the defaults. Publish it when you want to adjust holidays:

Bash
php artisan vendor:publish --tag=rtly-kit-config

This creates config/rtly-kit.php. Today it has one block, holidays: an Islamic-date offset, real Hijri month starts, extra and removed holidays, and a switch for the official data. The options are explained, with a short tutorial, on the Holiday calendar page.

Apart from that, behaviour is set by the library and the locale of the application. The library reads the default time zone from PHP (date_default_timezone_get()). Laravel sets it from config('app.timezone'), so Jalali::now() follows your application time zone.

Good to know. If the validation factory is not bound when the provider boots, the rules are not registered, and they are not added later. This only happens in unusual bootstraps, for example a console-only container without the validation service.

Next: validation rules and the Eloquent cast.