bywyd/laravel-qol 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

bywyd/laravel-qol

最新稳定版本:v1.1.1

Composer 安装命令:

composer require bywyd/laravel-qol

包简介

Quality of Life enhancements for Laravel - supportive tools, traits, and utilities

README 文档

README

Laravel Quality of Life - A collection of helpful traits, utilities, and tools to enhance your Laravel development experience.

Features

Media Management

  • HasImages Trait - Easy image management with ordering and tagging
  • HasFiles Trait - Generic file upload and management
  • HasVideos Trait - Video upload with metadata support
  • PhotoImage Model - Complete image model with helper methods
  • File Model - Flexible file handling with type detection
  • Video Model - Video model with duration, resolution, and thumbnails

Model Enhancements

  • HasHistory Trait - Automatic model change tracking
  • HasRoles Trait - Complete role and permission system for users
  • HasIntegrations Trait - Manage user integrations with OAuth, API keys, and credentials
  • HasSettings Trait - Universal settings system (app-wide, per-user, per-model)
  • HasUuid Trait - Automatic UUID generation for models
  • HasSlug Trait - Automatic slug generation from any field
  • HasStatus Trait - Status management with active/inactive scopes
  • Sortable Trait - Easy ordering/sorting functionality
  • Cacheable Trait - Built-in model-level caching
  • Searchable Trait - Simple and full-text search capabilities

Authorization

  • Role Model - Hierarchical role system with levels
  • Permission Model - Granular permission control
  • Middleware - Route protection with role, permission, or both
  • Blade Directives - Template-level authorization checks
  • Gates Integration - Automatic Laravel Gate registration

Installation

Install via Composer:

composer require bywyd/laravel-qol

Configuration

Publish the configuration file (optional):

php artisan vendor:publish --tag=laravel-qol-config

Publish the migrations:

php artisan vendor:publish --tag=laravel-qol-migrations
php artisan migrate

Usage

HasHistory Trait

Track all changes made to your models automatically:

use Bywyd\LaravelQol\Traits\HasHistory;

class Post extends Model
{
    use HasHistory;

    // Optional: Exclude specific attributes from history
    protected $historyExcludedAttributes = ['views', 'updated_at'];
    
    // Optional: Only log specific events
    protected $historyEvents = ['created', 'updated'];
    
    // Optional: Keep histories when model is deleted
    protected $deleteHistoriesOnDelete = false;
}

// Usage
$post = Post::find(1);
$post->histories; // Get all history records
$post->latestHistory; // Get the latest history

// Manual history logging
$post->logHistory(HistoryLogTypes::CUSTOM, 'Custom action performed');

// Temporarily disable history logging
$post->withoutHistory(function($post) {
    $post->update(['title' => 'No history logged']);
});

HasImages Trait

Manage images for your models with ease:

use Bywyd\LaravelQol\Traits\HasImages;

class Product extends Model
{
    use HasImages;
}

// Usage
$product = Product::find(1);

// Upload an image
$image = $product->uploadImage($request->file('image'), 0, 'gallery');

// Get all images
$product->images;

// Get images by tag
$product->imagesByTag('gallery');

// Get primary image
$product->primaryImage();

// Reorder images
$product->reorderImages([3, 1, 2]); // Array of image IDs

// Delete an image
$product->deleteImage($image);

// Delete all images
$product->deleteAllImages();

HasFiles Trait

Upload and manage any type of file:

use Bywyd\LaravelQol\Traits\HasFiles;

class Document extends Model
{
    use HasFiles;
}

// Usage
$document = Document::find(1);

// Upload a file
$file = $document->uploadFile($request->file('attachment'), 0, 'contract', [
    'department' => 'Legal'
]);

// Get all files
$document->files;

// Get files by tag
$document->filesByTag('contract');

// Get document files (PDFs, DOCs, etc.)
$document->documents();

// Download a file
return $file->download();

// Delete a file
$document->deleteFile($file);

HasVideos Trait

Manage video uploads with metadata:

use Bywyd\LaravelQol\Traits\HasVideos;

class Course extends Model
{
    use HasVideos;
}

// Usage
$course = Course::find(1);

// Upload a video
$video = $course->uploadVideo($request->file('video'), 0, 'lesson-1');

// Access video properties
$video->url; // Public URL
$video->human_size; // "50.5 MB"
$video->human_duration; // "5:23"
$video->aspect_ratio; // "16:9"

// Quality checks
$video->isHD(); // 720p or higher
$video->isFullHD(); // 1080p or higher
$video->is4K(); // 2160p or higher

// Get HD videos
$course->hdVideos();

// Delete a video
$course->deleteVideo($video);

HasUuid Trait

Automatically generate UUIDs for your models:

use Bywyd\LaravelQol\Traits\HasUuid;

class User extends Model
{
    use HasUuid;
    
    // Optional: Customize UUID column
    protected $uuidColumn = 'uuid';
}

// Usage
$user = User::create(['name' => 'John']);
$user->uuid; // "550e8400-e29b-41d4-a716-446655440000"

