## Getting Started
### Minimal Setup for Laravel Integration (Symfony Bridge)
Since `pd-user` is a Symfony bundle, Laravel developers must use **Symfony’s Laravel Bridge** (`symfony/ux-live-component` or `symfony/panther` for testing) or **Laravel’s Symfony Integration** (e.g., `spatie/symfony-laravel`). For simplicity, we’ll assume a hybrid approach via **Laravel’s Symfony Components** or a **micro-service architecture**.
#### Step 1: Install Dependencies
```bash
composer require appaydin/pd-user symfony/mailer symfony/event-dispatcher symfony/security-bundle
Note: Laravel’s native auth system conflicts with Symfony’s security.yaml. Use Laravel’s spatie/laravel-symfony-support for seamless integration:
composer require spatie/laravel-symfony-support
Publish the Symfony config:
php artisan vendor:publish --provider="Spatie\SymfonySupport\SymfonySupportServiceProvider"
Update config/symfony.php to include:
'symfony' => [
'bundles' => [
Pd\UserBundle\PdUserBundle::class,
],
],
Extend Symfony’s BaseUser/BaseGroup with Laravel’s Eloquent:
// app/Models/User.php (Laravel Eloquent + Symfony ORM)
namespace App\Models;
use Pd\UserBundle\Model\User as BaseUser;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable implements BaseUser
{
use Notifiable;
protected $table = 'users';
protected $primaryKey = 'id';
// Symfony ORM mapping (if using Doctrine via Laravel)
public function __construct()
{
parent::__construct();
$this->setTable('users'); // Match Laravel's table
}
// Laravel-specific methods (e.g., `sendPasswordResetNotification`)
}
user.yaml (Laravel Adaptation)Create config/packages/user.yaml (Symfony-style) and load it via Laravel’s config:
pd_user:
user_class: App\Models\User
group_class: App\Models\Group
default_group: '1' # ID of default group
login_redirect: 'home' # Laravel route name
email_confirmation: true
welcome_email: true
user_registration: true
mail_sender_address: 'noreply@example.com'
active_language: ['en']
Use Laravel’s route model binding to proxy Symfony routes:
// routes/web.php
Route::prefix('auth')->group(function () {
Route::get('/login', [PdUserController::class, 'login'])->name('security_login');
Route::post('/register', [PdUserController::class, 'register']);
// ... other pd-user routes
});
use Pd\UserBundle\Form\RegistrationType;
$form = $this->createForm(RegistrationType::class);
$userManager = $this->get('pd_user.user_manager');
$user = $userManager->createUser($form->getData());
$userManager->updateUser($user);
$event = new UserEvent($user);
$this->get('event_dispatcher')->dispatch(UserEvent::REGISTER_CONFIRM, $event);
Leverage Symfony’s event system for custom logic:
// Listen to registration confirmation
$dispatcher->addListener(UserEvent::REGISTER_CONFIRM, function (UserEvent $event) {
// Send Laravel notification
$event->getUser()->notify(new Registered($event->getUser()));
});
Combine Laravel’s Gate with Symfony’s RoleHierarchy:
// config/security.yaml (Symfony)
role_hierarchy:
ROLE_ADMIN: [ROLE_USER, ROLE_EDITOR]
// Laravel Gates
Gate::define('edit-post', function ($user) {
return $user->hasRole('ROLE_EDITOR'); // Assume `hasRole()` is added to User model
});
Use Symfony’s UserChecker for pre-auth checks alongside Laravel’s AuthenticatesUsers:
// app/Http/Controllers/Auth/LoginController.php
use Pd\UserBundle\Security\UserChecker;
class LoginController extends Controller
{
protected $userChecker;
public function __construct(UserChecker $userChecker)
{
$this->userChecker = $userChecker;
}
public function showLoginForm()
{
$this->userChecker->checkPostAuth($this->getUser()); // Symfony check
return view('auth.login');
}
}
Extend Twig templates (if using Laravel Mix + Symfony UX):
{# resources/views/auth/register.html.twig #}
{% extends '@PdUser/registration.html.twig' %}
{% block pd_user_registration_form %}
{{ form_start(form) }}
<div class="form-group">
{{ form_row(form.email) }}
{{ form_row(form.password) }}
<button type="submit" class="btn btn-primary">Register</button>
</div>
{{ form_end(form) }}
{% endblock %}
Use Laravel Migrations for users/groups tables, then sync with Doctrine:
// database/migrations/xxxx_create_users_table.php
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('email')->unique();
$table->string('password');
$table->boolean('is_active')->default(false);
$table->timestamps();
});
Run:
php artisan migrate
php artisan doctrine:schema:update --force # Sync with Symfony ORM
spatie/laravel-doctrine-orm for hybrid ORM support or stick to Eloquent and mock Symfony’s EntityManager:
$entityManager = $this->app->make('doctrine')->getManager();
$user = $entityManager->find(User::class, $id);
Auth::routes() and Symfony’s pd_user routes may conflict.
Fix: Explicitly prefix Symfony routes:
# config/routes.yaml (Symfony)
auth_login:
path: /auth/login
controller: Pd\UserBundle\Controller\SecurityController::login
In Laravel, proxy the route:
Route::get('/auth/login', function () {
return redirect()->route('symfony.route.auth_login'); // Hypothetical proxy
});
mailer expects a different config than Laravel’s mail.
Fix: Use Laravel’s Mail facade to send emails triggered by Symfony events:
$dispatcher->addListener(UserEvent::REGISTER_CONFIRM, function ($event) {
Mail::to($event->getUser()->email)->send(new WelcomeEmail($event->getUser()));
});
password_hashers may not align with Laravel’s Hash.
Fix: Use a shared hasher:
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
$hasher = $this->get('security.password_hasher');
$user->setPassword($hasher->hashPassword($user, $plainPassword));
php artisan tinker
>>> $dispatcher = app('event');
>>> $dispatcher->addListener(UserEvent::REGISTER, function ($event) {
... dd($event->getUser());
... });
vendor/pd-user-bundle/Resources/views to resources/views/vendor/pd-user to override without modifying the bundle.$user->load('groups'); // Eager load in Laravel
session(['user_groups' => $user->groups->pluck('name')]);
symfony/panther for browser testing:
How can I help you explore Laravel packages today?