This package requires PHP 8.4+ and supports Laravel 12 and Laravel 13.
This package can generate random tokens which can expires.
Generated token can be used for creating one-time links, or authentication with sms pin and etc.
we have 2 things that can expire genereted tokens:
- time limit : for example a token can be expired after 2022/05/12
- usage limit : for example a token can be expired after using it more than 3 times.
Donate me if you like this package 😎 ![]()
- Available drivers
- Install
- Configure
- How to use
- Testing
- Change log
- Contributing
- Security
- Credits
- License
Via Composer
$ composer require shetabit/token-builderThe service provider and the TokenBuilder alias are registered by Laravel's package discovery, so there is nothing to
add to config/app.php (or to bootstrap/providers.php).
Run the below commands to publish migrations and create tables
php artisan vendor:publish --tag=token-builder-migrations
php artisan migrateyou can use TokenBuilder facade or Builder class to build tokens.
In your code, use facade like the below :
use Shetabit\TokenBuilder\Facade\TokenBuilder;
// ...
$tokenObject = $token = TokenBuilder::build();you can also use Builder :
use Shetabit\TokenBuilder\Builder;
// ...
$builder = new Builder;
$tokenObject = $builder->build();each tokenObject has a unique value that can be used to recognize it from others and we call it token.
you can access to tokenObject unique token using token, see below example:
use Shetabit\TokenBuilder\Facade\TokenBuilder;
// ...
// generate and store token in database
$tokenObject = $token = TokenBuilder::build();
// show token unique value
echo $tokenObject->token;you can retrieve token and send it to users via email or sms or using it in URLs. it can be used to sms verifications or one-time login pins , etc.
you can build a token with auto expiration date. this kind of token will be expired after the specified date.
use Shetabit\TokenBuilder\Facade\TokenBuilder;
// ...
// will be expired after 5 minutes
$date = Carbon::now()->addMinutes(5);
$tokenObject = TokenBuilder::setExpireDate($date)->build();
echo $tokenObject->token; // show unique token
echo $tokenObject->expired_at; // show expiration datetime
if ($tokenObject->hasExpired()) {
echo 'token has expired';
}you can add usage limit into your tokens. a token will be invalid after the usage has exceeded the limit.
use Shetabit\TokenBuilder\Facade\TokenBuilder;
// ...
// will be expired after 1 usage.
$tokenObject = TokenBuilder::setUsageLimit(1)->build();
// use token --> increment the usage counter
$tokenObject->use();
echo $tokenObject->token; // show unique token
echo $tokenObject->usage_count; // show total usages count
echo $tokenObject->max_usage_limit; // show max usage limit
// determine if user has used
if ($tokenObject->hasUsed()) {
echo 'token has used';
}
// determin if token has exceed max usage
if ($tokenObject->hasExceedMaxUsage()) {
echo 'token used has exceeded the specified limit';
}you can validate a token using isValid method.
a token is valid if has not exceeded the specified limit and has not expired yet.
use Shetabit\TokenBuilder\Facade\TokenBuilder;
// ...
$date = Carbon::now()->addMinutes(5); // will be expired after 5 minutes
$usageLimit = 1; // max usages
$token = TokenBuilder::setExpireDate($date)->setUsageLimit($usageLimit)->build();
if ($token->isValid()) {
echo 'token is valid';
$token->use(); // use token (increament usage counter)
} else {
echo 'token is not valid any more!';
}you can use a token by running use method.
you can expire a token by running markAsExpired method. (this method will update expiration date to current date).
you can add a relation to tokens. this can be done in 2 different ways:
use Shetabit\TokenBuilder\Facade\TokenBuilder;
use App\User;
$user = User::first();
/**
* first example: using TokenBuilder
**/
$tokenObject = TokenBuilder::setRelatedItem($user)->build();
/**
* second example: using a main model
**/
$tokenObject = $user->temporaryTokenBuilder()->build();
// you can access to token's relation using the tokenable
dd($tokenObject->tokenable);
if ($tokenObject->tokenable) {
echo $tokenObject->tokenable->email;
}you can attach custom data into your token. this data will be stored in json format.
use Shetabit\TokenBuilder\Facade\TokenBuilder;
/**
* first example: using TokenBuilder
**/
$data = [
'mobile' => '9373620353',
'name' => 'John Doe',
];
$tokenObject = TokenBuilder::setData($data)->build();
echo $tokenObject->data['mobile'];you can retrieve tokenObject using token's unique string
$token = 22325651; // your unique token
// retrieve token object
$tokenObject = TokenBuilder::setUniqueId($token)->findToken();
// retrieve token object if it is valid
$tokenObject = TokenBuilder::setUniqueId($token)->findValidToken();
// retrieve token object using its relation
$tokenObject = $user->temporaryTokenBuilder()->setUniqueId($token)->findToken();
// retrieve token object if it is valid using its relation
$tokenObject = $user->temporaryTokenBuilder()->setUniqueId($token)->findValidToken();sometimes you don't have a token yet and want to know whether a model still has one that is valid:
a forgot password pin should not be sent again while the one that was sent is still usable.
a model that uses the HasTemporaryTokens trait can answer that itself:
use App\User;
$user = User::first();
// does this user still have a valid token?
if ($user->hasValidTemporaryToken()) {
echo 'this user has a valid token';
}
// the same question, for one type of token only
if ($user->hasValidTemporaryToken('reset-password')) {
echo 'a reset pin was sent and is still valid';
}
// retrieve them, latest one first
$tokenObjects = $user->validTemporaryTokens('reset-password');
echo $tokenObjects->count();
echo $tokenObjects->first()?->token;so a pin is only built when there is none left:
if (!$user->hasValidTemporaryToken('reset-password')) {
$user->temporaryTokenBuilder()
->setType('reset-password')
->setUsageLimit(1)
->setExpireDate(Carbon::now()->addMinutes(5))
->build(6);
}the TokenBuilder answers the same questions, and without a relation it looks at the tokens of every model:
use Shetabit\TokenBuilder\Facade\TokenBuilder;
// the valid tokens of one user, of one type
$tokenObjects = TokenBuilder::setRelatedItem($user)->setType('reset-password')->findValidTokens();
// is there any valid reset pin at all?
$exists = TokenBuilder::setType('reset-password')->hasAnyValidToken();notice: findValidTokens and hasAnyValidToken ask whether there is any valid token, so they ignore
setUniqueId. use findValidToken or isValid to validate a token you have.
This is a reference for TokenBuilder methods.
TokenBuilder creates a tokenObject (instance of eloquent Token model) if you run build method and searches into data base using findToken and findValidToken.
-
you can build tokens with your custom algoritm and use it as unique id.
$token = 'jgaZ1z9'; $tokenObject = TokenBuilder::setUniqueId($token)->build(); echo $tokenObject->token; // jgaZ1z9
-
returns your custom unique id (if not exists, returns
null). -
you can attach some data into tokens and retrieve them later.
-
returns attached data.
-
sets an expiration date.
-
retrieves expiration date.
-
sets usage limit.
-
retrieves usage limit.
-
sets token type. you can set type for your tokens. its like a scope for your tokens.
-
retrieves token type.
-
add a relation to token.
-
retrieve current relation.
-
generate a token. The number of digits of a generated token can be given:
build(6)builds a six digit one, the default is eight.create()is an alias of it. -
find token (being valid or not valid is not important) and return
nullif not exists. -
find token if it is valid and return
nullif not exists. -
retrieve every valid token of the related item (and of the type, when one is set), latest one first, as an eloquent collection. without a related item it looks at the tokens of every model. the unique id plays no part in it.
-
determine if there is any valid token of the related item (and of the type, when one is set), and returns a boolean result. the unique id plays no part in it either.
these methods are added to your own models by the Shetabit\TokenBuilder\Traits\HasTemporaryTokens trait.
-
the
morphManyrelation with every token of the model, valid or not. -
a
TokenBuilderwith the model set as the related item. -
retrieve the valid tokens of the model, latest one first, as an eloquent collection. a type can be given (
validTemporaryTokens('reset-password')) to only look at the tokens of that type. -
determine if the model still has a valid token, and returns a boolean result. a type can be given here as well.
-
add 1 to usage counter. (usageCounter = usageCounter + 1)
-
determine is current token has used and returns a boolean result.
-
determine if current token max usage is limited and returns a boolean result.
-
determine if current token has expired or not.
-
mark current token as expired.
notice: this method updates
expired_atfield to current time (now). -
determines if current token is valid (must not be expired and must not be exceeded max usage limit).
-
returns the token relation if there is any relation, and returns null if no relation exists.
Every pull request and every push to master is checked by GitHub Actions: the test suite runs on
PHP 8.4 and 8.5, against Laravel 12 and 13 and against both the lowest and the highest supported dependencies, the
coding style is checked with PHP_CodeSniffer, the sources are analysed with PHPStan (level 7, with larastan) and the
code coverage of the test suite is measured and has to stay above 95%.
The suite has two parts: tests/Unit covers the builder, the token, the repository, the token trait and the provider
on their own, and tests/Feature runs the flows of this readme end to end against a database.
You can run the same checks locally. With PHP and Composer installed on your machine:
composer install
composer test # run the test suite
composer test-coverage # run the test suite and report code coverage
composer check-style # check the coding style
composer fix-style # fix the coding style where possible
composer analyse # run static analysis
composer ci # run all of the checks aboveIf you would rather not install PHP on your machine, the shipped Dockerfile and Makefile run everything inside a
container:
make test # run the test suite
make coverage # run the test suite and report code coverage
make check-style # check the coding style
make fix-style # fix the coding style where possible
make analyse # run static analysis
make ci # run all of the checks above
make shell # open a shell inside the container
make help # list every available targetAnother PHP version can be used with make test PHP_VERSION=8.5, and a single Laravel version with
make test-laravel LARAVEL=12.
Please see CHANGELOG for more information on what has changed recently.
Please see CONTRIBUTING and CONDUCT for details.
If you discover any security related issues, please email khanzadimahdi@gmail.com instead of using the issue tracker.
The MIT License (MIT). Please see License File for more information.