// Find by UUID
$user = User::findByUuid('550e8400-e29b-41d4-a716-446655440000');
$user = User::findByUuidOrFail($uuid);

HasSlug Trait

Automatic slug generation from any field:

use Bywyd\LaravelQol\Traits\HasSlug;

class Article extends Model
{
    use HasSlug;
    
    // Optional: Customize slug source
    protected $slugSource = 'title';
    
    // Optional: Customize slug column
    protected $slugColumn = 'slug';
    
    // Optional: Prevent regeneration on update
    protected $regenerateSlugOnUpdate = false;
}

// Usage
$article = Article::create(['title' => 'Hello World']);
$article->slug; // "hello-world"

// Find by slug
$article = Article::findBySlug('hello-world');
$article = Article::findBySlugOrFail('hello-world');

HasStatus Trait

Manage model status with convenient methods:

use Bywyd\LaravelQol\Traits\HasStatus;

class Task extends Model
{
    use HasStatus;
    
    // Optional: Customize status column
    protected $statusColumn = 'status';
    
    // Optional: Customize status values
    protected $activeStatusValue = 1;
    protected $inactiveStatusValue = 0;
}

// Usage
$task = Task::find(1);

// Status checks
$task->isActive();
$task->isInactive();

// Status changes
$task->activate();
$task->deactivate();
$task->toggleStatus();

// Query scopes
Task::active()->get();
Task::inactive()->get();
Task::status(1)->get();

Sortable Trait

Add ordering functionality to your models:

use Bywyd\LaravelQol\Traits\Sortable;

class MenuItem extends Model
{
    use Sortable;
    
    // Optional: Customize sort column
    protected $sortColumn = 'order';
}

// Usage
$item = MenuItem::find(1);

// Move operations
$item->moveUp();
$item->moveDown();
$item->moveTo(5);
$item->swapWith($otherItem);

// Query scope
MenuItem::ordered()->get(); // Ordered by sort column
MenuItem::ordered('desc')->get();

Cacheable Trait

Built-in model caching:

use Bywyd\LaravelQol\Traits\Cacheable;

class Settings extends Model
{
    use Cacheable;
    
    // Optional: Customize cache prefix
    protected $cachePrefix = 'settings';
    
    // Optional: Customize TTL (seconds)
    protected $cacheTtl = 3600;
}

// Usage
$settings = Settings::find(1);

// Cache data
$value = $settings->remember('config', function() {
    return expensive_operation();
});

// Cache forever
$value = $settings->rememberForever('permanent', function() {
    return static_data();
});

// Clear cache
$settings->clearCache();

Searchable Trait

Add search functionality:

use Bywyd\LaravelQol\Traits\Searchable;

class Product extends Model
{
    use Searchable;
    
    // Define searchable columns
    protected $searchable = ['name', 'description', 'category.name'];
}

// Usage
// Simple search
Product::search('laptop')->get();

// Custom columns
Product::search('laptop', ['name', 'sku'])->get();

// Full-text search (MySQL)
Product::fullTextSearch('gaming laptop')->get();

HasRoles Trait

Complete role and permission system for User models:

use Bywyd\LaravelQol\Traits\HasRoles;

class User extends Authenticatable
{
    use HasRoles;
}

// Assign roles
$user->assignRole('admin');
$user->assignRole(['editor', 'moderator']);

// Remove roles
$user->removeRole('editor');

// Sync roles (removes all existing roles and assigns new ones)
$user->syncRoles(['admin', 'super-admin']);

// Check roles
$user->hasRole('admin'); // true
$user->hasAnyRole(['admin', 'editor']); // true if user has any
$user->hasAllRoles(['admin', 'editor']); // true if user has all

// Give direct permissions
$user->givePermission('edit-posts');
$user->givePermission(['edit-posts', 'delete-posts']);

// Revoke permissions
$user->revokePermission('delete-posts');

// Sync permissions
$user->syncPermissions(['edit-posts', 'view-posts']);

// Check permissions
$user->hasPermission('edit-posts'); // true
$user->hasAnyPermission(['edit-posts', 'delete-posts']); // true if has any
$user->hasAllPermissions(['edit-posts', 'view-posts']); // true if has all

// Get all permissions (direct + from roles)
$user->getAllPermissions();

// Check super admin
$user->isSuperAdmin(); // true if has super-admin role or * permission

// Query scopes
User::role('admin')->get();
User::role(['admin', 'editor'])->get();
User::permission('edit-posts')->get();
User::permission(['edit-posts', 'delete-posts'])->get();

Role Model

Manage roles with hierarchical levels:

use Bywyd\LaravelQol\Models\Role;

// Create a role
$role = Role::create([
    'name' => 'Administrator',
    'slug' => 'admin',
    'description' => 'Full access to the system',
    'level' => 100, // Higher = more privileges
    'is_default' => false,
]);

// Assign permissions to role
$role->givePermission('edit-posts');
$role->givePermission(['delete-posts', 'manage-users']);

// Revoke permissions
$role->revokePermission('delete-posts');

// Sync permissions
$role->syncPermissions(['edit-posts', 'view-posts']);

// Check if role has permission
$role->hasPermission('edit-posts'); // true

