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
其他信息
- 授权协议: MIT
- 更新时间: 2025-12-09