Since this is a Symfony bundle, Laravel integration requires Symfony Bridge (symfony/http-kernel-bundle). Start by:
Install the package (via Composer):
composer require appaydin/pd-api
Bridge Symfony Components (if not already present):
composer require symfony/http-kernel-bundle symfony/framework-bundle
Configure the bundle in config/packages/pd_api.yaml (create if missing):
pd_api:
zone: ["^/api"] # Match Laravel's API routes
default_accept: json
default_groups: ['default']
allow_accept: ['json', 'xml']
Register the bundle in config/bundles.php:
return [
// ...
Pd\ApiBundle\PdApiBundle::class => ['all' => true],
];
First Use Case: Basic API Endpoint
Extend AbstractApiController in a Laravel controller:
use Pd\ApiBundle\Controller\AbstractApiController;
use Symfony\Component\Routing\Annotation\Route;
class ExampleController extends AbstractApiController
{
#[Route('/api/test', name: 'api.test', methods: ['GET'])]
public function test()
{
return ['message' => 'Hello, Laravel-Symfony API!'];
}
}
symfony/routing annotations or Laravel’s native routing.Base Controller: Always extend AbstractApiController for built-in features (e.g., response formatting, error handling).
class UserController extends AbstractApiController
{
// ...
}
Login Trait: Use LoginTrait for JWT authentication (requires lexik/jwt-authentication-bundle):
use Pd\ApiBundle\Controller\LoginTrait;
class AuthController extends AbstractApiController
{
use LoginTrait;
#[Route('/api/login', name: 'api.login', methods: ['POST'])]
public function login()
{
// Handled by trait
}
}
Automatic Formatting: The bundle normalizes responses to JSON or XML based on Accept header.
return ['data' => $users]; // Auto-converted to JSON/XML
Error Responses: Errors are standardized under Pd\ApiBundle\Exception\ApiProblem.
throw new ApiProblem(404, 'User not found');
use Knp\Component\Pager\PaginatorInterface;
#[Route('/api/users', name: 'api.users', methods: ['GET'])]
public function index(PaginatorInterface $paginator)
{
$users = $paginator->paginate(
$this->userRepository->findAll(),
$this->request->query->getInt('page', 1),
10
);
return $users; // Auto-normalized
}
#[Route('/api/users', name: 'api.users', methods: ['POST'])]
public function store(Request $request)
{
$data = $request->getContent(); // Auto-parsed as array
// ...
}
security.yaml as shown in the README, but adapt for Laravel’s auth:api middleware:
Route::middleware('auth:api')->group(function () {
Route::get('/api/protected', [ProtectedController::class, 'index']);
});
Routing Conflicts: Symfony annotations (@Route) may clash with Laravel’s. Prefer Laravel’s Route::get() or use symfony/routing separately.
// Laravel-style (recommended)
Route::get('/api/test', [ExampleController::class, 'test']);
// Symfony-style (may require extra config)
#[Route('/api/test', name: 'api.test')]
public function test() { ... }
Dependency Injection: Use Laravel’s container for services:
public function __construct(private UserRepository $users)
{
// Laravel DI works, but Symfony services may need manual binding.
}
pd_api.zone: Must match Laravel’s API route prefix (e.g., ["^/api"]). Misconfiguration breaks response formatting.default_accept: Set to json for Laravel (XML is niche in PHP ecosystems).auth:api middleware replaces Symfony’s guard. Ensure JWT routes are excluded from Laravel’s auth middleware.Content-Type headers to verify JSON/XML output.
curl -H "Accept: application/xml" http://your-api.test/api/test
ApiProblem exceptions for consistent error formats:
throw new ApiProblem(400, 'Invalid input', ['field' => 'Username is required']);
symfony/web-profiler-bundle) for deep inspection:
composer require symfony/web-profiler-bundle
Pd\ApiBundle\Normalizer\AbstractNormalizer for new data types.Pd\ApiBundle\Exception\ApiProblemHttpExceptionMapper to customize error responses.Pd\ApiBundle\Transformer\RequestTransformerInterface for custom body parsing.$this->cache->set('users_page_1', $users, 300); // 5-minute cache
Validator) instead of Symfony’s Validator to avoid duplication.How can I help you explore Laravel packages today?