// Check if super admin
$role->isSuperAdmin(); // true if has * permission

// Get users with this role
$role->users;

// Query scopes
Role::default()->first(); // Get default role
Role::byLevel()->get(); // Order by level
Role::byLevel('desc')->get();

Permission Model

Create and manage permissions:

use Bywyd\LaravelQol\Models\Permission;

// Create a permission
$permission = Permission::create([
    'name' => 'Edit Posts',
    'slug' => 'edit-posts',
    'description' => 'Can create and edit posts',
    'group' => 'posts', // Group related permissions
]);

// Get permissions by group
Permission::byGroup('posts')->get();

// Get all permissions grouped
$grouped = Permission::getAllGrouped();
// Returns: ['posts' => [...], 'users' => [...]]

// Wildcard permission (grants all permissions)
Permission::create([
    'name' => 'All Permissions',
    'slug' => '*',
    'description' => 'Super admin permission',
]);

Route Protection with Middleware

Protect routes using middleware:

// In your routes file
Route::middleware(['role:admin'])->group(function () {
    Route::get('/admin/dashboard', [AdminController::class, 'index']);
});

// Multiple roles (OR condition)
Route::middleware(['role:admin|editor'])->group(function () {
    Route::get('/posts/create', [PostController::class, 'create']);
});

// Permission middleware
Route::middleware(['permission:edit-posts'])->group(function () {
    Route::put('/posts/{post}', [PostController::class, 'update']);
});

// Multiple permissions (OR condition)
Route::middleware(['permission:edit-posts|delete-posts'])->group(function () {
    Route::get('/posts/manage', [PostController::class, 'manage']);
});

// Role OR Permission (if user has either)
Route::middleware(['role_or_permission:admin|edit-posts'])->group(function () {
    Route::post('/posts', [PostController::class, 'store']);
});

Blade Directives

Use in your Blade templates:

{{-- Check single role --}}
@role('admin')
    <a href="/admin">Admin Panel</a>
@endrole

{{-- Alternative syntax --}}
@hasrole('admin')
    <p>You are an admin</p>
@endhasrole

{{-- Check any role --}}
@hasanyrole(['admin', 'editor'])
    <button>Edit Content</button>
@endhasanyrole

{{-- Check all roles --}}
@hasallroles(['admin', 'super-admin'])
    <button>Critical Action</button>
@endhasallroles

{{-- Check permission --}}
@permission('edit-posts')
    <a href="/posts/create">Create Post</a>
@endpermission

{{-- Alternative syntax --}}
@haspermission('delete-posts')
    <button class="btn-danger">Delete</button>
@endhaspermission

{{-- Check any permission --}}
@hasanypermission(['edit-posts', 'delete-posts'])
    <div>Post Management</div>
@endhasanypermission

{{-- Check all permissions --}}
@hasallpermissions(['edit-posts', 'publish-posts'])
    <button>Publish</button>
@endhasallpermissions

{{-- Using @else --}}
@role('admin')
    <p>Admin content</p>
@else
    <p>Regular user content</p>
@endrole

Laravel Gates

Permissions are automatically registered as Gates:

// In your controller or anywhere
if (Gate::allows('edit-posts')) {
    // User can edit posts
}

if (Gate::denies('delete-posts')) {
    // User cannot delete posts
}

// Using authorize
$this->authorize('edit-posts');

// In routes
Route::get('/posts/{post}/edit', [PostController::class, 'edit'])
    ->can('edit-posts');

Policy Integration

Use with Laravel Policies:

// In your Policy
public function update(User $user, Post $post)
{
    return $user->hasPermission('edit-posts') || $user->id === $post->user_id;
}

public function delete(User $user, Post $post)
{
    return $user->hasPermission('delete-posts') || 
           $user->hasRole('admin');
}

Creating a Complete Authorization System

// 1. Create permissions
$permissions = [
    ['name' => 'View Posts', 'slug' => 'view-posts', 'group' => 'posts'],
    ['name' => 'Create Posts', 'slug' => 'create-posts', 'group' => 'posts'],
    ['name' => 'Edit Posts', 'slug' => 'edit-posts', 'group' => 'posts'],
    ['name' => 'Delete Posts', 'slug' => 'delete-posts', 'group' => 'posts'],
    ['name' => 'Manage Users', 'slug' => 'manage-users', 'group' => 'users'],
];

foreach ($permissions as $permission) {
    Permission::create($permission);
}

// 2. Create roles
$superAdmin = Role::create([
    'name' => 'Super Admin',
    'slug' => 'super-admin',
    'level' => 100,
]);
$superAdmin->givePermission('*'); // All permissions

$admin = Role::create([
    'name' => 'Admin',
    'slug' => 'admin',
    'level' => 50,
]);
$admin->givePermission(['view-posts', 'create-posts', 'edit-posts', 'manage-users']);

$editor = Role::create([
    'name' => 'Editor',
    'slug' => 'editor',
    'level' => 25,
]);
$editor->givePermission(['view-posts', 'create-posts', 'edit-posts']);

