Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Api Bundle Laravel Package

cesurapp/api-bundle

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Install the package**:
   ```bash
   composer require cesurapp/api-bundle
  1. Configure CORS and Thor in config/packages/api.yaml:
    api:
      cors_header:
        - { name: 'Access-Control-Allow-Origin', value: '*' }
      thor:
        base_url: "%env(APP_DEFAULT_URI)%"
    
  2. Extend ApiController and use ApiResponse:
    use Cesurapp\ApiBundle\AbstractClass\ApiController;
    use Cesurapp\ApiBundle\Response\ApiResponse;
    
    class TestController extends ApiController {
        public function index(): ApiResponse {
            return ApiResponse::create()->setData(['test' => 'data']);
        }
    }
    
  3. Access Thor docs at /thor and generate TypeScript clients:
    bin/console thor:extract ./client
    

First Use Case: CRUD Endpoint

Create a UserController with DTO validation and resource transformation:

use Cesurapp\ApiBundle\AbstractClass\ApiController;
use Cesurapp\ApiBundle\Response\ApiResponse;
use Cesurapp\ApiBundle\Thor\Attribute\Thor;

class UserController extends ApiController {
    #[Thor(
        title: 'Create User',
        request: ['name' => 'string', 'email' => 'string'],
        response: [200 => ['data' => UserResource::class]],
        dto: CreateUserDto::class
    )]
    public function create(CreateUserDto $dto): ApiResponse {
        return ApiResponse::create()->setData($dto->toArray());
    }
}

Implementation Patterns

1. Controller Layer

  • Base Class: Extend ApiController for automatic JSON request parsing and error handling.
  • Annotations: Use [Thor] to auto-generate documentation and TypeScript clients.
    #[Thor(
        stack: 'User|1',
        query: ['filter[name]' => '?string'],
        isPaginate: true
    )]
    
  • Response Handling: Chain ApiResponse methods:
    return ApiResponse::create()
        ->setData($user)
        ->setResource(UserResource::class)
        ->setPaginate()
        ->setHTTPCache(3600);
    

2. DTO Layer

  • Validation: Use Symfony constraints + custom validators (PhoneNumber, UniqueEntity):
    class LoginDto extends ApiDto {
        #[Assert\NotNull]
        #[PhoneNumber]
        public string $phone;
    
        #[Assert\NotNull]
        #[UniqueEntity(entityClass: User::class, field: 'email')]
        public string $email;
    }
    
  • Lifecycle Hooks: Override beforeValidated()/endValidated() for custom logic:
    protected function beforeValidated(): void {
        $this->email = strtolower($this->email);
    }
    

3. Resource Layer

  • Transformation: Implement ApiResourceInterface to define API output:
    class UserResource implements ApiResourceInterface {
        public function toArray(User $user): array {
            return ['id' => $user->id, 'name' => $user->name];
        }
    
        public function toResource(): array {
            return [
                'name' => [
                    'type' => 'string',
                    'filter' => fn(QueryBuilder $qb, string $alias, $data) =>
                        $qb->andWhere("$alias.name LIKE :name")->setParameter('name', "%$data%"),
                ],
            ];
        }
    }
    
  • Query Building: Leverage setQuery() for filtering/sorting:
    return ApiResponse::create()
        ->setQuery($repo->createQueryBuilder('u'))
        ->setResource(UserResource::class);
    

4. Integration Workflows

  • Doctrine Filters: Use toResource() to enable dynamic query filtering:
    GET /users?filter[name]=John&filter[createdAt][from]=2024-01-01
    
  • Exports: Integrate with Sonata Export Bundle:
    use Cesurapp\ApiBundle\Exporter\ExcelExporter;
    
    $exporter = new ExcelExporter();
    return $exporter->export($users, 'users.xlsx');
    
  • Caching: Add HTTP caching to responses:
    ->setHTTPCache(60, tags: ['users'])
    

5. TypeScript Client Generation

  • Auto-Generate Clients: Run:
    bin/console thor:extract ./client
    
  • Use in Frontend:
    import { ApiClient } from './client';
    const client = new ApiClient();
    const users = await client.get('/users');
    

Gotchas and Tips

Pitfalls

  1. Thor Configuration Conflicts:

    • Issue: Misconfigured thor.base_url breaks TypeScript client generation.
    • Fix: Ensure APP_DEFAULT_URI in .env matches your API base URL.
      thor:
        base_url: "%env(APP_DEFAULT_URI)%"  # e.g., "https://api.example.com"
      
  2. DTO Validation Short-Circuiting:

    • Issue: Custom beforeValidated() may bypass Symfony constraints.
    • Fix: Call parent::beforeValidated() if extending ApiDto:
      protected function beforeValidated(): void {
          parent::beforeValidated(); // Ensure constraints run
          $this->email = strtolower($this->email);
      }
      
  3. Pagination Edge Cases:

    • Issue: setPaginate() without a QueryBuilder throws errors.
    • Fix: Always pass a query:
      ->setQuery($repo->createQueryBuilder('u'))
      ->setPaginate()
      
  4. Resource Filtering:

    • Issue: toResource() filters only work with pagination enabled (isPaginate: true).
    • Fix: Set isPaginate: true in [Thor] if using filters.
  5. CORS Headers:

    • Issue: Custom headers in cors_header may conflict with Symfony’s built-in CORS.
    • Fix: Disable Symfony’s CORS bundle if using custom headers:
      # config/packages/nelmio_cors.yaml
      nelmio_cors:
        enabled: false
      

Debugging Tips

  1. Validation Errors:

    • Check errors in HTTP 422 responses for constraint violations.
    • Enable debug mode to see full validation paths:
      $dto->validate(throw: true); // Throws exceptions in dev
      
  2. Thor Docs:

    • Clear cache after adding new [Thor] annotations:
      bin/console cache:clear
      
  3. QueryBuilder Issues:

    • Use dd($query->getSQL()) to debug generated SQL for filters/sorting.

Extension Points

  1. Custom Validators:

    • Extend AbstractValidator for reusable rules:
      use Cesurapp\ApiBundle\Validator\AbstractValidator;
      
      class CustomValidator extends AbstractValidator {
          public function validate($value, Constraint $constraint) {
              return $value === 'expected';
          }
      }
      
  2. Response Transformers:

    • Override ApiResponse to add custom headers or formats:
      class CustomApiResponse extends ApiResponse {
          public function setCustomHeader(string $name, string $value): self {
              $this->headers[$name] = $value;
              return $this;
          }
      }
      
  3. Thor Extensions:

    • Add custom sections to Thor docs by extending the Thor attribute:
      #[Attribute(Attribute::TARGET_METHOD)]
      class CustomThor extends Thor {
          public string $customField;
      }
      

Performance Quirks

  1. DTO Auto-Validation:
    • Disable with $dto->auto = false for manual validation (faster for bulk operations).
  2. Resource Caching:
    • toResource() is called per-request; cache results if static:
      private static ?array $resourceSchema;
      
      public function toResource(): array {
          return self::$resourceSchema ??= [
              // cached schema
          ];
      }
      

Configuration Tricks

  1. Disable Exception Conversion:
    • Set exception_converter: false in api.yaml to bypass automatic error formatting.
  2. Global Thor Settings:
    • Configure default auth/query headers in thor.global_config:
      thor:
        global_config:
          authHeader:
            Authorization: 'Bearer {token}'
      
  3. Conditional CORS:
    • Use environment variables for dynamic CORS:
      cors_header:
        - { name: 'Access-Control-Allow-Origin', value: "%env(CORS_ORIGIN)%" }
      

Testing Strategies

  1. DTO Tests:
    • Test validation with
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor