darkghosthunter / lararut
RutUtils integration for Laravel
Fund package maintenance!
Ko Fi
paypal.me/darkghosthunter
Requires
- php: >=7.4
- darkghosthunter/rut-utils: ^3.0.1
- illuminate/support: ^7.0||^8.0
- illuminate/validation: ^7.0||^8.0
Requires (Dev)
- doctrine/dbal: ^2.13.1||^3.1
- mockery/mockery: ^1.4
- orchestra/testbench: ^5.0||^6.0
- phpunit/phpunit: ^9.5.4
README
Lararut
This package integrates the RutUtils package, allowing manipulation of RUTs in your PHP project, with Laravel.
Additionally, it includes 6 new rules to validate RUT data conveniently.
Check the RutUtils documentation to see all the available methods to create, generate and validate RUTs.
Important This package does not validate if the RUT is from a real person, only if it's valid. If you need that kind of functionality, you should let your application interact with the pseudo-official API.
Requirements
- PHP 7.4 or 8.0
- Laravel 7.x or 8.x
Check older releases for older Laravel versions.
Installation
Fire up Composer and require it into your project:
composer require darkghosthunter/lararut
Validation rules
This package includes handy rules to validate RUTs incoming from your frontend. Compared to prior versions, they're are more easy to use and understand.
All validation rules messages are translated. You can add your own translation by publishing the files:
php artisan vendor:publish --provider="DarkGhostHunter\Lararut\LararutServiceProvider" --tag="translations"
Database rules will automatically normalize
K
verification digit to search in the database.
rut
This checks if the RUT being passed is a valid RUT string. This automatically cleans the RUT from anything except numbers and verification digit, and then checks if the resulting RUT is valid.
<?php use Illuminate\Support\Facades\Validator; $validator = Validator::make([ 'rut' => '14328145-0' ], [ 'rut' => 'rut' ]); echo $validator->fails(); // false $validator = Validator::make([ 'rut' => '65.00!!!390XXXX2' ], [ 'rut' => 'rut' ]); echo $validator->fails(); // false
This may come handy in situations when the user presses a wrong button into an RUT input, so no need to ask the user to add hyphen or dots. Afterwards, you can use Rut::make()
to create a new Rut instance from that input.
<?php use DarkGhostHunter\RutUtils\Rut; $rut = Rut::make(request()->input('rut'));
The rule also accepts an array
of RUTs. In that case, rut
will return true if all of the RUTs are valid, and false if at least one is invalid. This may come in handy when a user is registering a lot of people into your application.
<?php use Illuminate\Support\Facades\Validator; $validator = Validator::make([ 'rut' => ['14328145-0', '12.343.580-K', 'thisisnotarut'] ], [ 'rut' => 'rut' ]); echo $validator->fails(); // true $validator = Validator::make([ 'rut' => ['14328145-0', '12.343.580-K', '20881410-9'] ], [ 'rut' => 'rut' ]); echo $validator->fails(); // false
rut_strict
This works the same as rut
, but it will validate RUTs that are also using the correct RUT format: with thousand separator and a hyphen before the Validation Digit. This allows you to bypass any sanitization afterwards.
Since it does not cleans the value, it will return false
even if there is one misplaced character or an invalid one.
<?php use Illuminate\Support\Facades\Validator; $validator = Validator::make([ 'rut' => '14.328.145-0' ], [ 'rut' => 'rut_strict' ]); echo $validator->fails(); // false $validator = Validator::make([ 'rut' => '1.4328.145-0' ], [ 'rut' => 'rut_strict' ]); echo $validator->fails(); // true
This rule also accepts an array
of RUTs. In that case, rut_strict
will return true if all of the RUTs are properly formatted and valid.
<?php use Illuminate\Support\Facades\Validator; $validator = Validator::make([ 'rut' => ['1.4328.145-0', '12.343.580-K'] ], [ 'rut.*' => 'required|rut_strict', ]); echo $validator->fails(); // true
rut_equal
This will check if the RUT is equal to another RUT, like for example, the authenticated User's RUT or from another data resource. Both will be cleaned before the validation procedure.
This is handy when, for example, you need to cross-reference the RUT against other external services or API.
<?php use Illuminate\Support\Facades\Validator; $validator = Validator::make([ 'rut' => '12343580-K' ], [ 'rut' => 'required|rut_equal:12343580K' ]); echo $validator->fails(); // false
You can use an array
of RUTs to compare, which saves you to do multiple rut_equal
. In these cases, rut_equal
will return true if all of the RUTs are valid and equal to each other.
<?php use Illuminate\Support\Facades\Validator; $validator = Validator::make([ 'rut' => '12.343.580-K' ], [ 'rut' => 'required|rut_equal:12343!580K,12.343.580-K' ]); echo $validator->fails(); // false
If you need to compare two or more RUTs in your input, you're better using the
same
validation rule. In case of confirming a RUT, use theconfirmed
validation rule.
rut_exists
(Database)
Instead of using Laravel's exists, you can use rut_exists
in case your database has separated columns for the RUT Number and Verification Digit.
For this to work you need to set the table to look for, the RUT number column and RUT verification digit column, otherwise the rule will guess the column names by the attribute key and appending _num
and _vd
, respectively.
<?php use Illuminate\Support\Facades\Validator; $validator = Validator::make([ 'rut' => '12.343.580-K' ], [ 'rut' => 'required|rut_exists:mysql.users,rut_num,rut_vd' ]); echo $validator->fails(); // true
Since this also checks if the RUT is valid (not strict), it will return false
if its not, or the RUT doesn't exists in the database.
The rule will automatically set to uppercase the verification digit column, so it won't matter if in your column you manage k
as lowercase.
Having a column for the RUT number and verification digits is usually the best approach to persist them. The number can be saved as 4 byte unsigned
int
, and the latter as a 1 bytestring
(1 character length).
To customize the query, you can use the Rule
class of Laravel, but using the method rutExists
. Note that you can input the number and verification digit columns, or both, if you don't want to let the rule guess them, as it may incorrectly guess when using a wildcard.
<?php use Illuminate\Support\Facades\Validator; use Illuminate\Validation\Rule; $validator = Validator::make([ 'rut' => [ 'rut_1' => '12.343.580-K', 'rut_2' => '13.871.792-5', ], ], [ 'rut' => [ 'required', Rule::rutExists('mysql.users', 'rut_num', 'rut_vd')->where('account_id', 1), ] ]); echo $validator->fails(); // true
num_exists
(Database)
This validation rule checks if only the number of the RUT exists, without taking into account the verification digit. This is handy when the Database has an index in the number of the RUT, thus making this verification blazing fast.
This rule automatically validates the RUT before doing the query.
<?php use Illuminate\Support\Facades\Validator; $validator = Validator::make([ 'rut' => '12.343.580-K' ], [ 'rut' => 'required|num_exists:mysql.users,rut_num' ]); echo $validator->fails(); // true
You can customize the underlying query using the numExists
.
<?php use Illuminate\Support\Facades\Validator; use Illuminate\Validation\Rule; $validator = Validator::make([ 'rut' => '12.343.580-K', ], [ 'rut' => [ 'required', Rule::numExists('mysql.users', 'rut_num')->where('account_id', 1), ] ]); echo $validator->fails(); // true
rut_unique
(Database)
This works the same as the rut_exists
rule, but instead of checking if the RUT exists in the Database, it will detect if it doesn't. This rule works just like the Laravel's unique
rule works.
This rule automatically validates the RUT before doing the query.
<?php use Illuminate\Support\Facades\Validator; $validator = Validator::make([ 'rut' => '12.343.580-K' ], [ 'rut' => 'required|rut_unique:mysql.users,rut_num,rut_vd' ]); echo $validator->fails(); // true
You can also exclude a certain ID or records from the Unique validation. For this, you need to use the Rule
class.
<?php use Illuminate\Support\Facades\Validator; use Illuminate\Validation\Rule; $validator = Validator::make([ 'rut' => '12.343.580-K', ], [ 'rut' => [ 'required', Rule::rutUnique('mysql.users', 'rut_num')->ignore(request()->user()), ] ]); echo $validator->fails(); // true
[Warning] You should never pass any user controlled request input into the ignore method. Instead, you should only pass a system generated unique ID such as an auto-incrementing ID or UUID from an Eloquent model instance. Otherwise, your application will be vulnerable to an SQL injection attack.
num_unique
(Database)
This rule will check only if the number of the RUT doesn't exists already in the database, which is useful for Databases with an index solely on the number of the RUT. This rule also matches the Laravel's unique
rule works.
This rule automatically validates the RUT before doing the query.
<?php use Illuminate\Support\Facades\Validator; $validator = Validator::make([ 'rut' => '12.343.580-K' ], [ 'rut' => 'required|num_unique:mysql.users,rut_num' ]); echo $validator->fails(); // true
You can also exclude a certain ID or records from the Unique validation. For this, you need to use the Rule
class.
<?php use Illuminate\Support\Facades\Validator; use Illuminate\Validation\Rule; $validator = Validator::make([ 'rut' => '12.343.580-K', ], [ 'rut' => [ 'required', Rule::numUnique('mysql.users')->ignore(request()->user()->id), ] ]); echo $validator->fails(); // true
[Warning] You should never pass any user controlled request input into the ignore method. Instead, you should only pass a system generated unique ID such as an auto-incrementing ID or UUID from an Eloquent model instance. Otherwise, your application will be vulnerable to an SQL injection attack.
Database Blueprint helper
If you're creating your database from the ground up, you don't need to manually create the RUT columns. Just use the rut()
or rutNullable()
helpers in the Blueprint:
Schema::create('users', function (Blueprint $table) { $table->rut(); // ... }); Schema::create('company', function (Blueprint $table) { $table->rutNullable(); // ... });
The
rutNullable()
method creates both Number and Verification Digit columns as nullable.
If you plan to use the Number as an index, which may speed up queries to look for RUTs, you can just index the Number column by fluently adding primary()
, index()
or unique()
depending on your database needs. This is because it has more sense to index only the Number rather than the whole RUT.
RUT trait for Models
This package contains two traits: HasRut
and RoutesRut
.
To use these traits, ensure your model saves the RUT Number and RUT Verification digit in separate columns.
HasRut
This trait conveniently adds a RUT Scope to a model that has a RUT in its columns, and the rut
property which returns a Rut
instance.
<?php namespace App\Models; use DarkGhostHunter\Lararut\HasRut; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use HasRut; // ... }
With that, you will have access to convenient RUT queries shorthands:
findRut()
: Finds a record by the given RUT.findManyRut()
: Finds many records by the given RUTs.findRutOrFail()
: Finds a record by the RUT or fails.findRutOrNew()
: Finds a record by the RUT or creates one.whereRut()
: Creates aWHERE
clause with the RUT number equal to the issued one.orWhereRut()
: Creates aOR WHERE
clause with the RUT number equal to the issued one.
These RUT queries work over the RUT Number for convenience, as the RUT Verification Digit should be verified on persistence.
The rut
property is dynamically created from the RUT Number and RUT Verification Digit columns, which uses a caster underneath.
echo $user->rut; // "20490006-K"
Configuring the RUT columns
By convention, the trait uses rut_num
and rut_vd
as the default columns to retrieve and save the RUT Number and RUT Verification Digit, respectively.
You can easily change it to anything your database is working with:
class User extends Authenticatable { use HasRut; protected const RUT_NUM = 'numero_rut'; protected const RUT_VD = 'digit_rut'; // ... }
RoutesRut
You can use the RoutesRut
trait to override the resolveRouteBinding()
method of your Eloquent Model to look for its RUT if the field to identify is rut
.
Ensure you also add the
HasRut
trait, as it will use the added query scopes.
use DarkGhostHunter\Lararut\HasRut; use DarkGhostHunter\Lararut\RoutesRut; class User extends Authenticatable { use HasRut; use RoutesRut; }
Then, you will be able to use Route Model Binding in your routes by issuing the rut
as the name of the field to use to retrieve the model instance from the database.
Route::get('usuario/{user:rut}', function (User $user) { return $user; });
If the RUT is invalid, the model won't be found, so there is no need to validate the rut while route-binding.
Rut Collection
This package registers a callback to retrieve an array of RUTs as a Laravel Collection when using many()
and manyOrThrow()
.
$ruts = Rut::many([ '15500342-1', '7276742-K' ]); echo $ruts->first(); // "15.500.342-1"
Helpers
This package includes the rut()
global helper file, which allows you to create a Rut instance anywhere in your code, or a Rut Generator if you don't issue any parameter.
<?php namespace App\Http\Listeners; use Illuminate\Auth\Events\Lockout; use App\Notifications\ProbablyForgotHisPassword; use App\Notifications\SupportReadyToHelp; use App\Models\User; class LogFailedAttempt { /** * Handle the event. * * @param Lockout $event * @return void */ public function handle(Lockout $event) { // Get the RUT from the request input $rut = rut($event->request->input('rut')); // If the user who tried exists in the database, notify him. if ($user = User::where('rut_num', $rut->num)->first()) { $user->notify(new ProbablyForgotHisPassword()); } } /** * Creates many RUTs. * * @return array|\DarkGhostHunter\RutUtils\Rut */ public function generateRuts() { return rut()->generate(100); } }
License
This package is licenced by the MIT License.