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 Resource Bundle Laravel Package

conghau/api-resource-bundle

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup for Laravel Integration
Since this bundle is Symfony2-based, Laravel developers must adapt it via **Symfony Bridge** or **standalone usage**. Start by:

1. **Install Dependencies**
   ```bash
   composer require symfony/framework-bundle nelmio/api-doc-bundle jms/serializer-bundle
   composer require doctrine/orm doctrine/doctrine-bundle # If using Doctrine
  1. Configure Kernel (Laravel Equivalent: bootstrap/app.php) Replace Laravel’s service provider registration with Symfony’s kernel setup:

    $kernel = new Symfony\Component\HttpKernel\Kernel(
        'dev', // Environment
        false  // Debug mode
    );
    $kernel->boot();
    $request = Symfony\Component\HttpFoundation\Request::createFromGlobals();
    $response = $kernel->handle($request);
    $response->send();
    $kernel->terminate($request, $response);
    
  2. Define API Resources in config/config.yml (Laravel: config/api-resources.php)

    tch_api_resource:
        resources:
            user:
                entity: App\Models\User
                actions: [C, R, U, D, S] # CRUD + Search
            post:
                entity: App\Models\Post
                actions: [R, S]
    
  3. Route Configuration (Laravel: routes/api.php)

    use Symfony\Component\Routing\Loader\YamlFileLoader;
    use Symfony\Component\Routing\RouteCollection;
    
    $loader = new YamlFileLoader();
    $collection = $loader->load(__DIR__.'/config/routing.yml');
    $router = new Symfony\Component\Routing\Router($collection, $kernel->getEnvironment());
    
  4. First Use Case: Generate API Docs Access /api/doc to see auto-generated Swagger/OpenAPI docs for configured resources.


Implementation Patterns

1. Repository Integration

Use TraitTCHRepository to extend Doctrine repositories with API-specific methods:

// app/Repositories/UserRepository.php
namespace App\Repositories;

use TCH\ApiResourceBundle\Util\TraitTCHRepository;

class UserRepository extends \Doctrine\ORM\EntityRepository
{
    use TraitTCHRepository;

    // Auto-implemented: find(), findAll(), search(), create(), update(), delete()
}

Workflow:

  • CRUD Operations: Leverage trait methods (e.g., create()) in controllers.
  • Search: Use search() with query params (e.g., ?q=email:test@example.com).

2. Controller Integration

Create controllers to handle API logic:

// app/Http/Controllers/API/UserController.php
namespace App\Http\Controllers\API;

use App\Repositories\UserRepository;
use Symfony\Component\HttpFoundation\Request;

class UserController extends AbstractController
{
    private $repository;

    public function __construct(UserRepository $repository)
    {
        $this->repository = $repository;
    }

    public function index(Request $request)
    {
        return $this->repository->findAll($request->query->all());
    }

    public function store(Request $request)
    {
        return $this->repository->create($request->request->all());
    }
}

Patterns:

  • Dependency Injection: Inject UserRepository (or any entity repository).
  • Request Handling: Pass $request->query or $request->request to trait methods.
  • Serialization: JMS Serializer auto-converts entities to JSON (configure via config/packages/jms_serializer.yaml).

3. Custom Actions

Extend beyond CRUD by adding custom methods to repositories:

// app/Repositories/UserRepository.php
public function getActiveUsers()
{
    return $this->createQueryBuilder('u')
        ->where('u.isActive = :active')
        ->setParameter('active', true)
        ->getQuery()
        ->getResult();
}

Route it in config/routing.yml:

tch_api_resource_user_active:
    path:     /api/v1/users/active
    defaults: { _controller: App\Controller\API\UserController::activeUsers }
    methods:  GET

4. Validation

Use Symfony’s Validator component for request validation:

# config/validator/validation.yml
App\Models\User:
    properties:
        email:
            - Email: ~
        password:
            - NotBlank: ~
            - Length: { min: 8 }

Controller Usage:

public function store(Request $request)
{
    $validator = $this->get('validator');
    $errors = $validator->validate($request->request->all());

    if (count($errors) > 0) {
        return new JsonResponse(['errors' => (string) $errors], 400);
    }

    return $this->repository->create($request->request->all());
}

Gotchas and Tips

1. Laravel-Symfony Quirks

  • Kernel Bootstrapping: Symfony’s Kernel must be booted before handling requests. Avoid mixing Laravel’s service container with Symfony’s directly.
  • Routing Conflicts: Prefix API routes (/api/v1/) to avoid clashes with Laravel’s default routes.
  • Service Container: Use Symfony’s DI container ($this->get('service_id')) or bridge it with Laravel’s via SymfonyBridge.

2. Debugging

  • API Docs Not Loading: Ensure NelmioApiDocBundle is properly configured in config/packages/nelmio_api_doc.yaml:
    nelmio_api_doc:
        routes:
            prefix:   /api/doc
        areas:       # to filter documented controllers
            default:
                path_patterns:
                    - ^/api/v1
    
  • Serialization Errors: Check config/packages/jms_serializer.yaml:
    jms_serializer:
        metadata:
            directories:
                - %kernel.project_dir%/config/serializer
    
    Create custom metadata files (e.g., config/serializer/App.Models.User.yml) for complex types.

3. Performance Tips

  • Pagination: Use findAll() with limit and offset params:
    $users = $this->repository->findAll([
        'limit' => 10,
        'offset' => 0,
        'sort' => ['id' => 'DESC']
    ]);
    
  • Caching: Enable OPcache for Symfony classes and JMS Serializer metadata.

4. Extending the Bundle

  • Custom Actions: Override trait methods in repositories:
    public function search(array $params)
    {
        // Custom search logic
        return $this->createQueryBuilder('u')
            ->where('u.name LIKE :name')
            ->setParameter('name', '%'.$params['q'].'%')
            ->getQuery()
            ->getResult();
    }
    
  • Event Listeners: Use Symfony’s event system to hook into CRUD operations:
    // src/EventListener/UserListener.php
    use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
    
    class UserListener
    {
        public function onKernelController(FilterControllerEvent $event)
        {
            $request = $event->getRequest();
            if ($request->getPathInfo() === '/api/v1/users') {
                // Modify request/response here
            }
        }
    }
    
    Register in config/services.yaml:
    services:
        App\EventListener\UserListener:
            tags:
                - { name: kernel.event_listener, event: kernel.controller }
    

5. Common Pitfalls

  • Entity Not Found: Ensure entity in config.yml matches the fully qualified namespace (e.g., App\Models\User).
  • CSRF Issues: Disable CSRF for API routes in Symfony’s security config:
    security:
        access_control:
            - { path: ^/api/v1, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    
  • Doctrine Mismatch: If using Laravel’s Eloquent, do not mix with Doctrine ORM. Use this bundle only with Doctrine entities.

6. Testing

  • Functional Tests: Use Symfony’s WebTestCase:
    use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
    
    class UserAPITest extends WebTestCase
    {
        public function testCreateUser()
        {
            $client = static::createClient();
            $client->request('POST', '/api/v1/users', [
                'json' => ['name' => 'John', 'email' => 'john@example.com']
            ]);
            $this->assertEquals(201, $client->getResponse()->getStatusCode());
        }
    }
    
  • Unit Tests: Mock repositories and test trait methods in isolation.
use PHPUnit\Framework\TestCase;

class UserRepositoryTest extends TestCase
{
    public function testSearch()
    {
        $repo = $this->getMockBuilder(UserRepository::class)
            ->onlyMethods(['createQueryBuilder'])
            ->getMock();
        $repo->expects($this->once())
            ->method('createQueryBuilder')
            ->with('u')
            ->willReturn
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.
comsave/common
alecsammon/php-raml-parser
chrome-php/wrench
lendable/composer-license-checker
typhoon/reflection
mesilov/moneyphp-percentage
mike42/gfx-php
bookdown/themes
aura/view
aura/html
aura/cli
povils/phpmnd
nayjest/manipulator
omnipay/tests
psr-mock/http-message-implementation
psr-mock/http-factory-implementation
psr-mock/http-client-implementation
voku/email-check
voku/urlify
rtheunissen/guzzle-log-middleware