Laravel - api-platform: Full Api-platform usage example with larvel model and database

Updated: Feb 10, 2025

Laravel - api-platform: Full Api-platform usage example with larvel model and database

ApiPlatform is a full-featured, open-source, and easy-to-use RESTful API framework for PHP. It is designed to work seamlessly with Symfony and Laravel. In this example, we will discuss how to use ApiPlatform with Laravel, including creating a model, database, and defining the API routes and resources.

First, let's assume we have a simple Laravel project with a model called Product and a database table named products. The Product model has the following fields: id, name, price, and description.

To use ApiPlatform with Laravel, follow these steps:

  1. Install ApiPlatform:

Add the following line to your composer.json file:

{
    "require": {
        "api-platform/api-platform": "^2.7",
        "api-platform/doctrine-orm-bundle": "^2.7",
        "api-platform/symfony-bundle": "^2.7"
    }
}

Run composer install to install the packages.

  1. Configure the services:

Add the following lines to your config/services.yaml file:

services:
    _defaults:
        autowire: true
        autoconfigure: true

    App\:
        resource: '../src/'
        tags: ['controller.service_arguments']

    ApiPlatform:
        resource: '@api-platform/symfony-bundle/src'
        tags: ['api_platform.core']

    App\ProductController:
        arguments: ['%router%']
        tags: ['controller.service_arguments']

    App\ProductResource:
        arguments: ['%doctrine.orm.entity_manager%']
        tags: ['api_platform.resource']
  1. Define the Product model:

Make sure your Product model has the ApiPlatform\Core\Annotation\ApiResource annotation:

namespace App;

use ApiPlatform\Core\Annotation\ApiResource;
use Illuminate\Database\Eloquent\Model;

/**
 * @ApiResource()
 */
class Product extends Model
{
    // ...
}
  1. Define the Product resource:

Create a new file src/Resources/App/ProductResource.php with the following content:

namespace App\Resources;

use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
use App\Entity\Product;

/**
 * @ApiResource(
 *     normalizationContext={"groups"={"product:read"}},
 *     denormalizationContext={"groups"={"product:write"}}
 * )
 */
class ProductResource
{
    /**
     * @var Product
     *
     * @ApiProperty(
     *     name="id",
     *     readable=false,
     *     normalizationContext={"groups"={"product:read"}}
     * )
     */
    public $product;

    public function __construct(Product $product)
    {
        $this->product = $product;
    }

    public function toArray($request = null)
    {
        return [
            'id' => $this->product->getId(),
            'name' => $this->product->getName(),
            'price' => $this->product->getPrice(),
            'description' => $this->product->getDescription(),
        ];
    }

    public function getId()
    {
        return $this->product->getId();
    }
}
  1. Define the Product controller:

Create a new file src/Controller/ProductController.php with the following content:

namespace App\Controller;

use App\Entity\Product;
use ApiPlatform\Core\Api\IAnnotations as ApiDoc;
use ApiPlatform\Core\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * @ApiDoc(
 *     swaggerYml="controllers.yml",
 *     section="Products",
 *     tags={"Products"}
 * )
 */
class ProductController extends AbstractController
{
    public function __construct()
    {
        $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
    }

    /**
     * @ApiDoc(
     *     swaggerYml="get_product.yml",
     *     method="GET",
     *     path="/api/products/{id}",
     *     name="get_product",
     *     description="Get a single product",
     *     security={{"Bearer": {}}},
     *     requirements={{"id"="\d+"}},
     *     output={"class"="App\Resources\ProductResource", "groups"={"product:read"}},
     *     statusCodes={200="Returned when successful", 404="Returned when the product is not found"}
     * )
     *
     * @param Request $request
     * @param Product $product
     *
     * @return Response
     */
    public function getAction(Request $request, Product $product)
    {
        return $this->view($product, Response::HTTP_OK, ['_format' => $request->getRequestFormat()]);
    }

    /**
     * @ApiDoc(
     *     swaggerYml="post_product.yml",
     *     method="POST",
     *     path="/api/products",
     *     name="create_product",
     *     description="Create a new product",
     *     security={{"Bearer": {}}},
     *     input={"class"="App\Resources\ProductResource", "groups"={"product:write"}},
     *     output={"class"="App\Resources\ProductResource", "groups"={"product:read"}},
     *     statusCodes={201="Returned when the product is created", 400="Returned when the product creation fails"}
     * )
     *
     * @param Request $request
     *
     * @return Response
     */
    public function postAction(Request $request)
    {
        $product = $this->getDoctrine()->getRepository(Product::class)->createNew();

        $productResource = new ProductResource($product);

        $data = json_decode($request->getContent(), true);

        $productResource->applyToEntity($data, 'PATCH');

        $entityManager = $this->getDoctrine()->getManager();
        $entityManager->persist($product);
        $entityManager->flush();

        return $this->view($productResource, Response::HTTP_CREATED, ['_format' => $request->getRequestFormat()]);
    }
}
  1. Configure the routing:

Add the following lines to your routes/api.yaml file:

api_platform:
    resources:
        App\Entity\Product:
            class: App\Controller\ProductController
            methods: [GET, POST]
            path: /api/products/{id}
            name: product
            controller: App\Controller\ProductController::getAction
            defaults: { _controller: App\Controller\ProductController::getAction }
            requirements:
                id: '\d+'

    api_platform:
        resources:
            App\Entity\Product:
                class: App\Controller\ProductController
                methods: [POST]
                path: /api/products
                name: create_product
                controller: App\Controller\ProductController::postAction
                defaults: {}
                requirements: {}
  1. Create the Swagger documentation:

Create a new file controllers.yml in the public/swagger directory with the following content:

---
openapi: 3.0.0
info:
  title: API Platform Example
  version: 1.0.0
servers:
  - url: http://localhost:8000/api
components:
  schemas:
    Product:
      type: object
      properties:
        id:
          type: integer
          description: The id of the product
        name:
          type: string
          description: The name of the product
        price:
          type: number
          description: The price of the product
        description