Installation Add the bundle via Composer:
composer require bisonlab/common-bundle
Register the bundle in config/bundles.php:
return [
// ...
BisonLab\CommonBundle\BisonLabCommonBundle::class => ['all' => true],
];
First Use Case: User Object
The bundle provides a User entity class. Locate it in:
vendor/bisonlab/common-bundle/src/Entity/User.php
Extend it in your project:
namespace App\Entity;
use BisonLab\CommonBundle\Entity\User as BaseUser;
class User extends BaseUser
{
// Add custom fields/methods
}
Context System Initialize the context system in a service or controller:
use BisonLab\CommonBundle\Context\Context;
$context = new Context();
$context->set('key', 'value');
$value = $context->get('key');
Extend Base User
Override methods or add fields in your custom User entity:
class User extends BaseUser
{
/**
* @ORM\Column(type="string", length=255)
*/
private $customField;
public function getCustomField(): ?string
{
return $this->customField;
}
}
Repository Integration
Use the base UserRepository or extend it:
namespace App\Repository;
use BisonLab\CommonBundle\Repository\UserRepository as BaseUserRepository;
class UserRepository extends BaseUserRepository
{
public function findByCustomField($value)
{
return $this->createQueryBuilder('u')
->andWhere('u.customField = :val')
->setParameter('val', $value)
->getQuery()
->getResult();
}
}
Generic REST Controller
The bundle provides a base AbstractRestController. Extend it for your endpoints:
namespace App\Controller;
use BisonLab\CommonBundle\Controller\AbstractRestController;
use App\Entity\User;
class UserController extends AbstractRestController
{
public function __construct(UserRepository $userRepository)
{
$this->repository = $userRepository;
}
}
Serialization Groups
Use the Serializer service to handle JSON serialization:
use Symfony\Component\Serializer\SerializerInterface;
class UserController extends AbstractRestController
{
public function __construct(
UserRepository $userRepository,
SerializerInterface $serializer
) {
$this->repository = $userRepository;
$this->serializer = $serializer;
}
public function getUser($id)
{
$user = $this->repository->find($id);
return $this->serializer->serialize($user, 'json', ['groups' => 'user:read']);
}
}
Request/Response Context Bind the context to the request lifecycle (e.g., in a listener):
use BisonLab\CommonBundle\Context\Context;
use Symfony\Component\HttpKernel\Event\RequestEvent;
class ContextListener
{
public function onKernelRequest(RequestEvent $event)
{
$context = new Context();
$event->getRequest()->attributes->set('context', $context);
}
}
Dependency Injection Inject the context into services:
namespace App\Service;
use BisonLab\CommonBundle\Context\Context;
class MyService
{
private $context;
public function __construct(Context $context)
{
$this->context = $context;
}
}
Context Scope Issues
The Context class is stateless by default. Ensure it’s properly scoped (e.g., per request) to avoid shared state across requests:
// Bad: Shared across all requests
$globalContext = new Context();
// Good: Per-request context
$requestContext = new Context();
$event->getRequest()->attributes->set('context', $requestContext);
User Entity Conflicts
If extending BaseUser, ensure your User entity is properly mapped in Doctrine. Override the base class’s __construct() if adding required fields:
public function __construct()
{
parent::__construct();
$this->customField = null; // Initialize required fields
}
No Default Configuration
The bundle has no config/packages/bisonlab_common.yaml. Customize behavior via services or entity overrides.
REST Controller Assumptions
AbstractRestController assumes:
repository property is set in the constructor.Serializable or have serialization groups defined.
Override methods like getSerializerGroups() if needed:protected function getSerializerGroups(): array
{
return ['user:read', 'user:write'];
}
Custom Context Storage
Extend Context to add storage backends (e.g., Redis):
use BisonLab\CommonBundle\Context\Context;
class RedisContext extends Context
{
private $redis;
public function __construct(\Redis $redis)
{
$this->redis = $redis;
}
public function get($key, $default = null)
{
return $this->redis->get($key) ?: $default;
}
public function set($key, $value)
{
$this->redis->set($key, $value);
}
}
Hooks for REST Actions
Override methods in AbstractRestController to customize REST actions:
protected function createEntity(array $data): User
{
$user = parent::createEntity($data);
$user->setCustomField($data['custom_field']); // Pre-save logic
return $user;
}
Event Dispatching The bundle doesn’t include events, but you can dispatch them manually in controllers or listeners:
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
class UserController extends AbstractRestController
{
public function __construct(
UserRepository $userRepository,
EventDispatcherInterface $dispatcher
) {
$this->repository = $userRepository;
$this->dispatcher = $dispatcher;
}
public function createUser(array $data)
{
$user = $this->createEntity($data);
$this->dispatcher->dispatch(new UserCreatedEvent($user));
return $this->saveEntity($user);
}
}
How can I help you explore Laravel packages today?