ale95m / easy
API development package with laravel
Installs: 152
Dependents: 0
Suggesters: 0
Security: 0
Stars: 2
Watchers: 2
Forks: 0
Open Issues: 0
pkg:composer/ale95m/easy
Requires
- php: ^8.2
- laravel/framework: ^10.0|^11.0|^12.0
Requires (Dev)
- mockery/mockery: ^1.6
- orchestra/testbench: ^8.0|^9.0|^10.0
- phpunit/phpunit: ^10.5|^11.0
- dev-main
- 4.0.0
- 3.0.4
- 3.0.3
- 3.0.2
- 3.0.1
- 3.0.0
- 2.7.21
- 2.7.20
- 2.7.10
- 2.7.9
- 2.7.8
- 2.7.7
- 2.7.6
- 2.7.5
- 2.7.4
- 2.7.3
- 2.7.2
- 2.7.1
- 2.7.0
- 2.6.0
- 2.5.4
- 2.5.3
- 2.5.2
- 2.5.1
- 2.5.0
- 2.4.1
- 2.4.0
- 2.3.1
- 2.3.0
- 2.2.6
- 2.2.5
- 2.2.4
- 2.2.3
- 2.2.2
- 2.2.1
- 2.2.0
- 2.1.9
- 2.1.8
- 2.1.7
- 2.1.6
- 2.1.5
- 2.1.4
- 2.1.3
- 2.1.2
- 2.1.1
- 2.1.0
- 2.0.1
- 2.0.0
- 1.2.0
- 1.1.0
- 1.0.3
- 1.0.2
- 1.0.1
- 1.0.0
This package is auto-updated.
Last update: 2025-11-15 00:40:40 UTC
README
Speed up your Laravel API development with repositories, controllers, advanced filtering, and automatic logging.
Features
- ✅ Repository Pattern - Pre-built base repository with CRUD operations
- ✅ Advanced Filtering - Multiple operators (=, like, >, <, >=, <=, null) and relation filtering
- ✅ RESTful Controllers - Ready-to-use controller with all REST methods
- ✅ Flexible Authentication - Driver-based system supporting Passport, Sanctum, JWT, and Session
- ✅ Automatic Logging - Track all model changes with user and IP tracking
- ✅ Code Generators - Artisan commands to generate repositories, controllers, models, and seeders
- ✅ Soft Deletes Support - Built-in soft delete handling
- ✅ Excel Export - Export data to Excel with custom formatting
- ✅ Well Tested - 80+ tests ensuring reliability
Table of Contents
- Installation
- Quick Start
- Core Concepts
- Artisan Commands
- Configuration
- Testing
- Examples
- Documentation
Installation
Requirements
- PHP >= 8.2
- Laravel 10.x, 11.x, or 12.x
Install via Composer
composer require ale95m/laravel-easy
Run Migrations
Easy includes migrations for logs and files tables:
php artisan migrate
Publish Configuration (Optional)
php artisan vendor:publish --tag=easy-config
Quick Start
Create a complete CRUD in 5 minutes:
1. Create Everything at Once
# Create model with migration, repository, controller, and seeder php artisan easy:model Post -m -r -c -s # Or use the shorthand --easy flag php artisan easy:model Post --easy
This single command creates:
app/Models/Post.php- Modeldatabase/migrations/*_create_posts_table.php- Migrationapp/Repositories/PostRepository.php- Repositoryapp/Http/Controllers/PostController.php- Controllerdatabase/seeders/PostSeeder.php- Seeder
2. Define Migration
Schema::create('posts', function (Blueprint $table) { $table->id(); $table->string('title'); $table->text('content'); $table->string('status')->default('draft'); $table->foreignId('user_id')->constrained(); $table->timestamps(); $table->softDeletes(); });
Run migration:
php artisan migrate
3. Configure Repository
Edit app/Repositories/PostRepository.php to add filters:
<?php namespace App\Repositories; use App\Models\Post; use Easy\Repositories\EasyRepository; use Illuminate\Database\Eloquent\Model; class PostRepository extends EasyRepository { protected array $filters = [ 'title:like', 'status', 'user_id', 'created_at:>', 'created_at:<', ]; protected array $sortable_fields = ['title', 'created_at']; protected ?string $orderBy = 'created_at'; protected bool $orderByAsc = false; protected bool $allow_load_deleted = true; public function getModel(): Model { return new Post(); } }
4. Add Validation (Optional)
Edit app/Http/Controllers/PostController.php to add validation:
public function store(Request $request) { $request->validate([ 'title' => 'required|string|max:255', 'content' => 'required', 'status' => 'in:draft,published', 'user_id' => 'required|exists:users,id', ]); return $this->baseStore($request); }
5. Add Routes
In routes/api.php:
use App\Http\Controllers\PostController; Route::middleware('auth:sanctum')->group(function () { Route::apiResource('posts', PostController::class); Route::post('posts/{id}/restore', [PostController::class, 'restore']); });
6. Test Your API!
# List all posts GET /api/posts # Create a post POST /api/posts { "title": "My First Post", "content": "Hello World!", "status": "published", "user_id": 1 } # Get a single post GET /api/posts/1 # Update a post PUT /api/posts/1 { "title": "Updated Title" } # Delete a post (soft delete) DELETE /api/posts/1 # Restore a deleted post POST /api/posts/1/restore # Filter by status GET /api/posts?status=published # Search by title GET /api/posts?title:like=%Laravel% # Sort results GET /api/posts?sort_by=title&sort_asc=true # Include soft-deleted GET /api/posts?with_deleted=true
Core Concepts
Easy Repository
The EasyRepository is an abstract base class that implements the Repository Pattern with powerful features.
Basic Usage
<?php namespace App\Repositories; use App\Models\User; use Easy\Repositories\EasyRepository; use Illuminate\Database\Eloquent\Model; class UserRepository extends EasyRepository { protected array $filters = [ 'name:like', 'email:like', 'status', 'age:>', 'age:<', ]; protected array $sortable_fields = ['name', 'email', 'created_at']; protected ?string $orderBy = 'created_at'; protected bool $orderByAsc = false; public function getModel(): Model { return new User(); } }
Available Methods
// Create $user = $repository->create($data, $log = true); // Find $user = $repository->findOrFail($id); // Update $repository->update($user, $data, $log = true); // Delete (soft delete) $repository->delete($user, $log = true); // Restore $repository->restore($id); // Search with filters $query = $repository->search([ 'name:like' => '%John%', 'age:>' => 18, 'status' => 'active', ]); $results = $query->get();
Configuration Properties
protected array $filters = []; // Filterable fields protected array $filters_alias = []; // Filter aliases protected array $sortable_fields = []; // Sortable fields protected ?string $orderBy = null; // Default sort field protected bool $orderByAsc = true; // Default sort direction protected ?array $relationships = null; // Auto-load relationships protected array $select_fields = ['*']; // Fields to select protected bool $allow_load_deleted = false; // Enable soft delete filtering protected bool $use_uuid = false; // Use UUID as primary key protected array $checkDelete = []; // Relations to check before delete
Helper Hooks
Override these methods to add custom logic:
protected function creating(array &$data): void { // Runs before create $data['created_by'] = auth()->id(); } protected function created(Model &$model, array &$data): void { // Runs after create } protected function updating(Model &$model, array &$data): void { // Runs before update } protected function updated(Model &$model, array &$data): void { // Runs after update } protected function deleting(Model &$model): void { // Runs before delete } protected function deleted(Model &$model): void { // Runs after delete }
Easy Controller
The EasyController provides ready-to-use RESTful endpoints.
Basic Usage
<?php namespace App\Http\Controllers; use App\Repositories\UserRepository; use Easy\Http\Controllers\EasyController; class UserController extends EasyController { protected array $uniqueFields = ['email']; protected bool $use_logs = true; public function __construct() { $this->repository = new UserRepository(); } }
Available Methods
All these methods are inherited from EasyController:
index(Request $request)- List all resources with filteringstore(Request $request)- Create a new resourceshow($id)- Get a single resourceupdate(Request $request, $id)- Update a resourcedestroy($id)- Delete a resource (soft delete)restore($id)- Restore a soft-deleted resourcepaginate(PaginateRequest $request)- Get paginated results
Custom Validation
public function store(Request $request): JsonResponse { $request->validate([ 'name' => 'required|string|max:255', 'email' => 'required|email|unique:users', ]); return $this->baseStore($request); }
Filtering System
Easy provides a powerful filtering system with multiple operators.
Filter Operators
protected array $filters = [ 'name', // Exact match: ?name=John 'name:like', // LIKE operator: ?name:like=%John% 'email:like', // LIKE: ?email:like=%@example.com 'age:>', // Greater than: ?age:>=18 'age:<', // Less than: ?age:<65 'age:>=', // Greater or equal: ?age:>=18 'age:<=', // Less or equal: ?age:<=65 'status:null', // IS NULL / IS NOT NULL: ?status:null=true ];
Relation Filtering
Filter by relationship fields using the -> syntax:
protected array $filters = [ 'posts->status', // ?posts->status=published 'posts->title:like', // ?posts->title:like=%Laravel% 'posts->views:>', // ?posts->views:>1000 'profile->country', // ?profile->country=USA 'posts->comments->status', // Nested: ?posts->comments->status=approved ];
Filter Aliases
Create friendly names for filters:
protected array $filters_alias = [ 'username' => 'name', 'user_email' => 'email', ]; // Usage: ?username=john (maps to name)
Custom Search Methods
Create custom filter logic:
// In repository protected array $filters = ['active_users']; public function searchByActiveUsers($query, $value) { if ($value) { $query->where('status', 'active') ->whereNotNull('email_verified_at'); } } // Usage: ?active_users=true
Usage Examples
// Simple filter $users = $repository->search(['status' => 'active'])->get(); // Multiple filters $users = $repository->search([ 'status' => 'active', 'age:>' => 18, 'name:like' => '%John%', ])->get(); // Filter by relations $users = $repository->search([ 'posts->status' => 'published', 'posts->views:>' => 1000, ])->get(); // With sorting $users = $repository->search([ 'status' => 'active', 'sort_by' => 'name', 'sort_asc' => true, ])->get(); // With soft deletes $users = $repository->search([ 'with_deleted' => true ])->get();
Complete filtering documentation: docs/filtering-system.md
Authentication System
Easy provides a flexible, driver-based authentication system that works with multiple authentication backends without code changes.
Supported Drivers
- 🔐 Passport - OAuth2 server (
laravel/passport) - 🎫 Sanctum - Simple API tokens (
laravel/sanctum) - 🔑 JWT - JSON Web Tokens (
tymon/jwt-auth) - 📝 Session - Traditional Laravel auth (built-in)
- 🔧 Custom - Build your own driver
Quick Setup
- Choose your driver in
.env:
EASY_AUTH_DRIVER=sanctum # passport|sanctum|jwt|session
- Install driver package (if needed):
# For Sanctum composer require laravel/sanctum php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider" php artisan migrate
- Update your User model:
use Easy\Interfaces\IAuthenticableWithToken; use Easy\Traits\HasTokenAuthentication; use Laravel\Sanctum\HasApiTokens; // For Sanctum class User extends Authenticatable implements IAuthenticableWithToken { use HasApiTokens, HasTokenAuthentication; // Optional: allow login with email OR username protected $authField = ['email', 'username']; }
Usage
Login:
POST /api/login
{
"email": "user@example.com",
"password": "secret"
}
# Response includes token
{
"status": true,
"data": {...},
"token": "eyJ0eXAiOiJKV1QiLCJhbGc..."
}
In your code:
// Get token $token = $user->getToken(); // Revoke token $user->revokeToken(); // Get current driver $driver = $user->getTokenDriver(); // 'sanctum', 'passport', etc.
Direct TokenDriverManager usage:
use Easy\Auth\TokenDriverManager; $token = TokenDriverManager::createToken($user); TokenDriverManager::revokeToken($user);
Create Custom Driver
namespace App\Auth; use Easy\Auth\Contracts\TokenDriverInterface; class MyCustomDriver implements TokenDriverInterface { public function createToken(Model $user, ?string $tokenName = null): string { // Your logic return 'custom-token'; } // ... implement other methods } // Register in config/easy.php 'auth' => [ 'driver' => 'my-custom', 'drivers' => [ 'my-custom' => \App\Auth\MyCustomDriver::class, ], ]
Migration from Old System
The old IAuthenticableOAuth (Passport-specific) is still supported but deprecated. Migrate to the new system:
// Before (Passport only) use Easy\Traits\IsAuthenticableOAuth; // After (Works with any driver) use Easy\Traits\HasTokenAuthentication; use Laravel\Sanctum\HasApiTokens; // or Passport's HasApiTokens class User extends Authenticatable implements IAuthenticableWithToken { use HasApiTokens, HasTokenAuthentication; }
Complete authentication documentation: AUTHENTICATION.md | docs/authentication.md
Logging System
Easy includes automatic logging to track all model changes.
Make Your Model Loggable
<?php namespace App\Models; use Easy\Interfaces\ILogable; use Easy\Traits\HasLogs; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; class Post extends Model implements ILogable { use SoftDeletes, HasLogs; protected $fillable = ['title', 'content', 'status']; // Define which attributes should be logged protected $logableAttributes = ['title', 'content', 'status']; }
Enable Logging in Operations
// In controller or repository $post = $repository->create($data, true); // true = create log $repository->update($post, $changes, true); // true = create log $repository->delete($post, true); // true = create log
Log Structure
Each log entry contains:
{
"id": 1,
"action": "create|update|delete|login|logout",
"model": "post",
"attributes": "{json}",
"changes": "{json}",
"ip": "192.168.1.1",
"user_id": 1,
"logable_type": "App\\Models\\Post",
"logable_id": 5,
"created_at": "2024-01-15 10:30:00"
}
Retrieve Logs
// Get logs for a model $logs = $post->logs()->get(); // Get logs with filters use Easy\Repositories\LogRepository; $logRepository = new LogRepository(); $logs = $logRepository->search([ 'model:like' => '%Post%', 'action' => 'update', 'created_at:>' => '2024-01-01' ])->get();
Manual Logging
use Easy\Repositories\LogRepository; // Log login LogRepository::logInAction(); // Log logout LogRepository::logOutAction(); // Custom log LogRepository::createLog('custom_action', 'User', $attributes);
Artisan Commands
Easy provides powerful commands to generate code quickly.
💡 Tip: For complete command reference with advanced examples, see COMMANDS.md
Generate Repository
# Basic php artisan easy:repository UserRepository # With model php artisan easy:repository UserRepository --model=User # Multiple php artisan easy:repository UserRepository PostRepository CommentRepository
Generate Controller
# Basic php artisan easy:controller UserController # With repository php artisan easy:controller UserController --repository=UserRepository # Multiple php artisan easy:controller UserController PostController
Generate Model
The most powerful command - create models with all related files.
# Individual options php artisan easy:model Post -m # With migration php artisan easy:model Post -r # With repository php artisan easy:model Post -c # With controller (creates repository too) php artisan easy:model Post -s # With seeder (requires repository) # Combine options freely php artisan easy:model Post -m -r # Model + Migration + Repository php artisan easy:model Post -m -r -c # Model + Migration + Repository + Controller php artisan easy:model Post -m -r -c -s # Everything # Easy Mode (equivalent to -m -r -c -s) php artisan easy:model Post --easy # Create multiple models at once with any combination php artisan easy:model Post Comment Tag -m -r -c -s php artisan easy:model Product Category Brand --easy php artisan easy:model User Post Comment -m -r # Real-world example - complete blog structure php artisan easy:model Post Category Tag Comment -m -r -c -s # This creates for EACH model: # - Model file (Post.php, Category.php, Tag.php, Comment.php) # - Migration (create_posts_table, create_categories_table, etc.) # - Repository (PostRepository, CategoryRepository, etc.) # - Controller (PostController, CategoryController, etc.) # - Seeder (PostSeeder, CategorySeeder, etc.)
Options:
-m, --migration- Create migration-r, --repository- Create repository-c, --controller- Create controller (automatically creates repository if needed)-s, --seeder- Create seeder (automatically creates repository if needed)-e, --easy- Create all of the above (equivalent to-m -r -c -s)
Generate Seeder
php artisan easy:seeder UserSeeder --repository=UserRepository
Interactive Create
php artisan easy:create
This interactive command will guide you through creating a complete CRUD.
Configuration
After publishing the configuration (php artisan vendor:publish --tag=easy-config), you'll find config/easy.php:
<?php return [ // Authentication 'use_auth' => true, 'api_prefix' => 'api', 'api_middleware' => [], 'auth_middleware' => ['auth'], // Files 'files' => [ 'path' => 'files', 'disk' => 'local', ], // Tables 'tables' => [ 'files' => 'easy_files', 'logs' => 'easy_logs', ], // Pagination 'pagination' => [ 'input' => [ 'items_per_page' => 'itemsPerPage', 'current_page' => 'page', ], 'output' => [ 'items_per_page' => 'itemsPerPage', 'current_page' => 'page', 'items_length' => 'itemsLength', 'page_count' => 'pageCount', ] ], // Query parameters 'query' => [ 'sort_by' => 'sort_by', 'sort_asc' => 'sort_asc', 'only_deleted' => 'only_deleted', 'with_deleted' => 'with_deleted', ], // Project directories 'project_directories' => [ 'models' => 'App\\Models', 'controllers' => 'App\\Http\\Controllers', 'repositories' => 'App\\Repositories', 'seeders' => 'Database\\Seeders', ], ];
Testing
Easy includes a comprehensive test suite with 75+ tests.
Run Tests
# Install dependencies composer install # Run all tests composer test # Run with test documentation vendor/bin/phpunit --testdox # Run specific test suite vendor/bin/phpunit --testsuite=Feature # With coverage composer test-coverage
Test Coverage
- ✅ Artisan commands (repository, controller, seeder generation)
- ✅ Repository CRUD operations
- ✅ Advanced filtering (all operators, relations, aliases)
- ✅ Controller REST methods
- ✅ Logging system (create, update, delete logs)
- ✅ Soft deletes
- ✅ Custom search methods
For more information, see TESTING.md
Examples
Blog System with Relations
// Post Model class Post extends Model implements ILogable { use SoftDeletes, HasLogs; protected $fillable = ['title', 'content', 'status', 'user_id', 'category_id']; protected $logableAttributes = ['title', 'content', 'status']; public function user() { return $this->belongsTo(User::class); } public function category() { return $this->belongsTo(Category::class); } public function tags() { return $this->belongsToMany(Tag::class); } } // Post Repository class PostRepository extends EasyRepository { protected array $filters = [ 'title:like', 'status', 'user_id', 'category_id', 'created_at:>', 'created_at:<', 'user->name:like', // Filter by author name 'category->name', // Filter by category 'tags->name', // Filter by tag ]; protected ?array $relationships = ['user:id,name', 'category:id,name', 'tags']; protected bool $allow_load_deleted = true; public function getModel(): Model { return new Post(); } // Custom search public function searchByPopular($query, $value) { if ($value) { $query->where('views', '>', 1000)->orderBy('views', 'desc'); } } } // Usage Examples // Filter by author GET /api/posts?user->name:like=%John% // Filter by category GET /api/posts?category->name=Technology // Filter by tag GET /api/posts?tags->name=Laravel // Get popular posts GET /api/posts?popular=true // Combined filters GET /api/posts?status=published&category->name=Tech&created_at:>2024-01-01
E-commerce Product Management
// Product Repository class ProductRepository extends EasyRepository { protected array $filters = [ 'name:like', 'sku', 'is_active', 'price:>', 'price:<', 'stock:>', 'stock:<', 'category->name', ]; protected array $sortable_fields = ['name', 'price', 'stock', 'created_at']; public function getModel(): Model { return new Product(); } public function searchByInStock($query, $value) { if ($value) { $query->where('stock', '>', 0)->where('is_active', true); } } public function searchByLowStock($query, $value) { if ($value) { $query->where('stock', '>', 0)->where('stock', '<', 10); } } } // Usage GET /api/products?in_stock=true GET /api/products?low_stock=true GET /api/products?price:>=10&price:<=100 GET /api/products?category->name=Electronics
User Management with Custom Validation
// User Controller class UserController extends EasyController { protected array $uniqueFields = ['email']; protected bool $use_logs = true; public function __construct() { $this->repository = new UserRepository(); } public function store(Request $request): JsonResponse { $request->validate([ 'name' => 'required|string|max:255', 'email' => 'required|email|unique:users', 'password' => 'required|min:8', ]); $request->merge([ 'password' => Hash::make($request->password) ]); return $this->baseStore($request); } public function update(Request $request, $id): JsonResponse { $request->validate([ 'email' => 'sometimes|email|unique:users,email,'.$id, 'password' => 'sometimes|min:8', ]); if ($request->has('password')) { $request->merge([ 'password' => Hash::make($request->password) ]); } return $this->baseUpdate($request, $id); } }
Advanced Features
Excel Export
If your repository uses the ExportableToExcel trait:
use Easy\Traits\ExportableToExcel; class UserRepository extends EasyRepository { use ExportableToExcel; // ... your repository code } // In controller use Easy\Http\Requests\ExportExcelRequest; public function export(ExportExcelRequest $request) { return $this->repository->exportExcel($request->all()); }
Authentication
Easy includes authentication traits:
use Easy\Interfaces\IAuthenticable; use Easy\Traits\IsAuthenticable; class User extends Model implements IAuthenticable { use IsAuthenticable; // ... your model code }
File Management
Easy includes a file management system with the FileController and FileRepository.
Best Practices
- Always use filter definitions - Only allow filtering on indexed fields
- Enable logging on important operations - Track changes to sensitive data
- Use soft deletes - Maintain data integrity and audit trail
- Validate unique fields - Prevent duplicates at controller level
- Eager load relationships - Prevent N+1 queries
- Use custom search methods - Keep complex logic in repositories
- Index filtered fields - Add database indexes for performance
- Paginate large datasets - Always paginate in production
Documentation
📚 Full Documentation - Complete documentation with examples, guides, and API reference
Documentation Files
- 📖 README.md - Complete package overview and quick reference
- ⚡ COMMANDS.md - Detailed Artisan commands reference with examples
- 🔐 AUTHENTICATION.md - Flexible authentication system guide
- ⬆️ UPGRADE.md - Upgrade guide from 1.x to 2.x
- 🚀 LARAVEL_12_READINESS.md - Laravel 12 readiness guide
- 🧪 TESTING.md - Testing guide for contributors
- 💡 EXAMPLES.md - Real-world practical examples
Quick Links
- Getting Started: Installation & Quick Start
- Artisan Commands: Commands Guide
- API Filtering: Filtering System
- Authentication: Authentication System
- Automatic Logging: Logging System
- FAQ: Frequently Asked Questions
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Development Setup
git clone https://github.com/ale95m/laravel-easy.git cd laravel-easy composer install composer test
License
The Easy package is open-sourced software licensed under the MIT license.
Credits
- Author: ale95m
- Contributors: All Contributors
Support
- Documentation: https://ale95m.github.io/laravel-easy
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Made with ❤️ for the Laravel community