equidna / laravel-toolkit
Multi-context Laravel helpers, middleware, and utilities.
Installs: 29
Dependents: 1
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
pkg:composer/equidna/laravel-toolkit
Requires
- php: ^8.0
- illuminate/support: ^11.21 || ^12.0
- laravel/framework: ^11.21 || ^12.0
- laravel/helpers: ^1.7
Requires (Dev)
README
A modern Laravel package for multi-context, modular application development.
Equidna Toolkit bundles helpers, middleware, traits, and a service provider that keep responses, validation, and pagination consistent across web, API, hook, IoT, and console entry points. Targeted for Laravel 11 & 12 on PHP 8.0+, it embraces Laravel conventions while abstracting repetitive infrastructure code.
π Highlights
- Route-aware helpers β Detect API/web/hook/IoT/console contexts with
RouteHelperand branch logic safely. - Unified responses β
ResponseHelperemits JSON, redirects, or console strings from a single API. - Validation parity β
EquidnaFormRequestthrows HTTP-aware exceptions instead of redirecting on failure. - Paginator utilities β Build
LengthAwarePaginatorinstances from arrays/collections with query sanitization. - Pluggable middleware β Opt-in layers for forcing JSON, clearing session history, and disabling Debugbar.
- Composite key trait β Handle multi-column primary keys without reimplementing boilerplate.
π¦ Installation
composer require equidna/toolkit php artisan vendor:publish --tag=equidna:config
Auto-discovery registers the service provider. For manual registration, add it to config/app.php:
'providers' => [ Questions or ideas? Open an issue or discussion in the repositoryβwe welcome feedback for new multi-context helpers. > A modern Laravel package for multi-context, modular application development. Equidna Toolkit provides helpers, traits, middleware, and a service provider to streamline responses and errors across web, API, hooks, and IoT contexts. ## Key Features - Multi-context request handling (web, API, hooks, IoT, console) - Unified response helpers and custom exceptions - Eloquent composite primary key support - Configurable pagination helpers - Plug-and-play middleware and zero-config service provider # Equidna Toolkit v1.0.3 > **A modern Laravel package for multi-context, modular application development.** Equidna Toolkit provides helpers, traits, middleware, and a service provider to streamline responses and errors across web, API, hooks, and IoT contexts. Designed for Laravel 11 & 12, it enables unified response patterns, context-aware utilities, and advanced exception handling for professional-grade PHP projects. ## Key Features - Multi-context request handling: Seamlessly detect and respond to web, API, hook, IoT, and console requests. - Unified response helpers: Consistent success and error responses for all contexts. - Advanced exception architecture: Custom HTTP exceptions with automatic Laravel binding and context-aware rendering. - Eloquent composite key support: Effortlessly manage models with composite primary keys. - Configurable pagination: Build paginated responses from arrays or collections with minimal code. - Plug-and-play middleware: Easily exclude requests from session history or force JSON responses. - Zero-config service provider: Auto-discovers and binds all package features. ## Main Use Cases - API-first Laravel apps needing unified error/success responses - Multi-context SaaS: web, API, IoT, and hooks in one codebase - Rapid prototyping: Add robust helpers and exceptions with zero config - Enterprise Laravel: Enforce consistent error handling and pagination ## Quick Installation ```sh composer require equidna/toolkit php artisan vendor:publish --tag=equidna:config
If you use Laravel package auto-discovery the service provider registers automatically; otherwise add it to config/app.php:
'providers' => [ Equidna\Toolkit\Providers\EquidnaLaravelToolkitServiceProvider::class, ]
Usage Examples
use Equidna\Toolkit\Helpers\ResponseHelper; return ResponseHelper::success('Operation completed', ['foo' => 'bar']);
Composite primary keys:
use Equidna\Toolkit\Traits\Database\HasCompositePrimaryKey; class UserRole extends Model { use HasCompositePrimaryKey; public function getKeyName() { return ['user_id', 'role_id']; } }
Paginator helper:
use Equidna\Toolkit\Helpers\PaginatorHelper; $paginator = PaginatorHelper::buildPaginator($arrayOrCollection, $page, $itemsPerPage);
Technical Overview
Helpers/β Context-aware utilities (RouteHelper, ResponseHelper, PaginatorHelper)Http/Middleware/β Middleware likeExcludeFromHistory,ForceJsonResponse,DisableDebugbarExceptions/β Custom HTTP exceptions auto-bound by the service providerTraits/Database/βHasCompositePrimaryKey,Paginator(for Eloquent)Providers/βEquidnaLaravelToolkitServiceProvider
Development
- Coding Standard: PSR-12 (4-space indent)
- Static Analysis: PHPStan (
vendor/bin/phpstan analyse) - PHP: 8.0+
PHPStan note
When running PHPStan on this library you may see trait.unused warnings for Traits/Database/HasCompositePrimaryKey.php and Traits/Database/Paginator.php β this is common for packages that expose traits intended for consumers to use in their applications. Options:
- Leave the warning (informational).
- Add an
ignoreErrorsrule for the specific message(s) inphpstan.neon. - Add minimal unit tests or example usage files that reference the traits so PHPStan recognises they are used.
Configuration
Default config (config/equidna.php):
return [ 'paginator' => [ 'page_items' => 15, ], ];
Response JSON shapes
Success responses include status, message and optionally data:
{
"status": 200,
"message": "Operation completed",
"data": { "foo": "bar" }
}
Error responses contain status, message and errors (when status >= 400):
{
"status": 422,
"message": "Validation error",
"errors": { "email": ["The email field is required."] }
}
Paginator notes
PaginatorHelper::buildPaginator() uses config('equidna.paginator.page_items') when an explicit items_per_page isn't provided. The helper also strips a small set of sensitive query keys when appending request parameters; the default excluded keys are:
_token, page, client_user, client_token, client_token_type
Exceptions (clarified)
Package exceptions accept a message, an optional previous throwable, and an optional errors array. Each exception class sets its own HTTP status code internally. Example (BadRequestException):
new BadRequestException( message: 'Invalid input', previous: $previousException, errors: ['email' => ['invalid format']], ); // BadRequestException sets HTTP status 400 internally.
Further Reading
For full API reference and examples see the src/ directory. If you'd like, I can also add a short section showing how to add ignoreErrors entries to phpstan.neon to silence the trait warnings.
#### PaginatorHelper
```php
PaginatorHelper::buildPaginator(array|Collection $data, ?int $page = null, ?int $itemsPerPage = null, bool $setFullUrl = false): LengthAwarePaginator
PaginatorHelper::appendCleanedRequest(LengthAwarePaginator $paginator, Request $request): void
PaginatorHelper::setFullURL(LengthAwarePaginator $paginator): void
```
#### Traits
- **HasCompositePrimaryKey**: Enables Eloquent models to support composite primary keys.
- Usage:
```php
class MyModel extends Model {
use HasCompositePrimaryKey;
public function getKeyName() { return ['key1', 'key2']; }
}
```
- **Paginator**: Adds a `scopePaginator` to Eloquent models for flexible pagination with transformation support.
- Usage:
```php
$results = $this->scopePaginator($query, $page, $pageName, $itemsPerPage, $setFullUrl, $transformation);
```
#### Middleware
- **ExcludeFromHistory**: Prevents the current request from being stored in the session as the current URL.
- **ForceJsonResponse**: Forces the response to be JSON (sets `Accept: application/json`).
- **DisableDebugbar**: Disables the Laravel Debugbar for the current request if it is bound in the container.
- **ForceApiResponse**: (Deprecated) Use `ForceJsonResponse` instead.
**DisableDebugbar Usage Example:**
```php
// In app/Http/Kernel.php
protected $middlewareGroups = [
'web' => [
\Equidna\Toolkit\Http\Middleware\DisableDebugbar::class,
],
];
```
#### Exception Classes
Custom exceptions for each error response, with integrated logging and rendering. All exceptions share the following constructor:
```php
__construct(string $message = '...', ?Throwable $previous = null, array $errors = [])
```
Available exceptions:
- `BadRequestException` (400)
- `UnauthorizedException` (401)
- `ForbiddenException` (403)
- `NotFoundException` (404)
- `NotAcceptableException` (406)
- `ConflictException` (409)
- `UnprocessableEntityException` (422)
- `TooManyRequestsException` (429)
**Example:**
```php
throw new BadRequestException('Invalid input', $previousException, ['field' => 'error']);
```
---
## βοΈ Configuration
All config is referenced relative to the provider directory. Example:
```php
config('equidna.paginator.page_items');
```
Default config (`config/equidna.php`):
```php
return [
'paginator' => [
'page_items' => 15,
],
];
```
---
## π οΈ Development & Contribution
- **Coding Standard**: PSR-12, 4-space indent, 250-char line limit, StyleCI (laravel preset)
- **Static Analysis**: PHPStan (`vendor/bin/phpstan analyse`)
- **PHP Version**: 8.0+
- **No bundled tests**: Please contribute tests if you extend the package!
[!NOTE]
This package is designed for advanced Laravel projects. For questions, open an issue or PR on GitHub.
---
## π€ Main Use Cases
- **API-first Laravel apps** needing unified error/success responses
- **Multi-context SaaS**: web, API, IoT, and hooks in one codebase
- **Rapid prototyping**: Add robust helpers and exceptions with zero config
- **Enterprise Laravel**: Enforce consistent error handling and pagination
---
## π Further Reading
- [Laravel Documentation](https://laravel.com/docs)
- [Equidna Toolkit on Packagist](https://packagist.org/packages/equidna/toolkit)
[!TIP]
For advanced integration patterns and edge cases, see the source code and open issues for real-world examples.
---
## Helpers
### RouteHelper
**Namespace:** `Equidna\Toolkit\Helpers`
Static methods for request type detection:
```php
RouteHelper::isWeb()
RouteHelper::isApi()
RouteHelper::isHook()
RouteHelper::isIoT()
RouteHelper::isExpression(string $expression)
RouteHelper::isConsole()
RouteHelper::wantsJson()
RouteHelper::getMethod()
RouteHelper::isMethod(string $method)
RouteHelper::getRouteName()
RouteHelper::isRouteName(string $name)
RouteHelper::routeContains(string $name)
```
---
### ResponseHelper
**Namespace:** `Equidna\Toolkit\Helpers`
Static methods for generating error and success responses.
Returns a `RedirectResponse` for web requests or a JSON response for API requests.
**Error Responses:**
```php
ResponseHelper::badRequest(string $message, array $errors = [], array $headers = [], string $forward_url = null)
ResponseHelper::unauthorized(string $message, array $errors = [], array $headers = [], string $forward_url = null)
ResponseHelper::forbidden(string $message, array $errors = [], array $headers = [], string $forward_url = null)
ResponseHelper::notFound(string $message, array $errors = [], array $headers = [], string $forward_url = null)
ResponseHelper::notAcceptable(string $message, array $errors = [], array $headers = [], string $forward_url = null)
ResponseHelper::conflict(string $message, array $errors = [], array $headers = [], string $forward_url = null)
ResponseHelper::unprocessableEntity(string $message, array $errors = [], array $headers = [], string $forward_url = null)
ResponseHelper::tooManyRequests(string $message, array $errors = [], array $headers = [], string $forward_url = null)
ResponseHelper::error(string $message, array $errors = [], array $headers = [], string $forward_url = null)
ResponseHelper::handleException(Exception $exception, array $errors = [], array $headers = [], string $forward_url = null)
```
**Success Responses:**
```php
ResponseHelper::success(string $message, mixed $data = null, string $forward_url = null)
ResponseHelper::created(string $message, mixed $data = null, string $forward_url = null)
ResponseHelper::accepted(string $message, mixed $data = null, string $forward_url = null)
ResponseHelper::noContent(string $message = 'Operation completed successfully', string $forward_url = null)
```
---
### PaginatorHelper
**Namespace:** `Equidna\Toolkit\Helpers`
Builds paginated responses from arrays or collections, using config-driven pagination length.
```php
PaginatorHelper::buildPaginator(array|Collection $data, ?int $page = null, ?int $items_per_page = null, bool $set_full_url = false): LengthAwarePaginator
PaginatorHelper::appendCleanedRequest(LengthAwarePaginator $paginator, Request $request): void
PaginatorHelper::setFullURL(LengthAwarePaginator $paginator): void
```
**Trait Usage Example:**
```php
// In your Eloquent model
use Equidna\Toolkit\Traits\Database\Paginator;
// Usage in a query scope
$results = $this->scopePaginator($query, $page, $pageName, $items_per_page, $set_full_url, $transformation);
```
Pagination length is set via config:
`config/equidna.php`
```php
return [
'paginator' => [
'page_items' => 15,
],
];
```
---
## Service Provider
### EquidnaLaravelToolkitServiceProvider
**Namespace:** `Equidna\Toolkit\Providers`
Registers and publishes package config, and binds custom exception handlers for Laravel.
---
## Exception Classes
Custom exceptions for each error response, with integrated logging and rendering. All exceptions share the following constructor signature:
```php
__construct(string $message = '...', ?Throwable $previous = null, array $errors = [])
```
Available exceptions:
- `BadRequestException`
- `UnauthorizedException`
- `ForbiddenException`
- `NotFoundException`
- `NotAcceptableException`
- `ConflictException`
- `UnprocessableEntityException`
- `TooManyRequestsException`
**Example:**
```php
throw new BadRequestException('Invalid input', $previousException, ['field' => 'error']);
```
Each exception logs the error and returns the appropriate response via `ResponseHelper`. The `$errors` array is optional and can be used to provide additional error details.
---
## Configuration
All config is referenced relative to the provider directory.
Example:
`config('equidna.paginator.page_items')`
---
## Installation & Usage
- Add the service provider to `config/app.php`:
```php
'providers' => [
Equidna\Toolkit\Providers\EquidnaLaravelToolkitServiceProvider::class,
]
```
- Publish config:
```sh
php artisan vendor:publish --tag=equidna:config
```