$user = Role::create([
    'name' => 'User',
    'slug' => 'user',
    'level' => 1,
    'is_default' => true,
]);
$user->givePermission('view-posts');

// 3. Assign to users
$user = User::find(1);
$user->assignRole('super-admin');

HasIntegrations Trait

Manage user integrations with third-party services:

use Bywyd\LaravelQol\Traits\HasIntegrations;

class User extends Authenticatable
{
    use HasIntegrations;
}

// Create OAuth integration (e.g., Google, GitHub, Facebook)
$user->createOAuthIntegration('google', [
    'provider_id' => '123456789',
    'provider_name' => 'Google',
    'access_token' => 'ya29.a0AfH6SMC...',
    'refresh_token' => '1//0gOZp...',
    'expires_in' => 3600, // seconds
    'metadata' => [
        'email' => 'user@gmail.com',
        'name' => 'John Doe',
        'avatar' => 'https://...',
    ],
]);

// Create API Key integration (e.g., Stripe, AWS, SendGrid)
$user->createApiKeyIntegration('stripe', [
    'provider_name' => 'Stripe',
    'api_key' => 'sk_test_51H...',
    'api_secret' => 'whsec_...',
    'metadata' => [
        'account_id' => 'acct_123',
        'mode' => 'test',
    ],
]);

// Create custom integration
$user->createIntegration('webhook', 'webhook', [
    'provider_name' => 'My Webhook Service',
    'credentials' => [
        'url' => 'https://api.example.com/webhook',
        'secret' => 'webhook_secret_123',
    ],
]);

// Check if user has integration
if ($user->hasIntegration('google')) {
    // User has Google integration
}

// Check if integration is active
if ($user->hasActiveIntegration('stripe')) {
    // Stripe integration is active
}

// Get integration
$integration = $user->getIntegration('google');

// Access decrypted credentials
$accessToken = $user->getIntegrationAccessToken('google');
$apiKey = $user->getIntegrationApiKey('stripe');
$apiSecret = $user->getIntegrationApiSecret('stripe');

// Check token validity
$integration = $user->getIntegration('google');
if ($integration->hasValidToken()) {
    // Token exists and not expired
}

// Activate/Deactivate integration
$user->activateIntegration('google');
$user->deactivateIntegration('stripe');

// Remove integration
$user->removeIntegration('github');

// Update metadata
$user->updateIntegrationMetadata('google', [
    'last_sync' => now(),
    'sync_count' => 5,
]);

// Mark as used (updates last_used_at)
$user->markIntegrationAsUsed('stripe');

// Get all integrations
$user->integrations; // All integrations
$user->activeIntegrations; // Only active

// Filter by type
$user->oauthIntegrations(); // OAuth only
$user->apiKeyIntegrations(); // API keys only
$user->validIntegrations(); // Valid tokens only

// Query scopes
UserIntegration::provider('google')->get();
UserIntegration::type('oauth')->get();
UserIntegration::active()->get();
UserIntegration::validToken()->get();

UserIntegration Model

Direct model usage:

use Bywyd\LaravelQol\Models\UserIntegration;

$integration = UserIntegration::find(1);

// Encrypted credential methods
$integration->setAccessToken('new_token');
$integration->setRefreshToken('new_refresh');
$integration->setApiKey('sk_test_123');
$integration->setApiSecret('secret_456');

$integration->save();

// Decrypted access
$token = $integration->getDecryptedAccessToken();
$refresh = $integration->getDecryptedRefreshToken();
$apiKey = $integration->getDecryptedApiKey();
$apiSecret = $integration->getDecryptedApiSecret();

// Status checks
$integration->isTokenExpired(); // Check if token expired
$integration->hasValidToken(); // Token exists and not expired

// Actions
$integration->activate();
$integration->deactivate();
$integration->markAsUsed();

// Relationships
$integration->user; // Get the user

Common Integration Examples

// Google OAuth
$user->createOAuthIntegration('google', [
    'provider_id' => $googleUser->id,
    'provider_name' => 'Google',
    'access_token' => $googleUser->token,
    'refresh_token' => $googleUser->refreshToken,
    'expires_in' => $googleUser->expiresIn,
    'metadata' => [
        'email' => $googleUser->email,
        'name' => $googleUser->name,
    ],
]);

// GitHub OAuth
$user->createOAuthIntegration('github', [
    'provider_id' => $githubUser->id,
    'provider_name' => 'GitHub',
    'access_token' => $githubUser->token,
    'metadata' => [
        'username' => $githubUser->nickname,
        'repos_url' => $githubUser->user['repos_url'],
    ],
]);

// Stripe
$user->createApiKeyIntegration('stripe', [
    'provider_name' => 'Stripe',
    'api_key' => config('services.stripe.secret'),
    'metadata' => [
        'customer_id' => $stripeCustomer->id,
        'mode' => 'live',
    ],
]);

// AWS
$user->createApiKeyIntegration('aws', [
    'provider_name' => 'AWS',
    'api_key' => $credentials['access_key_id'],
    'api_secret' => $credentials['secret_access_key'],
    'credentials' => [
        'region' => 'us-east-1',
        'bucket' => 'my-bucket',
    ],
]);

