Development Guide
Development workflow, best practices, and common tasks for ZÈYA API.
Development Workflow
1. Create Feature Branch
git checkout -b feature/your-feature-name
2. Make Changes
Follow Laravel conventions and coding standards (see Contributing).
3. Write Tests
# Create test file
php artisan make:test ProductTest
# Run tests
php artisan test --filter ProductTest
4. Format Code
# Format code with Laravel Pint
php artisan pint
# Check without fixing
php artisan pint --test
5. Commit Changes
git add .
git commit -m "feat: add product search feature"
6. Push and Create PR
git push origin feature/your-feature-name
Code Quality
Laravel Pint
Laravel Pint is used for code formatting:
# Format all files
php artisan pint
# Format specific file
php artisan pint app/Http/Controllers/ProductController.php
# Check without fixing
php artisan pint --test
PHPUnit Testing
# Run all tests
php artisan test
# Run specific test file
php artisan test --filter ProductTest
# Run with coverage
php artisan test --coverage
# Run specific test method
php artisan test --filter test_can_create_product
Common Development Tasks
Creating a New Feature
- Create Migration
php artisan make:migration create_products_table
- Create Model
php artisan make:model Product -m
- Create Controller
php artisan make:controller ProductController --api --resource
- Create Form Request
php artisan make:request StoreProductRequest
php artisan make:request UpdateProductRequest
- Create API Resource
php artisan make:resource ProductResource
- Create Service
# Manual creation in app/Services/ProductService.php
- Add Routes
// routes/api.php
Route::apiResource('products', ProductController::class);
- Write Tests
php artisan make:test ProductTest
Database Operations
# Run migrations
php artisan migrate
# Rollback last migration
php artisan migrate:rollback
# Rollback all migrations
php artisan migrate:reset
# Fresh migration with seeding
php artisan migrate:fresh --seed
# Create migration
php artisan make:migration add_column_to_products_table
# Create seeder
php artisan make:seeder ProductSeeder
# Run seeder
php artisan db:seed --class=ProductSeeder
Queue Development
# Run queue worker
php artisan queue:work
# Run specific queue
php artisan queue:work --queue=high,default
# Run with specific connection
php artisan queue:work redis
# Restart workers after code changes
php artisan queue:restart
# View failed jobs
php artisan queue:failed
# Retry failed job
php artisan queue:retry {job-id}
# Clear failed jobs
php artisan queue:flush
Cache Management
# Clear all caches
php artisan optimize:clear
# Cache configuration
php artisan config:cache
# Clear config cache
php artisan config:clear
# Cache routes
php artisan route:cache
# Clear route cache
php artisan route:clear
# Cache views
php artisan view:cache
# Clear view cache
php artisan view:clear
# Clear specific cache
php artisan cache:clear
Logging
# View logs
tail -f storage/logs/laravel.log
# Clear logs (be careful!)
> storage/logs/laravel.log
Debugging
Tinker
Laravel Tinker for interactive debugging:
php artisan tinker
# Example usage
>>> $user = User::find(1);
>>> $user->products;
Debugging Tools
- Laravel Debugbar (if installed)
- dd() - Dump and die
- dump() - Dump without dying
- Log::debug() - Log to file
Common Debugging Commands
# Check routes
php artisan route:list
# Check config
php artisan config:show database
# Check environment
php artisan env
# Clear everything
php artisan optimize:clear
Local Development Setup
Environment Variables
Use .env for local development:
APP_ENV=local
APP_DEBUG=true
Database Seeding
# Seed database
php artisan db:seed
# Seed specific seeder
php artisan db:seed --class=UserSeeder
Mail Testing
Use Mailtrap or similar for local mail testing:
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=your-username
MAIL_PASSWORD=your-password
Best Practices
1. Use Form Requests
Always use Form Requests for validation:
// ✅ Good
public function store(StoreProductRequest $request)
{
$validated = $request->validated();
// ...
}
// ❌ Bad
public function store(Request $request)
{
$request->validate([
'title' => 'required',
]);
// ...
}
2. Use Services for Business Logic
Keep controllers thin:
// ✅ Good
public function store(StoreProductRequest $request, ProductService $service)
{
$product = $service->createProduct($request->validated(), $request->user());
return new ProductResource($product);
}
// ❌ Bad
public function store(StoreProductRequest $request)
{
// 50 lines of business logic here
}
3. Use API Resources
Transform responses consistently:
// ✅ Good
return new ProductResource($product);
// ❌ Bad
return response()->json([
'id' => $product->id,
'title' => $product->title,
// ...
]);
4. Eager Load Relationships
Prevent N+1 queries:
// ✅ Good
$products = Product::with(['owner', 'category', 'images'])->get();
// ❌ Bad
$products = Product::all();
foreach ($products as $product) {
$product->owner; // N+1 query!
}
5. Use Transactions
For multiple database operations:
DB::transaction(function () use ($data) {
$product = Product::create($data);
$product->images()->createMany($imageData);
});
Related Documentation
- Contributing - Code standards and guidelines
- Architecture - System architecture
- Setup & Installation - Initial setup