Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- Enh #86: Remove `yiisoft/cookies` dependency (@vjik)
- Bug #86: `NullSession::getCookieParameters()` now returns proper cookie parameters instead of an empty array (@vjik)
- Bug #25: Fix reusing the previous session ID in `Session::open()` in long-running workers (@klsoft-web)

## 3.0.2 August 26, 2026

Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,17 @@ $session = new \Yiisoft\Session\Session([], $handler);

Custom storage must implement `\SessionHandlerInterface`.

## Custom session ID

When using `Yiisoft\Session\Session` as session component, you can provide your own implementation of the session ID creator:

```php
$idCreator = new MySessionId();
$session = new \Yiisoft\Session\Session([], null, $idCreator);
```

The custom session ID creator must implement the `\SessionIdInterface`.

## Documentation

- [Internals](docs/internals.md)
Expand Down
1 change: 1 addition & 0 deletions config/di-web.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
'__construct()' => [
$params['yiisoft/session']['session']['options'],
$params['yiisoft/session']['session']['handler'],
$params['yiisoft/session']['session']['idCreator'],
],
'reset' => function () {
$this->sessionId = null;
Expand Down
1 change: 1 addition & 0 deletions config/params.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
'session' => [
'options' => ['cookie_secure' => 0],
'handler' => null,
'idCreator' => null,
],
],
];
9 changes: 8 additions & 1 deletion src/Session.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Yiisoft\Session;

use SessionHandlerInterface;
use SessionIdInterface;
use Throwable;

use const PHP_SESSION_ACTIVE;
Expand Down Expand Up @@ -38,10 +39,14 @@ final class Session implements SessionInterface
/**
* @param array $options Session options. See {@link https://www.php.net/manual/en/session.configuration.php}.
* @param SessionHandlerInterface|null $handler Session handler. If not specified, default PHP handler is used.
* @param SessionIdInterface|null $idCreator Session id creator.
*
* @psalm-param SessionOptions $options
*/
public function __construct(array $options = [], ?SessionHandlerInterface $handler = null)
public function __construct(
array $options = [],
?SessionHandlerInterface $handler = null,
private ?SessionIdInterface $idCreator = null)
{
if ($handler !== null) {
session_set_save_handler($handler, true);
Expand Down Expand Up @@ -94,6 +99,8 @@ public function open(): void

if ($this->sessionId !== null) {
session_id($this->sessionId);
} else if ($this->idCreator !== null) {
session_id($this->idCreator->create_sid());
}

try {
Expand Down
17 changes: 17 additions & 0 deletions tests/MockSessionId.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Yiisoft\Session\Tests;

use SessionIdInterface;

final class MockSessionId implements SessionIdInterface
{
public function __construct(private string $sessionId)
{
}

public function create_sid(): string
{
return $this->sessionId;
}
}
13 changes: 13 additions & 0 deletions tests/SessionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,19 @@ public function testRegenerateIdOpensInactiveSession(): void
self::assertNotEquals($id, $session->getId());
}

public function testOpenDoesNotReuseIdOfClosedSession(): void
{
$firstSession = new Session([], null, new MockSessionId('first-session-id'));
$firstSession->open();
$firstId = $firstSession->getId();
$firstSession->close();

$secondSession = new Session([], null, new MockSessionId('second-session-id'));
$secondSession->open();

self::assertNotSame($firstId, $secondSession->getId());
}

public function testDiscard(): void
{
$session = $this->getSession();
Expand Down
Loading