// SendGrid
$user->createApiKeyIntegration('sendgrid', [
    'provider_name' => 'SendGrid',
    'api_key' => $sendgridApiKey,
    'metadata' => [
        'from_email' => 'noreply@example.com',
        'from_name' => 'My App',
    ],
]);

// Slack Webhook
$user->createIntegration('slack', 'webhook', [
    'provider_name' => 'Slack',
    'credentials' => [
        'webhook_url' => 'https://hooks.slack.com/services/...',
        'channel' => '#general',
    ],
]);

Security Features

All sensitive data is automatically encrypted:

  • Access tokens
  • Refresh tokens
  • API keys
  • API secrets
  • Custom credentials

The trait uses Laravel's built-in encryption, ensuring data is secure at rest.

Middleware

The package includes 10 production-ready middleware:

SetLocale Middleware

Automatically sets application locale based on multiple sources (priority order):

// In your routes or middleware group
Route::middleware('locale')->group(function () {
    // Your routes
});

// Supports:
// 1. Query parameter: ?locale=es
// 2. Session: session('locale')
// 3. User preference: $user->getPreferredLocale()
// 4. Cookie: locale=fr
// 5. Accept-Language header

RestrictAccess Middleware

Maintenance mode with granular access control:

// Enable in .env
ACCESS_RESTRICTION_ENABLED=true
ALLOWED_IPS="192.168.1.1,10.0.0.0/24,172.16.*.*"
BYPASS_TOKEN=secret-token-123

// Apply to routes
Route::middleware('restrict.access')->group(function () {
    // Protected routes
});

// Access with bypass token
// ?bypass_token=secret-token-123
// Header: X-Bypass-Token: secret-token-123

ForceJsonResponse Middleware

Force JSON responses for API applications:

Route::middleware('force.json')->group(function () {
    // All responses will be JSON
});

LogRequestResponse Middleware

Log all HTTP requests and responses:

Route::middleware('log.request')->group(function () {
    // Requests/responses logged
});

// Configure in config/laravel-qol.php
'logging' => [
    'log_requests' => true,
    'log_responses' => true,
    'log_request_body' => false,
    'log_response_body' => false,
    'sensitive_keys' => ['password', 'token'],
],

SecurityHeaders Middleware

Add security headers automatically:

Route::middleware('security.headers')->group(function () {
    // Security headers added
});

// Adds: X-Frame-Options, X-Content-Type-Options, X-XSS-Protection,
// HSTS, CSP, Referrer-Policy, Permissions-Policy

RateLimitByUser Middleware

Rate limiting per user or IP:

// 60 requests per minute
Route::middleware('rate.limit.user:60,1')->group(function () {
    //
});

// 100 requests per 5 minutes
Route::middleware('rate.limit.user:100,5')->group(function () {
    //
});

ConvertEmptyStringsToNull Middleware

Convert empty strings to null in requests:

Route::middleware('convert.empty.strings')->group(function () {
    // '' becomes null
});

TrimStrings Middleware

Automatically trim string inputs:

Route::middleware('trim.strings')->group(function () {
    // All strings trimmed (except passwords)
});

ApiVersioning Middleware

API versioning support:

// Require specific version
Route::middleware('api.version:v1')->group(function () {
    //
});

// Accept any supported version
Route::middleware('api.version')->group(function () {
    $version = request()->attributes->get('api_version');
});

// Version sources:
// - Header: Accept: application/vnd.api.v1+json
// - Header: X-API-Version: v1
// - Query: ?version=v1
// - URL: /api/v1/users

CorsMiddleware

Advanced CORS handling:

Route::middleware('cors')->group(function () {
    //
});

// Configure in config/laravel-qol.php
'cors' => [
    'allowed_origins' => ['*'],
    'allowed_methods' => ['GET', 'POST', 'PUT', 'DELETE'],
    'allowed_headers' => ['Content-Type', 'Authorization'],
    'allow_credentials' => false,
],

Universal Settings System

Flexible settings system supporting app-wide, per-user, and per-model settings.

App-Wide Settings

Use the Settings facade for application-level settings:

use Bywyd\LaravelQol\Facades\Settings;

// Set settings
Settings::set('site_name', 'My Application');
Settings::set('items_per_page', 25);
Settings::set('maintenance_mode', false);
Settings::set('features', ['api', 'webhooks', 'exports']);

// Organize by groups
Settings::set('smtp_host', 'smtp.gmail.com', 'email');
Settings::set('smtp_port', 587, 'email');
Settings::set('theme_color', '#FF5733', 'appearance');

// Get settings
$siteName = Settings::get('site_name');
$perPage = Settings::get('items_per_page', 10); // with default

// Get all settings in a group
$emailSettings = Settings::getGroup('email');
// ['smtp_host' => 'smtp.gmail.com', 'smtp_port' => 587]

// Check if exists
if (Settings::has('api_key')) {
    //
}

// Remove setting
Settings::remove('old_setting');

// Set multiple at once
Settings::setMultiple([
    'key1' => 'value1',
    'key2' => 'value2',
], 'group_name');

