[: string { return 'First Post'; }
public static function description(?Model $achiever = null): string
{
return 'Create your first post on the platform.';
}
// Example of dynamic content (optional):
// public static function name(?Model $achiever = null): string
// {
// if ($achiever) {
// $progress = static::getProgress($achiever);
// $remaining = static::getRemainingProgress($achiever);
// if ($remaining > 0) {
// return "First Post ({$progress}/{$remaining} remaining)";
// }
// }
// return 'First Post';
// }gist/v/ram64/laravel-merit.svg?style=flat-square)](https://packagist.org/packages/ram64/laravel-merit)
Laravel Merit brings gamification to your Laravel apps with clean, code-first achievements, XP tracking, and leveling. Define achievements in config, track progress with traits, and reward your users with milestones and badges.
To do
You can install the package via composer:
composer require ram64/laravel-meritYou can publish and run the migrations with:
php artisan vendor:publish --tag="laravel-merit-migrations"
php artisan migrateYou can publish the config file with:
php artisan vendor:publish --tag="laravel-merit-config"This is the contents of the published config file:
return [
'achiever_model' => env('MERIT_ACHIEVER_MODEL', App\Models\User::class),
'achievements_table' => env('MERIT_ACHIEVEMENTS_TABLE', 'achiever_achievements'),
'cache_ttl' => 10,
'queue_events' => env('MERIT_QUEUE_EVENTS', false),
];Optionally, you can publish the views using
php artisan vendor:publish --tag="laravel-merit-views"- Add the CanAchieve trait to your model:
use Ram64\LaravelMerit\Concerns\CanAchieve;
class User extends Authenticatable
{
use CanAchieve;
// Your model code...
}- Create Achievement Definitions:
Use the artisan command to create new achievements:
php artisan make:merit-achievement FirstPost --category=postsThis creates a new achievement class:
<?php
namespace App\Definitions\Achievements\Posts;
use Illuminate\Database\Eloquent\Model;
use Ram64\LaravelMerit\Definitions\Achievements\AchievementDefinition;
class FirstPostAchievement extends AchievementDefinition
{
public static function key(): string
{
return 'first_post';
}
public static function name(): string
{
return 'First Post';
}
public static function description(): string
{
return 'Create your very first post';
}
public static function goal(): int
{
return 1;
}
public static function category(): string
{
return 'posts';
}
public static function qualifiesFor(Model $achiever): bool
{
return static::getCount($achiever, 'posts') >= static::goal();
}
public static function calculateCurrentProgress(Model $achiever): int
{
return min(static::getCount($achiever, 'posts'), static::goal());
}
}- Track Achievement Progress:
use Ram64\LaravelMerit\Services\AchievementTracker;
// Check all achievements for a user
AchievementTracker::check($user);
// Get achievement definition by key
$definition = AchievementTracker::getDefinition('first_post');
// Get definition from an AchieverAchievement model
$achievement = $user->achievements()->where('achievement_key', 'first_post')->first();
$definition = AchievementTracker::getDefinitionFromAchievement($achievement);
// Get all achievement keys
$keys = AchievementTracker::getAchievementKeys();
// Get achievement display data
$display = AchievementTracker::getAchievementDisplay($user, 'first_post');Laravel Merit supports flexible prerequisite definitions. Achievements can require other achievements to be completed first:
public static function prerequisite(): string|array|null
{
// No prerequisites
return null;
// Single string key prerequisite
return 'first_post';
// Single class prerequisite
return FirstPostAchievement::class;
// Multiple mixed prerequisites
return [
'first_post', // String key
FifthPostAchievement::class, // Class reference
];
}Laravel Merit includes a comprehensive experience and leveling system:
use Ram64\LaravelMerit\Concerns\Experiencer;
class User extends Authenticatable
{
use Experiencer;
}
```php
use Ram64\LaravelMerit\Concerns\CanExperience;
class User extends Authenticatable
{
use CanExperience;
}
// Award experience
$user->gainExperience(100, 'Completed quest');// Check level and progress $level = $user->getLevel(); $progress = $user->getExperienceProgress();
**Features:**
- Flexible level calculation (static thresholds or dynamic formulas)
- Experience logging with optional enable/disable
- Events for experience changes and level-ups
- Caching for performance
- Polymorphic support for any model
## Performance & Caching
Laravel Merit includes comprehensive caching to ensure high performance, especially with dynamic achievement content:
### Cached Methods
For optimal performance, use these cached methods instead of calling `name()` and `description()` directly:
```php
// Fast cached access (recommended)
$name = FirstPostAchievement::getCachedName($user);
$description = FirstPostAchievement::getCachedDescription($user);
// Direct access (bypasses cache)
$name = FirstPostAchievement::name($user);
$description = FirstPostAchievement::description($user);
Caches are automatically cleared when:
- Achievement progress changes
- Achievements are unlocked
- Manual award/increment operations occur
Configure cache TTL in config/merit.php:
'cache_ttl' => 10, // minutes- Use
getAchievementDisplay()for complete achievement data - it's fully cached - Use cached methods for individual name/description access
- Avoid direct database queries in dynamic content methods - use cached progress methods
- Consider cache TTL based on your update frequency
composer testPlease see CHANGELOG for more information on what has changed recently.
Please see CONTRIBUTING for details.
Please review our security policy on how to report security vulnerabilities.
The MIT License (MIT). Please see License File for more information.