Installation
composer require apiboxsym/user-bundle
Add to config/bundles.php:
return [
// ...
ApiBoxSym\UserBundle\ApiBoxSymUserBundle::class => ['all' => true],
];
Database Migrations Run migrations to create required tables:
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
First Use Case: User Registration
Expose the User resource via API Platform:
# config/api_platform/resources.yaml
resources:
ApiBoxSym\UserBundle\Entity\User:
collectionOperations:
post: { method: 'POST', path: '/register' }
Test with:
curl -X POST http://your-app/register -d '{"email":"test@example.com","password":"secret"}'
Check config/packages/apiboxsym_user.yaml for:
default_roles)password_hash_algorithm)email_verification)$user = $userRepository->find($id);
$user->addRole('ROLE_ADMIN'); // Uses Symfony's Role hierarchy
$entityManager->flush();
$this->denyAccessUnlessGranted('ROLE_EDITOR', $user);
// Or via custom permission:
$this->denyAccessUnlessGranted('user:edit:own', $user);
$group = new Group();
$group->setName('Developers');
$group->addRole('ROLE_DEVELOPER');
$entityManager->persist($group);
$user->addGroup($group);
IS_AUTHENTICATED_FULLY):
# config/api_platform/resources.yaml
ApiBoxSym\UserBundle\Entity\User:
itemOperations:
put: { method: 'PUT', security: 'is_granted("ROLE_ADMIN")' }
PermissionChecker service to fetch all permissions for a user:
$permissions = $permissionChecker->getPermissionsForUser($user);
// src/EventListener/UserPasswordResetListener.php
public function onPasswordReset(UserPasswordResetEvent $event) {
$this->mailer->send(new ResetPasswordEmail($event->getUser()));
}
Register in services.yaml:
services:
App\EventListener\UserPasswordResetListener:
tags:
- { name: 'kernel.event_listener', event: 'user.password_reset' }
ApiBoxSym\UserBundle\Security\UserProvider to add custom logic:
class CustomUserProvider extends UserProvider {
public function loadUserByIdentifier($identifier) {
// Custom logic
}
}
Register in security.yaml:
providers:
app_user_provider:
id: App\Security\CustomUserProvider
User serialization via ApiPlatform\Metadata\Operation:
#[ApiResource(
operations: [
new Get(
normalizationContext: ['groups' => ['user:read']]
)
]
)]
ApiBoxSym\UserBundle\Repository\UserRepository:
class CustomUserRepository extends UserRepository {
public function findByRole(string $role) {
return $this->createQueryBuilder('u')
->where('u.roles LIKE :role')
->setParameter('role', '%'.$role.'%')
->getQuery()
->getResult();
}
}
Role Hierarchy Conflicts
ROLE_ADMIN implies ROLE_USER), ensure your custom roles don’t conflict.php bin/console debug:role to validate hierarchy.Permission Caching
PermissionChecker caches permissions. Clear cache after role changes:
php bin/console cache:clear
permission_checker.clear_cache() in post-update listeners.Email Verification Tokens
config/apiboxsym_user.yaml:
email_verification:
token_ttl: 86400 # 1 day in seconds
API Platform Security
IS_AUTHENTICATED_FULLY is used for sensitive operations to avoid bypassing RBAC.security: "is_granted('ROLE_ADMIN') or object == user"
Doctrine Lifecycle Callbacks
$entityManager->getConnection()->beginTransaction();
$entityManager->getConnection()->getConfiguration()->setSQLLogger(null);
// Bulk operations here
$entityManager->getConnection()->commit();
Enable SQL Logging
# config/packages/dev/doctrine.yaml
doctrine:
dbal:
logging: true
profiling: true
Check Events Enable event dispatching logs:
bin/console debug:event-dispatcher
Permission Debugging Dump user permissions:
dump($permissionChecker->getPermissionsForUser($user));
Custom User Entity
Extend ApiBoxSym\UserBundle\Entity\User:
class CustomUser extends User {
#[ORM\Column]
private ?string $customField = null;
// Add getters/setters
}
Update config/apiboxsym_user.yaml:
user_entity: App\Entity\CustomUser
Custom Group/Role Entities Override default entities by configuring:
group_entity: App\Entity\CustomGroup
role_entity: App\Entity\CustomRole
Custom Permission Voter Create a voter and tag it:
#[AsVoter]
class CustomPermissionVoter implements VoterInterface {
public function supports(string $attribute, $subject): bool {
return $attribute === 'user:custom_action';
}
}
Custom Serializers
Override User serialization groups:
#[Groups(['user:public'])]
public function getPublicName(): string {
return $this->name;
}
Custom Migrations Extend migrations by creating a post-install command:
#[AsCommand(name: 'apiboxsym:user:post-install')]
class PostInstallCommand extends Command {
protected function execute(InputInterface $input, OutputInterface $output): int {
// Custom logic (e.g., seed default roles)
}
}
How can I help you explore Laravel packages today?