// Increment/Decrement numeric values
Settings::increment('page_views');
Settings::decrement('credits', 5);

// Toggle boolean values
Settings::toggle('feature_enabled');

// Store with metadata
Settings::set('api_key', 'secret', 'api', true, [
    'description' => 'Third-party API key',
    'editable' => false,
]);

Per-User Settings

Add the HasSettings trait to your User model:

use Bywyd\LaravelQol\Traits\HasSettings;

class User extends Authenticatable
{
    use HasSettings;
}

// Set user preferences
$user->setSetting('theme', 'dark');
$user->setSetting('language', 'es');
$user->setSetting('notifications_enabled', true);
$user->setSetting('email_frequency', 'daily', 'notifications');

// Get user settings
$theme = $user->getSetting('theme', 'light'); // with default
$language = $user->getSetting('language');

// Organize by groups
$user->setSetting('push_enabled', true, 'notifications');
$user->setSetting('email_enabled', false, 'notifications');
$notificationSettings = $user->getSettingsGroup('notifications');

// Get all user settings
$allSettings = $user->getAllSettings();
// ['general.theme' => 'dark', 'general.language' => 'es', ...]

// Public settings (visible to others)
$user->setSetting('profile_visibility', 'public', 'privacy', true);
$publicSettings = $user->getAllSettings(true); // only public

// Batch operations
$user->setSettings([
    'theme' => 'dark',
    'font_size' => 'medium',
    'compact_mode' => true,
], 'appearance');

// Clear settings
$user->clearSettings(); // all
$user->clearSettings('notifications'); // specific group

// Numeric operations
$user->incrementSetting('posts_count');
$user->decrementSetting('credits', 10);

// Boolean operations
$user->toggleSetting('notifications_enabled');

Per-Model Settings

Add the HasSettings trait to any model:

use Bywyd\LaravelQol\Traits\HasSettings;

class Post extends Model
{
    use HasSettings;
}

$post = Post::find(1);

// Model-specific settings
$post->setSetting('featured', true);
$post->setSetting('visibility', 'public');
$post->setSetting('allow_comments', true);
$post->setSetting('views_count', 0, 'analytics');

// Get settings
$featured = $post->getSetting('featured', false);
$visibility = $post->getSetting('visibility');

// Analytics example
$post->incrementSetting('views_count', 1, 'analytics');
$post->setSetting('last_viewed_at', now(), 'analytics');

$analytics = $post->getSettingsGroup('analytics');
// ['views_count' => 150, 'last_viewed_at' => '2024-01-01 12:00:00']

Settings Features

Type Support:

  • String
  • Integer
  • Float
  • Boolean
  • Array
  • JSON

Automatic Caching:

  • Settings are cached automatically
  • Cache cleared on update/delete
  • Configurable TTL

Organization:

  • Group settings logically
  • Isolate by model instance
  • Public vs private settings

Metadata:

  • Store additional info about settings
  • Descriptions, editability flags, etc.

Real-World Examples

// E-commerce: Product settings
$product->setSetting('on_sale', true);
$product->setSetting('discount_percentage', 20);
$product->setSetting('stock_alert_threshold', 5, 'inventory');

// Blog: Post settings
$post->setSetting('featured', true);
$post->setSetting('allow_comments', false);
$post->setSetting('publish_at', '2024-12-25 00:00:00', 'scheduling');

// SaaS: Organization settings
$organization->setSetting('max_users', 50, 'limits');
$organization->setSetting('api_enabled', true, 'features');
$organization->setSetting('webhook_url', 'https://...', 'integrations');

// Multi-tenant: Tenant customization
$tenant->setSetting('primary_color', '#FF5733', 'branding');
$tenant->setSetting('logo_url', 'https://...', 'branding');
$tenant->setSetting('custom_domain', 'tenant.example.com', 'domain');

// User preferences dashboard
$preferences = $user->getSettingsGroup('preferences');
foreach ($preferences as $key => $value) {
    echo "{$key}: {$value}";
}

CommonScopes Trait

Add powerful query scopes to your models:

use Bywyd\LaravelQol\Traits\CommonScopes;

class Product extends Model
{
    use CommonScopes;
}

// Usage examples:
Product::active()->get();
Product::recent(7)->get(); // Last 7 days
Product::thisMonth()->get();
Product::popular('views_count', 100)->get();
Product::published()->get();
Product::whereLike('search term', ['name', 'description'])->get();
Product::smartPaginate(20); // Auto-handles per_page from request

Available scopes: active(), inactive(), recent(), older(), today(), thisWeek(), thisMonth(), thisYear(), betweenDates(), latest(), oldest(), whereIds(), whereNotIds(), whereLike(), whereEmpty(), whereNotEmpty(), random(), popular(), featured(), published(), draft(), smartPaginate()

ApiResponse Trait

Standardized API responses for controllers:

use Bywyd\LaravelQol\Traits\ApiResponse;

class UserController extends Controller
{
    use ApiResponse;

    public function index()
    {
        $users = User::paginate();
        return $this->paginated($users, 'Users retrieved successfully');
    }

