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

Doctrine Session Bundle Laravel Package

blast-project/doctrine-session-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require blast-project/doctrine-session-bundle
    

    Add the bundle to config/bundles.php (Symfony 4+) or AppKernel.php (Symfony 3/legacy):

    return [
        // ...
        Blast\DoctrineSessionBundle\BlastDoctrineSessionBundle::class => ['all' => true],
    ];
    
  2. Configure Doctrine Session Handler Add this to your config/packages/blast_doctrine_session.yaml (or merge into existing config):

    blast_doctrine_session:
        handler_id: 'blast.doctrine.session.handler'
        entity:
            class: App\Entity\Session
            repository: App\Repository\SessionRepository
    
  3. Create Session Entity Generate a basic Doctrine entity for sessions (adjust namespace and properties as needed):

    php bin/console make:entity Session
    

    Add these fields:

    • id (UUID or ID, primary key)
    • data (string, nullable)
    • lifetime (integer, nullable)
    • lastUsed (datetime, nullable)
    • ipAddress (string, nullable)
    • userAgent (string, nullable)

    Example entity (src/Entity/Session.php):

    namespace App\Entity;
    
    use Doctrine\ORM\Mapping as ORM;
    
    #[ORM\Entity(repositoryClass: "App\Repository\SessionRepository")]
    class Session
    {
        #[ORM\Id]
        #[ORM\Column(type: "uuid", unique: true)]
        #[ORM\GeneratedValue(strategy: "CUID")]
        private ?string $id = null;
    
        #[ORM\Column(type: "string", length: 255, nullable: true)]
        private ?string $data;
    
        #[ORM\Column(type: "integer", nullable: true)]
        private ?int $lifetime;
    
        #[ORM\Column(type: "datetime_immutable", nullable: true)]
        private ?\DateTimeImmutable $lastUsed;
    
        #[ORM\Column(type: "string", length: 45, nullable: true)]
        private ?string $ipAddress;
    
        #[ORM\Column(type: "text", nullable: true)]
        private ?string $userAgent;
    
        // Getters and setters...
    }
    
  4. Update Database Schema

    php bin/console doctrine:schema:update --force
    
  5. First Use Case: Replace Native Session Handler The bundle automatically replaces Symfony’s default session handler with Doctrine-based storage. Test by:

    // In a controller or service
    $session = $this->get('session');
    $session->set('foo', 'bar');
    dump($session->get('foo')); // Should output 'bar'
    

Implementation Patterns

Core Workflows

  1. Session Management

    • Reading/Writing Sessions: Use Symfony’s session service as usual. The bundle handles serialization/deserialization of session data to/from the data field in the Session entity.
      $session->start(); // Starts the session (if not already started)
      $session->set('user_id', 123);
      $userId = $session->get('user_id');
      
    • Session Expiry: The bundle respects Symfony’s session lifetime configuration (framework.session.lifetime). Expired sessions are automatically cleaned up via Doctrine’s SessionRepository (if implemented).
  2. Customizing Session Data

    • Extend the Session entity to include custom fields (e.g., rememberMeToken, loginAttempts):
      #[ORM\Column(type: "boolean")]
      private bool $rememberMe = false;
      
      #[ORM\Column(type: "integer")]
      private int $loginAttempts = 0;
      
    • Update the repository to filter or query these fields:
      // src/Repository/SessionRepository.php
      public function findByRememberMe(bool $rememberMe): array
      {
          return $this->createQueryBuilder('s')
              ->andWhere('s.rememberMe = :rememberMe')
              ->setParameter('rememberMe', $rememberMe)
              ->getQuery()
              ->getResult();
      }
      
  3. Integration with Security

    • Firewall Context: Store firewall-specific data (e.g., last login IP) in session:
      $session->set('_security_main', serialize(['ip' => $request->getClientIp()]));
      
    • Post-Authentication: Attach user-specific session data after login:
      public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $providerKey)
      {
          $session = $request->getSession();
          $session->set('user', $token->getUser());
          $session->set('last_login_ip', $request->getClientIp());
      }
      
  4. Session Cleanup

    • Manual Cleanup: Implement a cron job or command to purge old sessions:
      // src/Command/CleanupSessionsCommand.php
      namespace App\Command;
      
      use Symfony\Component\Console\Command\Command;
      use Symfony\Component\Console\Input\InputInterface;
      use Symfony\Component\Console\Output\OutputInterface;
      use Doctrine\ORM\EntityManagerInterface;
      
      class CleanupSessionsCommand extends Command
      {
          protected static $defaultName = 'app:cleanup-sessions';
      
          public function __construct(private EntityManagerInterface $em)
          {
              parent::__construct();
          }
      
          protected function execute(InputInterface $input, OutputInterface $output): int
          {
              $cutoff = new \DateTimeImmutable('-1 hour');
              $sessions = $this->em->getRepository(Session::class)->findBy(['lastUsed' => $cutoff]);
              foreach ($sessions as $session) {
                  $this->em->remove($session);
              }
              $this->em->flush();
              $output->writeln(sprintf('Removed %d expired sessions.', count($sessions)));
              return Command::SUCCESS;
          }
      }
      
    • Automatic Cleanup: Override the SessionRepository to add a postFlush listener for cleanup:
      // src/Repository/SessionRepository.php
      use Doctrine\ORM\Event\LifecycleEventArgs;
      
      public function postFlush(LifecycleEventArgs $args)
      {
          $em = $args->getEntityManager();
          $cutoff = new \DateTimeImmutable('-1 hour');
          $sessions = $em->createQuery(
              'SELECT s FROM App\Entity\Session s WHERE s.lastUsed < :cutoff'
          )->setParameter('cutoff', $cutoff)
           ->getResult();
          foreach ($sessions as $session) {
              $em->remove($session);
          }
      }
      
  5. Testing Sessions

    • Functional Tests: Use Symfony’s SessionTestCase or mock the session handler:
      use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
      
      class SessionTest extends WebTestCase
      {
          public function testSessionStorage()
          {
              $client = static::createClient();
              $client->request('GET', '/');
              $client->getContainer()->get('session')->set('test', 'value');
              $this->assertEquals('value', $client->getContainer()->get('session')->get('test'));
          }
      }
      
    • Unit Tests: Mock the SessionHandlerInterface to test session logic:
      $handler = $this->createMock(SessionHandlerInterface::class);
      $handler->expects($this->once())
          ->method('read')
          ->with('test_session_id')
          ->willReturn(serialize(['foo' => 'bar']));
      $this->container->set('blast.doctrine.session.handler', $handler);
      

Integration Tips

  1. Database Indexing

    • Add indexes to frequently queried fields (e.g., lastUsed, ipAddress) for performance:
      #[ORM\Index(name: "idx_last_used", columns: ["lastUsed"])]
      #[ORM\Index(name: "idx_ip_address", columns: ["ipAddress"])]
      
  2. Session Serialization

    • Customize serialization by implementing a custom SessionHandler:
      // src/Service/CustomSessionHandler.php
      namespace App\Service;
      
      use Blast\DoctrineSessionBundle\Handler\DoctrineSessionHandler;
      use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler;
      
      class CustomSessionHandler extends DoctrineSessionHandler
      {
          public function read($sessionId): string|false
          {
              $data = parent::read($sessionId);
              return $data ? gzuncompress($data) : false;
          }
      
          public function write($sessionId, $data): bool
          {
              return parent::write($sessionId, gzcompress($data));
          }
      }
      
    • Register the handler in config/services.yaml:
      services:
          App\Service\CustomSessionHandler:
              arguments:
                  $entityManager: '@doctrine.
      
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui