Installation Add the package via Composer:
composer require dingo/api
Publish the config (optional but recommended for customization):
php artisan vendor:publish --provider="Dingo\Api\Provider\LaravelServiceProvider"
Basic Setup
Register the API service provider in config/app.php (Laravel) or bootstrap/app.php (Lumen):
Dingo\Api\Provider\LaravelServiceProvider::class,
First API Route
Define a route in routes/api.php:
$api->version('v1', function ($api) {
$api->get('users', 'App\Http\Controllers\UserController@index');
});
Access via /api/v1/users.
Key Configurations
Check config/api.php for:
url).middleware).versioning).auth).URL Versioning (Recommended)
$api->version('v1', function ($api) {
$api->get('users', 'UserController@index');
});
Access: /api/v1/users.
Header Versioning
Configure in config/api.php:
'versioning' => 'header',
Access: Accept: application/vnd.api.v1+json.
Route Group Versioning
Route::group(['prefix' => 'api', 'middleware' => 'api.auth'], function () {
$api = app('Dingo\Api\Routing\Router');
$api->version('v1', [...]);
});
config/api.php:
'middleware' => [
'api.auth',
'throttle:60,1',
],
$api->get('admin/users', 'UserController@adminIndex')
->middleware('can:admin-access');
Token-Based Auth
Use api.auth middleware with api.token guard:
'auth' => [
'default' => 'api',
'guards' => [
'api' => ['driver' => 'token', 'provider' => 'users'],
],
],
Generate tokens via php artisan passport:create-token.
JWT Integration
Combine with tymon/jwt-auth:
$api->get('protected', 'UserController@protected')
->middleware('api.jwt');
Custom Request Classes
Extend Dingo\Api\Http\Request:
namespace App\Http\Requests;
use Dingo\Api\Http\Request;
class CreateUserRequest extends Request {
public function rules() {
return ['name' => 'required'];
}
}
Use in routes:
$api->post('users', 'UserController@store')->request('CreateUserRequest');
Response Formatting
Use response()->api() for consistent JSON:
return response()->api(['data' => $users]);
Dingo\Api\Transformer\AbstractTransformer:
namespace App\Transformers;
use Dingo\Api\Transformer\AbstractTransformer;
class UserTransformer extends AbstractTransformer {
public function transform($user) {
return [
'id' => $user->id,
'name' => $user->name,
];
}
}
Apply in controllers:
$this->response->transformer(new UserTransformer());
Dingo\Api\Exception\Handler:
namespace App\Exceptions;
use Dingo\Api\Exception\Handler;
class ApiExceptionHandler extends Handler {
public function register() {
$this->registerErrorRenderer(function (\Exception $e) {
return response()->api(['error' => $e->getMessage()], 500);
});
}
}
Bind in AppServiceProvider:
$this->app->bind('Dingo\Api\Exception\Handler', 'App\Exceptions\ApiExceptionHandler');
Dingo\Api\Testing\TestCase:
use Dingo\Api\Testing\TestCase;
class UserTest extends TestCase {
public function test_get_users() {
$response = $this->get('/api/v1/users');
$response->assertStatus(200);
}
}
Versioning Conflicts
Middleware Order Matters
api.auth must be defined before route-specific middleware in config/api.php.CORS Headers in Lumen
fruitcake/laravel-cors or add headers manually:
$api->middleware('cors');
Transformer Caching
api.resource() for collections:
return $this->response->resource($users);
Deprecated Methods
response()->json()) may not work as expected.response()->api() for consistency.Lumen Route Caching
php artisan route:clear.Route Debugging
Use php artisan route:list and filter by api:
php artisan route:list --path="api/v1"
Middleware Debugging Temporarily add logging in middleware:
public function handle($request, Closure $next) {
\Log::info('Middleware executed', ['path' => $request->path()]);
return $next($request);
}
Transformer Debugging Dump transformer output:
$transformer = new UserTransformer();
\Log::info('Transformer output', $transformer->transform($user));
Request Validation Validate manually if rules fail silently:
$this->validate($request, ['name' => 'required']);
if ($request->fails()) {
return response()->api(['errors' => $request->errors()], 422);
}
Custom Route Model Binding
Extend Dingo\Api\Binding\BindingResolver:
$api->bind('user', function ($id) {
return User::findOrFail($id);
});
Dynamic API Groups Create reusable API groups:
$api->group(['namespace' => 'App\Http\Controllers'], function ($api) {
$api->get('users', 'UserController@index');
});
API Documentation
Integrate with darkaonline/l5-swagger:
$api->get('docs', 'DocumentationController@index')
->name('api.documentation');
Rate Limiting
Use api.throttle middleware with custom limits:
$api->middleware('throttle:api,60,1');
Event Listeners
Listen to API events (e.g., api.before):
$api->before(function ($request) {
\Log::info('API request received', ['path' => $request->path()]);
});
Disable Debug Mode in Production
Set 'debug' => false in config/api.php to reduce overhead.
Lazy-Load Transformers Avoid eager-loading transformers for every request:
$this->response->transformer = new UserTransformer(); // Cache instance
Use API Resources for Collections
return $
How can I help you explore Laravel packages today?