This document outlines the standard workflow and conventions for developing new features in the Sjoppie API project.
app/
├── Http/
│ ├── Controllers/
│ │ └── Api/ # API controllers
│ ├── Middleware/ # Custom middleware
│ └── Requests/ # Form requests
├── Models/ # Eloquent models
├── Services/ # Business logic services
└── Resources/ # API resources
- Create a new migration:
php artisan make:migration create_table_name_table- Always include:
timestamps()softDeletes()if the model should support soft deletion- Proper indexes
- Foreign key constraints where needed
- Create model with migration:
php artisan make:model ModelName -m- Model requirements:
- Use
HasFactoryandSoftDeletestraits when needed - Define
$fillableproperties - Define
$castsfor JSON, boolean, etc. - Add relationships
- Add accessors/mutators if needed
Example:
class ModelName extends Model
{
use HasFactory, SoftDeletes;
protected $fillable = [
'field1',
'field2',
];
protected $casts = [
'is_active' => 'boolean',
'settings' => 'array',
];
public function relatedModel()
{
return $this->belongsTo(RelatedModel::class);
}
}- Create a service class in
app/Services/ - Services should:
- Handle business logic
- Use dependency injection
- Be testable
- Use caching when appropriate
- Follow single responsibility principle
Example:
class ModelNameService
{
public function __construct(
protected RelatedService $relatedService
) {}
public function getResource(): Resource
{
return Cache::remember('cache_key', 3600, function () {
return $this->model->first();
});
}
}- Create controller in
app/Http/Controllers/Api/ - Controllers should:
- Use dependency injection
- Be thin (move logic to services)
- Return standardized responses
- Use form requests for validation
- Follow RESTful conventions
Example:
class ModelNameController extends Controller
{
public function __construct(
protected ModelNameService $service
) {}
public function index(): JsonResponse
{
return response()->json([
'data' => $this->service->getAll(),
]);
}
}- Add routes in
routes/api.php - Routes should:
- Be grouped under middleware
- Follow RESTful naming
- Use resource controllers when possible
- Be documented
Example:
Route::middleware(['api.key', 'api.response'])->group(function () {
Route::apiResource('resource', ResourceController::class);
});- Create documentation in
docs/api/ - Documentation should include:
- Endpoint description
- Request/response examples
- All possible fields
- Field types and defaults
- Required/optional fields
Example file: docs/api/resource.md
- Database
- Use migrations for all schema changes
- Include proper indexes
- Use foreign keys for relationships
- Support soft deletes when appropriate
- Models
- Use proper relationships
- Define fillable fields
- Use proper type casting
- Add accessors/mutators when needed
- Services
- Handle business logic
- Use dependency injection
- Implement caching
- Be testable
- Controllers
- Be thin
- Use dependency injection
- Return standardized responses
- Use form requests
- API Responses
- Always use the
ApiResponseMiddleware - Follow the standard response format:
{
"success": true,
"status": 200,
"data": {},
"message": "Optional message",
"timestamp": "ISO8601"
}- Caching
- Cache expensive operations
- Use appropriate cache keys
- Clear cache on updates
- Use cache tags when possible
- Validation
- Use form requests
- Validate all input
- Return clear error messages
- Use proper validation rules
- Error Handling
- Use try-catch blocks
- Log errors
- Return proper error responses
- Use custom exceptions when needed
- Create tests in
tests/ - Test:
- Models
- Services
- Controllers
- API endpoints
- Edge cases
- Error scenarios
- Always run tests before deployment
- Check migrations
- Clear cache if needed
- Update documentation
- Create migration
- Create model
- Create service
- Create controller
- Add routes
- Create documentation
- Add tests
- Create migration if needed
- Update model
- Update service
- Update controller
- Update documentation
- Update tests
- Follow the same workflow
- Consider existing patterns
- Maintain consistency
- Update documentation
- Add tests
- Code Style
- Follow PSR-12
- Use proper type hints
- Add docblocks
- Keep methods small
- Security
- Validate all input
- Use proper authentication
- Sanitize output
- Follow security best practices
- Performance
- Use caching
- Optimize queries
- Use proper indexes
- Monitor performance
- Maintainability
- Write clean code
- Add comments
- Follow SOLID principles
- Keep documentation updated