    public function store(Request $request)
    {
        $user = User::create($request->validated());
        return $this->created($user, 'User created successfully');
    }

    public function show(User $user)
    {
        return $this->success($user);
    }

    public function update(Request $request, User $user)
    {
        $user->update($request->validated());
        return $this->updated($user);
    }

    public function destroy(User $user)
    {
        $user->delete();
        return $this->deleted();
    }
}

Available methods: success(), error(), created(), updated(), deleted(), notFound(), unauthorized(), forbidden(), validationError(), serverError(), paginated(), noContent()

Request Macros

Enhanced request handling:

// Check if any of the keys exist
if (request()->hasAny(['email', 'username'])) {
    // ...
}

// Check if all keys exist
if (request()->hasAll(['name', 'email', 'password'])) {
    // ...
}

// Get boolean value (handles 'true', '1', 'yes', 'on')
$active = request()->boolean('is_active', false);

// Get array of IDs from comma-separated or array
$ids = request()->ids('user_ids'); // "1,2,3" or [1,2,3] => [1,2,3]

// Get sanitized search term
$search = request()->search('q');

// Get real IP (considering proxies, Cloudflare, etc.)
$ip = request()->realIp();

// Check if mobile device
if (request()->isMobile()) {
    // ...
}

// Get sort parameters
$sort = request()->sort('created_at', 'desc');
// Returns: ['column' => 'created_at', 'direction' => 'desc']

// Get filters (removes empty values)
$filters = request()->filters(['status', 'category', 'price_min']);

Collection Macros

Extended collection functionality:

// Recursively convert to array
$data = collect($nested)->recursive()->toArray();

// Group by multiple keys
$grouped = $users->groupByMultiple(['country', 'city']);

// Export to CSV
$csv = $users->toCsv(['ID', 'Name', 'Email']);

// Check for duplicates
if ($items->hasDuplicates('email')) {
    // ...
}

// Transpose (rows to columns)
$transposed = collect([[1, 2], [3, 4]])->transpose();
// Result: [[1, 3], [2, 4]]

// Get statistics
$stats = $numbers->stats();
// Returns: ['count', 'sum', 'avg', 'min', 'max', 'median']

// Filter null/empty values
$filtered = $collection->filterNull()->filterEmpty();

// Manual pagination
$paginated = $collection->paginate(15);

Validation Rules

Custom validation rules:

use Bywyd\LaravelQol\Rules\PhoneNumber;
use Bywyd\LaravelQol\Rules\StrongPassword;
use Bywyd\LaravelQol\Rules\Username;

// Phone number validation
'phone' => ['required', new PhoneNumber()],

// Strong password validation
'password' => [
    'required',
    new StrongPassword(
        minLength: 8,
        requireUppercase: true,
        requireLowercase: true,
        requireNumbers: true,
        requireSpecialChars: true
    )
],

// Username validation
'username' => [
    'required',
    new Username(
        minLength: 3,
        maxLength: 20,
        allowDash: true,
        allowUnderscore: true,
        allowDot: false
    )
],

Helper Functions

Global utility functions:

// Limit words in string
$excerpt = str_limit_words($text, 10);

// Simple money formatting
$price = money_format_simple(1234.56, '$', 2); // "$1,234.56"

// Calculate percentage
$percent = percentage(25, 100); // 25.00

// Filter array recursively
$filtered = array_filter_recursive($array);

// Sanitize filename
$safe = sanitize_filename('My File (1).pdf'); // "My_File_1.pdf"

// Generate random string
$token = generate_random_string(32); // Alphanumeric
$password = generate_random_string(16, false); // With special chars

// Convert bytes to human readable
$size = bytes_to_human(1048576); // "1.00 MB"

// Convert human readable to bytes
$bytes = human_to_bytes('10MB'); // 10485760

// Check if string is valid JSON
if (is_json($string)) {
    // ...
}

// Safe Carbon parsing
$date = carbon_parse_safe($input, now());

// Active route helper (for navigation)
<li class="{{ active_route(['users.*', 'profile']) }}">Users</li>

// Get client browser
$browser = get_client_browser(); // "Chrome", "Firefox", etc.

// Truncate middle of string
$truncated = truncate_middle('very-long-filename.txt', 20); // "very-long...ame.txt"

Database Utilities

QueryLogger

Log and analyze database queries:

use Bywyd\LaravelQol\Utilities\QueryLogger;

// Enable query logging
QueryLogger::enable();

// Your code here...
User::all();
Post::with('comments')->get();

// Get all queries
$queries = QueryLogger::getQueries();

// Get total execution time
$time = QueryLogger::getTotalTime(); // in milliseconds

// Get query count
$count = QueryLogger::getCount();

// Get slowest queries
$slow = QueryLogger::getSlowestQueries(10);

// Log to file
QueryLogger::logToFile('database');

// Dump for debugging
QueryLogger::dump();

// Clear logged queries
QueryLogger::clear();

// Disable logging
QueryLogger::disable();

ModelUtility

Useful model introspection methods:

use Bywyd\LaravelQol\Utilities\ModelUtility;

