ezsystems/ezplatform-user
User management bundle for eZ Platform/EzPlatform: handles users, roles and permissions, authentication and related services. Integrates with the repository and security layer to manage accounts, groups, and access control in eZ-based apps.
## Getting Started
### Minimal Setup
1. **Installation**
```bash
composer require ezsystems/ezplatform-user:^2.3.12
Ensure your project extends ezsystems/ezplatform-user in composer.json under require.
Service Configuration
Add the bundle to config/bundles.php:
return [
// ...
EzSystems\EzPlatformUserBundle\EzSystemsEzPlatformUserBundle::class => ['all' => true],
];
First Use Case: User Creation with Generator Workflow Leverage the new reusable generator workflow for streamlined user creation:
use EzSystems\EzPlatformUserBundle\Service\UserGenerator;
public function __construct(private UserGenerator $userGenerator) {}
public function generateUser()
{
$user = $this->userGenerator->generate([
'email' => 'john.doe@example.com',
'password' => 'securePassword123',
'roles' => ['ROLE_USER'],
'firstName' => 'John',
'lastName' => 'Doe',
]);
$this->userService->saveUser($user);
}
Note: The UserGenerator replaces manual entity construction for common use cases.
Key Classes to Explore
UserGenerator: New reusable workflow for user creation (replaces manual UserService calls for standard cases).UserService: Core interface for advanced CRUD operations (still required for custom logic).User: Entity representing users (extends ezsystems/ezplatform-kernel User).UserRepository: For querying users (e.g., findByEmail()).// 1. Use the new generator for standard cases
$user = $this->userGenerator->generate([
'email' => 'john.doe@example.com',
'password' => 'plainPassword123', // Automatically hashed
'roles' => ['ROLE_USER'],
'customFields' => ['department' => 'Marketing'],
]);
// 2. Save and trigger events
$userService->saveUser($user);
event(new UserRegisteredEvent($user));
// Add role to existing user
$user = $userService->loadUserByUsername('john.doe@example.com');
$user->addRole('ROLE_ADMIN');
$userService->saveUser($user);
// Generate 10 users with reusable template
$users = $userGenerator->generateBulk(10, [
'emailTemplate' => 'user{index}@example.com',
'password' => 'defaultPass123',
'roles' => ['ROLE_USER'],
]);
foreach ($users as $user) {
$userService->saveUser($user);
}
// Export users to CSV (unchanged)
$users = $userRepository->findAll();
$csv = new League\Csv\Writer(fopen('php://output', 'w'));
$csv->insertOne(['Email', 'Roles']);
foreach ($users as $user) {
$csv->insertOne([$user->getEmail(), implode(', ', $user->getRoles())]);
}
Service Provider Binding (Updated)
Bind both UserService and UserGenerator in AppServiceProvider:
$this->app->bind(UserGenerator::class, function ($app) {
return new UserGenerator(
$app->make(UserService::class),
$app->make(UserPasswordHasherInterface::class)
);
});
Event Listeners (Unchanged)
Listen to UserRegisteredEvent in Laravel’s event system:
Event::listen(UserRegisteredEvent::class, function (UserRegisteredEvent $event) {
// Send welcome email, log activity, etc.
});
Query Builder Extensions (Unchanged)
Extend the UserRepository to add custom methods:
class CustomUserRepository extends UserRepository
{
public function findActiveUsers()
{
return $this->createQueryBuilder('u')
->where('u.enabled = :enabled')
->setParameter('enabled', true)
->getQuery()
->getResult();
}
}
User model with ezsystems/ezplatform-user’s User and use UserGenerator for registration:
// In Fortify's CreateNewUser action
$user = $userGenerator->generate($request->only(['email', 'password']));
$userService->saveUser($user);
Resource to work with User entity (unchanged).UserService for OAuth user resolution (unchanged).Password Hashing Mismatch (Updated)
UserGenerator automatically handles password hashing. Avoid manually hashing passwords when using the generator:
// ❌ Avoid this with UserGenerator
$hashed = $passwordHasher->hashPassword($user, 'plainPassword');
// ✅ Correct (let UserGenerator handle it)
$user = $userGenerator->generate(['password' => 'plainPassword']);
Role Hierarchy Conflicts (Unchanged)
ROLE_ADMIN may override ROLE_USER. Test role inheritance explicitly.Entity Manager Detachment (Unchanged)
$entityManager->persist($user);
$entityManager->flush();
Custom Fields Not Persisted (Updated)
UserGenerator payload:
$user = $userGenerator->generate([
'email' => 'test@example.com',
'customFields' => [ // Required for non-standard fields
'department' => 'Engineering',
'hireDate' => '2023-01-01',
],
]);
User Not Found Exceptions (Unchanged)
UserRepository is properly injected. Override loadUserByUsername() to log queries.Password Reset Issues (Unchanged)
UserPasswordHasherInterface is configured in Symfony’s security.yaml.Generator Validation Failures (New)
UserGenerator validates input. Check for errors:
try {
$user = $userGenerator->generate(['email' => 'invalid-email']);
} catch (InvalidArgumentException $e) {
\Log::error("Generator validation failed: " . $e->getMessage());
}
Bulk Generation Issues (New)
$users = $userGenerator->generateBulk(5, [
'emailTemplate' => 'user{index}@example.com', // Must include {index}
'password' => 'securePass123',
]);
Custom User Fields (Updated)
Extend the User entity and update the UserGenerator:
class CustomUserGenerator extends UserGenerator
{
protected function configureUser(User $user, array $data): void
{
parent::configureUser($user, $data);
$user->setCustomField($data['customField'] ?? null);
}
}
Pre/Post Save Logic (Unchanged) Use Doctrine lifecycle callbacks:
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\PrePersist
*/
public function setCreatedAt()
{
$this->createdAt = new \DateTime();
}
API Resource Transformers (Unchanged) Create a custom serializer for API responses.
Bulk Operations (Updated)
Combine UserGenerator with bulk updates:
// Generate and save in bulk
$users = $userGenerator->generateBulk(100, ['emailTemplate' => 'user{index}@example.com']);
$entityManager->persist($users); // Doctrine bulk persist
$entityManager->flush();
Security.yaml Overrides (Unchanged)
Ensure the user_provider points to your custom provider.
Environment-Specific Roles (Unchanged)
Use Laravel’s config() to dynamically assign roles.
Caching User Lookups (Updated)
Cache UserRepository queries, but invalidate after bulk operations:
// After bulk generation
Cache::forget
How can I help you explore Laravel packages today?