// Get table columns
$columns = ModelUtility::getTableColumns(User::class);

// Get fillable columns
$fillable = ModelUtility::getFillableColumns($user);

// Get hidden columns
$hidden = ModelUtility::getHiddenColumns($user);

// Get dirty (changed but not saved) attributes
$dirty = ModelUtility::getDirtyAttributes($user);

// Get changed attributes after save
$changes = ModelUtility::getChangedAttributes($user);

// Check if attribute exists
if (ModelUtility::hasAttribute($user, 'email')) {
    // ...
}

// Clone model
$clone = ModelUtility::cloneModel($user, ['id', 'created_at']);

// Get loaded relations
$relations = ModelUtility::getLoadedRelations($user);

// Check if relation is loaded
if (ModelUtility::isRelationLoaded($user, 'posts')) {
    // ...
}

// Diff two models
$diff = ModelUtility::diff($originalUser, $modifiedUser);
// Returns: ['email' => ['old' => 'old@example.com', 'new' => 'new@example.com']]

Usage Examples

Example 1: API Controller with All Features

use App\Models\Product;
use Bywyd\LaravelQol\Traits\ApiResponse;
use Bywyd\LaravelQol\Rules\StrongPassword;
use Illuminate\Http\Request;

class ProductController extends Controller
{
    use ApiResponse;

    public function index(Request $request)
    {
        $query = Product::query();

        // Use CommonScopes
        if ($request->boolean('active_only')) {
            $query->active();
        }

        if ($search = $request->search('q')) {
            $query->whereLike($search, ['name', 'description']);
        }

        // Use Request macros for sorting
        $sort = $request->sort('created_at', 'desc');
        $query->orderBy($sort['column'], $sort['direction']);

        // Smart pagination
        $products = $query->smartPaginate();

        return $this->paginated($products, 'Products retrieved successfully');
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'name' => 'required|string|max:255',
            'price' => 'required|numeric|min:0',
            'is_active' => 'boolean',
        ]);

        $product = Product::create($validated);

        return $this->created($product, 'Product created successfully');
    }
}

Example 2: Using Utilities for Performance Monitoring

use Bywyd\LaravelQol\Utilities\QueryLogger;

// In a middleware or service provider
if (app()->environment('local')) {
    QueryLogger::enable();

    app()->terminating(function () {
        if (QueryLogger::getCount() > 50) {
            logger()->warning('High query count detected', [
                'total_queries' => QueryLogger::getCount(),
                'total_time' => QueryLogger::getTotalTime(),
                'slowest' => QueryLogger::getSlowestQueries(5),
            ]);
        }
    });
}

Example 3: Model with All Traits

use Illuminate\Database\Eloquent\Model;
use Bywyd\LaravelQol\Traits\{
    HasHistory,
    HasRoles,
    HasSettings,
    HasUuid,
    HasSlug,
    HasStatus,
    Sortable,
    Cacheable,
    Searchable,
    CommonScopes
};

class Article extends Model
{
    use HasHistory,
        HasRoles,
        HasSettings,
        HasUuid,
        HasSlug,
        HasStatus,
        Sortable,
        Cacheable,
        Searchable,
        CommonScopes;

    protected $fillable = ['title', 'content', 'status'];
    protected $slugSource = 'title';
    protected $searchable = ['title', 'content'];

    // Now you have access to all features:
    // - History tracking
    // - Role-based permissions
    // - Per-model settings
    // - UUID primary key
    // - Auto-generated slugs
    // - Status management
    // - Sortable ordering
    // - Model caching
    // - Full-text search
    // - Query scopes
}

// Usage
$article = Article::create(['title' => 'My Article', 'content' => '...']);
$article->logHistory(HistoryLogTypes::CUSTOM, 'Published');
$article->setSetting('views_count', 0);
$articles = Article::active()->published()->thisMonth()->get();

Available Traits

Media Traits

  • HasImages - Image management with ordering, tagging, and URLs
  • HasFiles - Generic file management with type detection
  • HasVideos - Video management with metadata and thumbnails

Model Enhancement Traits

  • HasHistory - Automatic change tracking with old/new values
  • HasRoles - Complete role & permission system with middleware and Blade directives
  • HasIntegrations - OAuth, API keys, and third-party service credentials
  • HasUuid - Auto-generate UUIDs on model creation
  • HasSlug - Auto-generate unique slugs from any field
  • HasStatus - Active/inactive status management
  • Sortable - Ordering and reordering functionality
  • Cacheable - Model-level caching with auto-invalidation
  • Searchable - Simple and full-text search

Authorization System

  • Role Model - Hierarchical roles with level-based access
  • Permission Model - Granular permission control with groups
  • Route Middleware - role, permission, role_or_permission
  • Blade Directives - @role, @permission, @hasanyrole, etc.
  • Laravel Gates - Auto-registered from permissions
  • Super Admin - Wildcard permission support

Requirements

  • PHP 8.1 or higher
  • Laravel 10.0 or higher

License

The MIT License (MIT). Please see License File for more information.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

统计信息

  • 总下载量: 5
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 0
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-12-09