├── LICENSE ├── README.md ├── composer.json └── src ├── Exceptions ├── HeadersSentException.php ├── SessionException.php ├── SessionNotStartedException.php ├── SessionStartedException.php └── WrongSessionOptionException.php ├── Facades └── Session.php └── Session.php /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright (c) 2017, Josantonius 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | this software and associated documentation files (the "Software"), to deal in 8 | the Software without restriction, including without limitation the rights to 9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 10 | of the Software, and to permit persons to whom the Software is furnished to do 11 | so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PHP Session library 2 | 3 | [![Latest Stable Version](https://poser.pugx.org/josantonius/session/v/stable)](https://packagist.org/packages/josantonius/session) 4 | [![License](https://poser.pugx.org/josantonius/session/license)](LICENSE) 5 | [![Total Downloads](https://poser.pugx.org/josantonius/session/downloads)](https://packagist.org/packages/josantonius/session) 6 | [![CI](https://github.com/josantonius/php-session/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/josantonius/php-session/actions/workflows/ci.yml) 7 | [![CodeCov](https://codecov.io/gh/josantonius/php-session/branch/main/graph/badge.svg)](https://codecov.io/gh/josantonius/php-session) 8 | [![PSR1](https://img.shields.io/badge/PSR-1-f57046.svg)](https://www.php-fig.org/psr/psr-1/) 9 | [![PSR4](https://img.shields.io/badge/PSR-4-9b59b6.svg)](https://www.php-fig.org/psr/psr-4/) 10 | [![PSR12](https://img.shields.io/badge/PSR-12-1abc9c.svg)](https://www.php-fig.org/psr/psr-12/) 11 | 12 | **Translations**: [Español](.github/lang/es-ES/README.md) 13 | 14 | PHP library for handling sessions. 15 | 16 | --- 17 | 18 | - [Requirements](#requirements) 19 | - [Installation](#installation) 20 | - [Available Classes](#available-classes) 21 | - [Session Class](#session-class) 22 | - [Session Facade](#session-facade) 23 | - [Exceptions Used](#exceptions-used) 24 | - [Usage](#usage) 25 | - [Tests](#tests) 26 | - [TODO](#todo) 27 | - [Changelog](#changelog) 28 | - [Contribution](#contribution) 29 | - [Sponsor](#sponsor) 30 | - [License](#license) 31 | 32 | --- 33 | 34 | ## Requirements 35 | 36 | - Operating System: Linux | Windows. 37 | 38 | - PHP versions: 8.0 | 8.1 | 8.2 | 8.3. 39 | 40 | ## Installation 41 | 42 | The preferred way to install this extension is through [Composer](http://getcomposer.org/download/). 43 | 44 | To install **PHP Session library**, simply: 45 | 46 | ```console 47 | composer require josantonius/session 48 | ``` 49 | 50 | The previous command will only install the necessary files, 51 | if you prefer to **download the entire source code** you can use: 52 | 53 | ```console 54 | composer require josantonius/session --prefer-source 55 | ``` 56 | 57 | You can also **clone the complete repository** with Git: 58 | 59 | ```console 60 | git clone https://github.com/josantonius/php-session.git 61 | ``` 62 | 63 | ## Available Classes 64 | 65 | ### Session Class 66 | 67 | `Josantonius\Session\Session` 68 | 69 | Starts the session: 70 | 71 | ```php 72 | /** 73 | * @throws HeadersSentException if headers already sent. 74 | * @throws SessionStartedException if session already started. 75 | * @throws WrongSessionOptionException if setting options failed. 76 | * 77 | * @see https://php.net/session.configuration for List of available $options. 78 | */ 79 | public function start(array $options = []): bool; 80 | ``` 81 | 82 | Check if the session is started: 83 | 84 | ```php 85 | public function isStarted(): bool; 86 | ``` 87 | 88 | Sets an attribute by name: 89 | 90 | ```php 91 | /** 92 | * @throws SessionNotStartedException if session was not started. 93 | */ 94 | public function set(string $name, mixed $value): void; 95 | ``` 96 | 97 | Gets an attribute by name: 98 | 99 | ```php 100 | /** 101 | * Optionally defines a default value when the attribute does not exist. 102 | */ 103 | public function get(string $name, mixed $default = null): mixed; 104 | ``` 105 | 106 | Gets all attributes: 107 | 108 | ```php 109 | public function all(): array; 110 | ``` 111 | 112 | Check if an attribute exists in the session: 113 | 114 | ```php 115 | public function has(string $name): bool; 116 | ``` 117 | 118 | Sets several attributes at once: 119 | 120 | ```php 121 | /** 122 | * If attributes exist they are replaced, if they do not exist they are created. 123 | * 124 | * @throws SessionNotStartedException if session was not started. 125 | */ 126 | public function replace(array $data): void; 127 | ``` 128 | 129 | Deletes an attribute by name and returns its value: 130 | 131 | ```php 132 | /** 133 | * Optionally defines a default value when the attribute does not exist. 134 | * 135 | * @throws SessionNotStartedException if session was not started. 136 | */ 137 | public function pull(string $name, mixed $default = null): mixed; 138 | ``` 139 | 140 | Deletes an attribute by name: 141 | 142 | ```php 143 | /** 144 | * @throws SessionNotStartedException if session was not started. 145 | */ 146 | public function remove(string $name): void; 147 | ``` 148 | 149 | Free all session variables: 150 | 151 | ```php 152 | /** 153 | * @throws SessionNotStartedException if session was not started. 154 | */ 155 | public function clear(): void; 156 | ``` 157 | 158 | Gets the session ID: 159 | 160 | ```php 161 | public function getId(): string; 162 | ``` 163 | 164 | Sets the session ID: 165 | 166 | ```php 167 | /** 168 | * @throws SessionStartedException if session already started. 169 | */ 170 | public function setId(string $sessionId): void; 171 | ``` 172 | 173 | Update the current session ID with a newly generated one: 174 | 175 | ```php 176 | /** 177 | * @throws SessionNotStartedException if session was not started. 178 | */ 179 | public function regenerateId(bool $deleteOldSession = false): bool; 180 | ``` 181 | 182 | Gets the session name: 183 | 184 | ```php 185 | public function getName(): string; 186 | ``` 187 | 188 | Sets the session name: 189 | 190 | ```php 191 | /** 192 | * @throws SessionStartedException if session already started. 193 | */ 194 | public function setName(string $name): void; 195 | ``` 196 | 197 | Destroys the session: 198 | 199 | ```php 200 | /** 201 | * @throws SessionNotStartedException if session was not started. 202 | */ 203 | public function destroy(): bool; 204 | ``` 205 | 206 | ### Session Facade 207 | 208 | `Josantonius\Session\Facades\Session` 209 | 210 | Starts the session: 211 | 212 | ```php 213 | /** 214 | * @throws HeadersSentException if headers already sent. 215 | * @throws SessionStartedException if session already started. 216 | * @throws WrongSessionOptionException if setting options failed. 217 | * 218 | * @see https://php.net/session.configuration for List of available $options. 219 | */ 220 | public static function start(array $options = []): bool; 221 | ``` 222 | 223 | Check if the session is started: 224 | 225 | ```php 226 | public static function isStarted(): bool; 227 | ``` 228 | 229 | Sets an attribute by name: 230 | 231 | ```php 232 | /** 233 | * @throws SessionNotStartedException if session was not started. 234 | */ 235 | public static function set(string $name, mixed $value): void; 236 | ``` 237 | 238 | Gets an attribute by name: 239 | 240 | ```php 241 | /** 242 | * Optionally defines a default value when the attribute does not exist. 243 | */ 244 | public static function get(string $name, mixed $default = null): mixed; 245 | ``` 246 | 247 | Gets all attributes: 248 | 249 | ```php 250 | public static function all(): array; 251 | ``` 252 | 253 | Check if an attribute exists in the session: 254 | 255 | ```php 256 | public static function has(string $name): bool; 257 | ``` 258 | 259 | Sets several attributes at once: 260 | 261 | ```php 262 | /** 263 | * If attributes exist they are replaced, if they do not exist they are created. 264 | * 265 | * @throws SessionNotStartedException if session was not started. 266 | */ 267 | public static function replace(array $data): void; 268 | ``` 269 | 270 | Deletes an attribute by name and returns its value: 271 | 272 | ```php 273 | /** 274 | * Optionally defines a default value when the attribute does not exist. 275 | * 276 | * @throws SessionNotStartedException if session was not started. 277 | */ 278 | public static function pull(string $name, mixed $default = null): mixed; 279 | ``` 280 | 281 | Deletes an attribute by name: 282 | 283 | ```php 284 | /** 285 | * @throws SessionNotStartedException if session was not started. 286 | */ 287 | public static function remove(string $name): void; 288 | ``` 289 | 290 | Free all session variables: 291 | 292 | ```php 293 | /** 294 | * @throws SessionNotStartedException if session was not started. 295 | */ 296 | public static function clear(): void; 297 | ``` 298 | 299 | Gets the session ID: 300 | 301 | ```php 302 | public static function getId(): string; 303 | ``` 304 | 305 | Sets the session ID: 306 | 307 | ```php 308 | /** 309 | * @throws SessionStartedException if session already started. 310 | */ 311 | public static function setId(string $sessionId): void; 312 | ``` 313 | 314 | Update the current session ID with a newly generated one: 315 | 316 | ```php 317 | /** 318 | * @throws SessionNotStartedException if session was not started. 319 | */ 320 | public static function regenerateId(bool $deleteOldSession = false): bool; 321 | ``` 322 | 323 | Gets the session name: 324 | 325 | ```php 326 | public static function getName(): string; 327 | ``` 328 | 329 | Sets the session name: 330 | 331 | ```php 332 | /** 333 | * @throws SessionStartedException if session already started. 334 | */ 335 | public static function setName(string $name): void; 336 | ``` 337 | 338 | Destroys the session: 339 | 340 | ```php 341 | /** 342 | * @throws SessionNotStartedException if session was not started. 343 | */ 344 | public static function destroy(): bool; 345 | ``` 346 | 347 | ## Exceptions Used 348 | 349 | ```php 350 | use Josantonius\Session\Exceptions\HeadersSentException; 351 | use Josantonius\Session\Exceptions\SessionException; 352 | use Josantonius\Session\Exceptions\SessionNotStartedException; 353 | use Josantonius\Session\Exceptions\SessionStartedException; 354 | use Josantonius\Session\Exceptions\WrongSessionOptionException; 355 | ``` 356 | 357 | ## Usage 358 | 359 | Example of use for this library: 360 | 361 | ### Starts the session without setting options 362 | 363 | ```php 364 | use Josantonius\Session\Session; 365 | 366 | $session = new Session(); 367 | 368 | $session->start(); 369 | ``` 370 | 371 | ```php 372 | use Josantonius\Session\Facades\Session; 373 | 374 | Session::start(); 375 | ``` 376 | 377 | ### Starts the session setting options 378 | 379 | ```php 380 | use Josantonius\Session\Session; 381 | 382 | $session = new Session(); 383 | 384 | $session->start([ 385 | // 'cache_expire' => 180, 386 | // 'cache_limiter' => 'nocache', 387 | // 'cookie_domain' => '', 388 | 'cookie_httponly' => true, 389 | 'cookie_lifetime' => 8000, 390 | // 'cookie_path' => '/', 391 | 'cookie_samesite' => 'Strict', 392 | 'cookie_secure' => true, 393 | // 'gc_divisor' => 100, 394 | // 'gc_maxlifetime' => 1440, 395 | // 'gc_probability' => true, 396 | // 'lazy_write' => true, 397 | // 'name' => 'PHPSESSID', 398 | // 'read_and_close' => false, 399 | // 'referer_check' => '', 400 | // 'save_handler' => 'files', 401 | // 'save_path' => '', 402 | // 'serialize_handler' => 'php', 403 | // 'sid_bits_per_character' => 4, 404 | // 'sid_length' => 32, 405 | // 'trans_sid_hosts' => $_SERVER['HTTP_HOST'], 406 | // 'trans_sid_tags' => 'a=href,area=href,frame=src,form=', 407 | // 'use_cookies' => true, 408 | // 'use_only_cookies' => true, 409 | // 'use_strict_mode' => false, 410 | // 'use_trans_sid' => false, 411 | ]); 412 | ``` 413 | 414 | ```php 415 | use Josantonius\Session\Facades\Session; 416 | 417 | Session::start([ 418 | 'cookie_httponly' => true, 419 | ]); 420 | ``` 421 | 422 | ### Check if the session is started 423 | 424 | ```php 425 | use Josantonius\Session\Session; 426 | 427 | $session = new Session(); 428 | 429 | $session->isStarted(); 430 | ``` 431 | 432 | ```php 433 | use Josantonius\Session\Facades\Session; 434 | 435 | Session::isStarted(); 436 | ``` 437 | 438 | ### Sets an attribute by name 439 | 440 | ```php 441 | use Josantonius\Session\Session; 442 | 443 | $session = new Session(); 444 | 445 | $session->set('foo', 'bar'); 446 | ``` 447 | 448 | ```php 449 | use Josantonius\Session\Facades\Session; 450 | 451 | Session::set('foo', 'bar'); 452 | ``` 453 | 454 | ### Gets an attribute by name without setting a default value 455 | 456 | ```php 457 | use Josantonius\Session\Session; 458 | 459 | $session = new Session(); 460 | 461 | $session->get('foo'); // null if attribute does not exist 462 | ``` 463 | 464 | ```php 465 | use Josantonius\Session\Facades\Session; 466 | 467 | Session::get('foo'); // null if attribute does not exist 468 | ``` 469 | 470 | ### Gets an attribute by name setting a default value 471 | 472 | ```php 473 | use Josantonius\Session\Session; 474 | 475 | $session = new Session(); 476 | 477 | $session->get('foo', false); // false if attribute does not exist 478 | ``` 479 | 480 | ```php 481 | use Josantonius\Session\Facades\Session; 482 | 483 | Session::get('foo', false); // false if attribute does not exist 484 | ``` 485 | 486 | ### Gets all attributes 487 | 488 | ```php 489 | use Josantonius\Session\Session; 490 | 491 | $session = new Session(); 492 | 493 | $session->all(); 494 | ``` 495 | 496 | ```php 497 | use Josantonius\Session\Facades\Session; 498 | 499 | Session::all(); 500 | ``` 501 | 502 | ### Check if an attribute exists in the session 503 | 504 | ```php 505 | use Josantonius\Session\Session; 506 | 507 | $session = new Session(); 508 | 509 | $session->has('foo'); 510 | ``` 511 | 512 | ```php 513 | use Josantonius\Session\Facades\Session; 514 | 515 | Session::has('foo'); 516 | ``` 517 | 518 | ### Sets several attributes at once 519 | 520 | ```php 521 | use Josantonius\Session\Session; 522 | 523 | $session = new Session(); 524 | 525 | $session->replace(['foo' => 'bar', 'bar' => 'foo']); 526 | ``` 527 | 528 | ```php 529 | use Josantonius\Session\Facades\Session; 530 | 531 | Session::replace(['foo' => 'bar', 'bar' => 'foo']); 532 | ``` 533 | 534 | ### Deletes an attribute and returns its value or the default value if not exist 535 | 536 | ```php 537 | use Josantonius\Session\Session; 538 | 539 | $session = new Session(); 540 | 541 | $session->pull('foo'); // null if attribute does not exist 542 | ``` 543 | 544 | ```php 545 | use Josantonius\Session\Facades\Session; 546 | 547 | Session::pull('foo'); // null if attribute does not exist 548 | ``` 549 | 550 | ### Deletes an attribute and returns its value or the custom value if not exist 551 | 552 | ```php 553 | use Josantonius\Session\Session; 554 | 555 | $session = new Session(); 556 | 557 | $session->pull('foo', false); // false if attribute does not exist 558 | ``` 559 | 560 | ```php 561 | use Josantonius\Session\Facades\Session; 562 | 563 | Session::pull('foo', false); // false if attribute does not exist 564 | ``` 565 | 566 | ### Deletes an attribute by name 567 | 568 | ```php 569 | use Josantonius\Session\Session; 570 | 571 | $session = new Session(); 572 | 573 | $session->remove('foo'); 574 | ``` 575 | 576 | ```php 577 | use Josantonius\Session\Facades\Session; 578 | 579 | Session::remove('foo'); 580 | ``` 581 | 582 | ### Free all session variables 583 | 584 | ```php 585 | use Josantonius\Session\Session; 586 | 587 | $session = new Session(); 588 | 589 | $session->clear(); 590 | ``` 591 | 592 | ```php 593 | use Josantonius\Session\Facades\Session; 594 | 595 | Session::clear(); 596 | ``` 597 | 598 | ### Gets the session ID 599 | 600 | ```php 601 | use Josantonius\Session\Session; 602 | 603 | $session = new Session(); 604 | 605 | $session->getId(); 606 | ``` 607 | 608 | ```php 609 | use Josantonius\Session\Facades\Session; 610 | 611 | Session::getId(); 612 | ``` 613 | 614 | ### Sets the session ID 615 | 616 | ```php 617 | use Josantonius\Session\Session; 618 | 619 | $session = new Session(); 620 | 621 | $session->setId('foo'); 622 | ``` 623 | 624 | ```php 625 | use Josantonius\Session\Facades\Session; 626 | 627 | Session::setId('foo'); 628 | ``` 629 | 630 | ### Update the current session ID with a newly generated one 631 | 632 | ```php 633 | use Josantonius\Session\Session; 634 | 635 | $session = new Session(); 636 | 637 | $session->regenerateId(); 638 | ``` 639 | 640 | ```php 641 | use Josantonius\Session\Facades\Session; 642 | 643 | Session::regenerateId(); 644 | ``` 645 | 646 | ### Update the current session ID with a newly generated one deleting the old session 647 | 648 | ```php 649 | use Josantonius\Session\Session; 650 | 651 | $session = new Session(); 652 | 653 | $session->regenerateId(true); 654 | ``` 655 | 656 | ```php 657 | use Josantonius\Session\Facades\Session; 658 | 659 | Session::regenerateId(true); 660 | ``` 661 | 662 | ### Gets the session name 663 | 664 | ```php 665 | use Josantonius\Session\Session; 666 | 667 | $session = new Session(); 668 | 669 | $session->getName(); 670 | ``` 671 | 672 | ```php 673 | use Josantonius\Session\Facades\Session; 674 | 675 | Session::getName(); 676 | ``` 677 | 678 | ### Sets the session name 679 | 680 | ```php 681 | use Josantonius\Session\Session; 682 | 683 | $session = new Session(); 684 | 685 | $session->setName('foo'); 686 | ``` 687 | 688 | ```php 689 | use Josantonius\Session\Facades\Session; 690 | 691 | Session::setName('foo'); 692 | ``` 693 | 694 | ### Destroys the session 695 | 696 | ```php 697 | use Josantonius\Session\Session; 698 | 699 | $session = new Session(); 700 | 701 | $session->destroy(); 702 | ``` 703 | 704 | ```php 705 | use Josantonius\Session\Facades\Session; 706 | 707 | Session::destroy(); 708 | ``` 709 | 710 | ## Tests 711 | 712 | To run [tests](tests) you just need [composer](http://getcomposer.org/download/) 713 | and to execute the following: 714 | 715 | ```console 716 | git clone https://github.com/josantonius/php-session.git 717 | ``` 718 | 719 | ```console 720 | cd php-session 721 | ``` 722 | 723 | ```console 724 | composer install 725 | ``` 726 | 727 | Run unit tests with [PHPUnit](https://phpunit.de/): 728 | 729 | ```console 730 | composer phpunit 731 | ``` 732 | 733 | Run code standard tests with [PHPCS](https://github.com/squizlabs/PHP_CodeSniffer): 734 | 735 | ```console 736 | composer phpcs 737 | ``` 738 | 739 | Run [PHP Mess Detector](https://phpmd.org/) tests to detect inconsistencies in code style: 740 | 741 | ```console 742 | composer phpmd 743 | ``` 744 | 745 | Run all previous tests: 746 | 747 | ```console 748 | composer tests 749 | ``` 750 | 751 | ## TODO 752 | 753 | - [ ] Add new feature 754 | - [ ] Improve tests 755 | - [ ] Improve documentation 756 | - [ ] Improve English translation in the README file 757 | - [ ] Refactor code for disabled code style rules (see phpmd.xml and phpcs.xml) 758 | - [ ] Show an example of renewing the session lifetime 759 | - [ ] Feature to enable/disable exceptions? 760 | - [ ] Feature to add prefixes in session attributes? 761 | 762 | ## Changelog 763 | 764 | Detailed changes for each release are documented in the 765 | [release notes](https://github.com/josantonius/php-session/releases). 766 | 767 | ## Contribution 768 | 769 | Please make sure to read the [Contributing Guide](.github/CONTRIBUTING.md), before making a pull 770 | request, start a discussion or report a issue. 771 | 772 | Thanks to all [contributors](https://github.com/josantonius/php-session/graphs/contributors)! :heart: 773 | 774 | ## Sponsor 775 | 776 | If this project helps you to reduce your development time, 777 | [you can sponsor me](https://github.com/josantonius#sponsor) to support my open source work :blush: 778 | 779 | ## License 780 | 781 | This repository is licensed under the [MIT License](LICENSE). 782 | 783 | Copyright © 2017-present, [Josantonius](https://github.com/josantonius#contact) 784 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "josantonius/session", 3 | "description": "PHP library for handling sessions.", 4 | "license": "MIT", 5 | "type": "library", 6 | "keywords": [ 7 | "session", 8 | "php" 9 | ], 10 | "authors": [ 11 | { 12 | "name": "Josantonius", 13 | "email": "hello@josantonius.dev", 14 | "homepage": "https://josantonius.dev", 15 | "role": "Developer" 16 | } 17 | ], 18 | "support": { 19 | "issues": "https://github.com/josantonius/php-session/issues", 20 | "source": "https://github.com/josantonius/php-session", 21 | "discussions": "https://github.com/josantonius/php-session/discussions" 22 | }, 23 | "require": { 24 | "php": "^8.0" 25 | }, 26 | "require-dev": { 27 | "phpmd/phpmd": "^2.12", 28 | "phpunit/phpunit": "^9.5", 29 | "squizlabs/php_codesniffer": "^3.7" 30 | }, 31 | "minimum-stability": "stable", 32 | "autoload": { 33 | "psr-4": { 34 | "Josantonius\\Session\\": "src/" 35 | } 36 | }, 37 | "autoload-dev": { 38 | "psr-4": { 39 | "Josantonius\\Session\\Tests\\": "tests/" 40 | } 41 | }, 42 | "config": { 43 | "preferred-install": "dist" 44 | }, 45 | "extra": { 46 | "branch-alias": { 47 | "dev-master": "1.0-dev" 48 | } 49 | }, 50 | "scripts": { 51 | "coverage": "vendor/bin/phpunit --coverage-clover=coverage.xml", 52 | "fix": [ 53 | "vendor/bin/phpcbf src tests" 54 | ], 55 | "htmlCoverage": "vendor/bin/phpunit --coverage-html coverage", 56 | "phpcs": "vendor/bin/phpcs --standard=phpcs.xml $(find . -name '*.php');", 57 | "phpmd": "vendor/bin/phpmd src,tests text ./phpmd.xml", 58 | "phpunit": "vendor/bin/phpunit", 59 | "tests": [ 60 | "clear", 61 | "@phpmd", 62 | "@phpcs", 63 | "@phpunit" 64 | ] 65 | } 66 | } -------------------------------------------------------------------------------- /src/Exceptions/HeadersSentException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Josantonius\Session\Exceptions; 13 | 14 | class HeadersSentException extends SessionException 15 | { 16 | public function __construct(string $file, int $line) 17 | { 18 | parent::__construct(sprintf( 19 | 'Session->start(): The headers have already been sent in "%s" at line %d.', 20 | $file, 21 | $line 22 | )); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Exceptions/SessionException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Josantonius\Session\Exceptions; 13 | 14 | /** 15 | * Session exception manager. 16 | * 17 | * @deprecated since version v2.0.6 18 | */ 19 | class SessionException extends \Exception 20 | { 21 | } 22 | -------------------------------------------------------------------------------- /src/Exceptions/SessionNotStartedException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Josantonius\Session\Exceptions; 13 | 14 | class SessionNotStartedException extends SessionException 15 | { 16 | public function __construct(string $methodName) 17 | { 18 | parent::__construct( 19 | 'Session->' . $methodName . '(): Changing $_SESSION when no started session.' 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Exceptions/SessionStartedException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Josantonius\Session\Exceptions; 13 | 14 | class SessionStartedException extends SessionException 15 | { 16 | public function __construct(string $methodName) 17 | { 18 | parent::__construct('Session->' . $methodName . '(): The session has already started.'); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Exceptions/WrongSessionOptionException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Josantonius\Session\Exceptions; 13 | 14 | class WrongSessionOptionException extends SessionException 15 | { 16 | public function __construct(string $name) 17 | { 18 | parent::__construct("Session->start(): Setting option '$name' failed."); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Facades/Session.php: -------------------------------------------------------------------------------- 1 | 9 | * 10 | * For the full copyright and license information, please view the LICENSE 11 | * file that was distributed with this source code. 12 | */ 13 | 14 | namespace Josantonius\Session\Facades; 15 | 16 | use Josantonius\Session\Session as SessionInstance; 17 | use Josantonius\Session\Exceptions\HeadersSentException; 18 | use Josantonius\Session\Exceptions\SessionStartedException; 19 | use Josantonius\Session\Exceptions\SessionNotStartedException; 20 | use Josantonius\Session\Exceptions\WrongSessionOptionException; 21 | 22 | /** 23 | * Session handler. 24 | */ 25 | class Session 26 | { 27 | private static ?SessionInstance $session; 28 | 29 | private static function getInstance() 30 | { 31 | return self::$session ?? new SessionInstance(); 32 | } 33 | 34 | /** 35 | * Starts the session. 36 | * 37 | * List of available $options with their default values: 38 | * 39 | * * cache_expire: "180" 40 | * * cache_limiter: "nocache" 41 | * * cookie_domain: "" 42 | * * cookie_httponly: "0" 43 | * * cookie_lifetime: "0" 44 | * * cookie_path: "/" 45 | * * cookie_samesite: "" 46 | * * cookie_secure: "0" 47 | * * gc_divisor: "100" 48 | * * gc_maxlifetime: "1440" 49 | * * gc_probability: "1" 50 | * * lazy_write: "1" 51 | * * name: "PHPSESSID" 52 | * * read_and_close: "0" 53 | * * referer_check: "" 54 | * * save_handler: "files" 55 | * * save_path: "" 56 | * * serialize_handler: "php" 57 | * * sid_bits_per_character: "4" 58 | * * sid_length: "32" 59 | * * trans_sid_hosts: $_SERVER['HTTP_HOST'] 60 | * * trans_sid_tags: "a=href,area=href,frame=src,form=" 61 | * * use_cookies: "1" 62 | * * use_only_cookies: "1" 63 | * * use_strict_mode: "0" 64 | * * use_trans_sid: "0" 65 | * 66 | * @see https://php.net/session.configuration 67 | * 68 | * @throws HeadersSentException if headers already sent. 69 | * @throws SessionStartedException if session already started. 70 | * @throws WrongSessionOptionException If setting options failed. 71 | */ 72 | public static function start(array $options = []): bool 73 | { 74 | return self::getInstance()->start($options); 75 | } 76 | 77 | /** 78 | * Gets all attributes. 79 | */ 80 | public static function all(): array 81 | { 82 | return self::getInstance()->all(); 83 | } 84 | 85 | /** 86 | * Checks if an attribute exists in the session. 87 | */ 88 | public static function has(string $name): bool 89 | { 90 | return self::getInstance()->has($name); 91 | } 92 | 93 | /** 94 | * Gets an attribute by name. 95 | * 96 | * Optionally defines a default value when the attribute does not exist. 97 | */ 98 | public static function get(string $name, mixed $default = null): mixed 99 | { 100 | return self::getInstance()->get($name, $default); 101 | } 102 | 103 | /** 104 | * Sets an attribute by name. 105 | * 106 | * @throws SessionNotStartedException if session was not started. 107 | */ 108 | public static function set(string $name, mixed $value): void 109 | { 110 | self::getInstance()->set($name, $value); 111 | } 112 | 113 | /** 114 | * Sets several attributes at once. 115 | * 116 | * If attributes exist they are replaced, if they do not exist they are created. 117 | * 118 | * @throws SessionNotStartedException if session was not started. 119 | */ 120 | public static function replace(array $data): void 121 | { 122 | self::getInstance()->replace($data); 123 | } 124 | 125 | /** 126 | * Deletes an attribute by name and returns its value. 127 | * 128 | * Optionally defines a default value when the attribute does not exist. 129 | * 130 | * @throws SessionNotStartedException if session was not started. 131 | */ 132 | public static function pull(string $name, mixed $default = null): mixed 133 | { 134 | return self::getInstance()->pull($name, $default); 135 | } 136 | 137 | /** 138 | * Deletes an attribute by name. 139 | * 140 | * @throws SessionNotStartedException if session was not started. 141 | */ 142 | public static function remove(string $name): void 143 | { 144 | self::getInstance()->remove($name); 145 | } 146 | 147 | /** 148 | * Free all session variables. 149 | * 150 | * @throws SessionNotStartedException if session was not started. 151 | */ 152 | public static function clear(): void 153 | { 154 | self::getInstance()->clear(); 155 | } 156 | 157 | /** 158 | * Gets the session ID. 159 | */ 160 | public static function getId(): string 161 | { 162 | return self::getInstance()->getId(); 163 | } 164 | 165 | /** 166 | * Sets the session ID. 167 | * 168 | * @throws SessionStartedException if session already started. 169 | */ 170 | public static function setId(string $sessionId): void 171 | { 172 | session_id($sessionId); 173 | } 174 | 175 | /** 176 | * Updates the current session id with a newly generated one. 177 | * 178 | * @throws SessionNotStartedException if session was not started. 179 | */ 180 | public static function regenerateId(bool $deleteOldSession = false): bool 181 | { 182 | return self::getInstance()->regenerateId($deleteOldSession); 183 | } 184 | 185 | /** 186 | * Gets the session name. 187 | */ 188 | public static function getName(): string 189 | { 190 | return self::getInstance()->getName(); 191 | } 192 | 193 | /** 194 | * Sets the session name. 195 | * 196 | * @throws SessionStartedException if session already started. 197 | */ 198 | public static function setName(string $name): void 199 | { 200 | self::getInstance()->setName($name); 201 | } 202 | 203 | /** 204 | * Destroys the session. 205 | * 206 | * @throws SessionNotStartedException if session was not started. 207 | */ 208 | public static function destroy(): bool 209 | { 210 | return self::getInstance()->destroy(); 211 | } 212 | 213 | /** 214 | * Checks if the session is started. 215 | */ 216 | public static function isStarted(): bool 217 | { 218 | return self::getInstance()->isStarted(); 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /src/Session.php: -------------------------------------------------------------------------------- 1 | 9 | * 10 | * For the full copyright and license information, please view the LICENSE 11 | * file that was distributed with this source code. 12 | */ 13 | 14 | namespace Josantonius\Session; 15 | 16 | use Josantonius\Session\Exceptions\HeadersSentException; 17 | use Josantonius\Session\Exceptions\SessionStartedException; 18 | use Josantonius\Session\Exceptions\SessionNotStartedException; 19 | use Josantonius\Session\Exceptions\WrongSessionOptionException; 20 | 21 | /** 22 | * Session handler. 23 | */ 24 | class Session 25 | { 26 | /** 27 | * Starts the session. 28 | * 29 | * List of available $options with their default values: 30 | * 31 | * * cache_expire: "180" 32 | * * cache_limiter: "nocache" 33 | * * cookie_domain: "" 34 | * * cookie_httponly: "0" 35 | * * cookie_lifetime: "0" 36 | * * cookie_path: "/" 37 | * * cookie_samesite: "" 38 | * * cookie_secure: "0" 39 | * * gc_divisor: "100" 40 | * * gc_maxlifetime: "1440" 41 | * * gc_probability: "1" 42 | * * lazy_write: "1" 43 | * * name: "PHPSESSID" 44 | * * read_and_close: "0" 45 | * * referer_check: "" 46 | * * save_handler: "files" 47 | * * save_path: "" 48 | * * serialize_handler: "php" 49 | * * sid_bits_per_character: "4" 50 | * * sid_length: "32" 51 | * * trans_sid_hosts: $_SERVER['HTTP_HOST'] 52 | * * trans_sid_tags: "a=href,area=href,frame=src,form=" 53 | * * use_cookies: "1" 54 | * * use_only_cookies: "1" 55 | * * use_strict_mode: "0" 56 | * * use_trans_sid: "0" 57 | * 58 | * @see https://php.net/session.configuration 59 | * 60 | * @throws HeadersSentException if headers already sent. 61 | * @throws SessionStartedException if session already started. 62 | * @throws WrongSessionOptionException If setting options failed. 63 | */ 64 | public function start(array $options = []): bool 65 | { 66 | $this->throwExceptionIfHeadersWereSent(); 67 | $this->throwExceptionIfSessionWasStarted(); 68 | $this->throwExceptionIfHasWrongOptions($options); 69 | 70 | return session_start($options); 71 | } 72 | 73 | /** 74 | * Gets all attributes. 75 | */ 76 | public function all(): array 77 | { 78 | return $_SESSION ?? []; 79 | } 80 | 81 | /** 82 | * Checks if an attribute exists in the session. 83 | */ 84 | public function has(string $name): bool 85 | { 86 | return isset($_SESSION[$name]); 87 | } 88 | 89 | /** 90 | * Gets an attribute by name. 91 | * 92 | * Optionally defines a default value when the attribute does not exist. 93 | */ 94 | public function get(string $name, mixed $default = null): mixed 95 | { 96 | return $_SESSION[$name] ?? $default; 97 | } 98 | 99 | /** 100 | * Sets an attribute by name. 101 | * 102 | * @throws SessionNotStartedException if session was not started. 103 | */ 104 | public function set(string $name, mixed $value): void 105 | { 106 | $this->throwExceptionIfSessionWasNotStarted(); 107 | 108 | $_SESSION[$name] = $value; 109 | } 110 | 111 | /** 112 | * Sets several attributes at once. 113 | * 114 | * If attributes exist they are replaced, if they do not exist they are created. 115 | * 116 | * @throws SessionNotStartedException if session was not started. 117 | */ 118 | public function replace(array $data): void 119 | { 120 | $this->throwExceptionIfSessionWasNotStarted(); 121 | 122 | $_SESSION = array_merge($_SESSION, $data); 123 | } 124 | 125 | /** 126 | * Deletes an attribute by name and returns its value. 127 | * 128 | * Optionally defines a default value when the attribute does not exist. 129 | * 130 | * @throws SessionNotStartedException if session was not started. 131 | */ 132 | public function pull(string $name, mixed $default = null): mixed 133 | { 134 | $this->throwExceptionIfSessionWasNotStarted(); 135 | 136 | $value = $_SESSION[$name] ?? $default; 137 | 138 | unset($_SESSION[$name]); 139 | 140 | return $value; 141 | } 142 | 143 | /** 144 | * Deletes an attribute by name. 145 | * 146 | * @throws SessionNotStartedException if session was not started. 147 | */ 148 | public function remove(string $name): void 149 | { 150 | $this->throwExceptionIfSessionWasNotStarted(); 151 | 152 | unset($_SESSION[$name]); 153 | } 154 | 155 | /** 156 | * Free all session variables. 157 | * 158 | * @throws SessionNotStartedException if session was not started. 159 | */ 160 | public function clear(): void 161 | { 162 | $this->throwExceptionIfSessionWasNotStarted(); 163 | 164 | session_unset(); 165 | } 166 | 167 | /** 168 | * Gets the session ID. 169 | */ 170 | public function getId(): string 171 | { 172 | return session_id(); 173 | } 174 | 175 | /** 176 | * Sets the session ID. 177 | * 178 | * @throws SessionStartedException if session already started. 179 | */ 180 | public function setId(string $sessionId): void 181 | { 182 | $this->throwExceptionIfSessionWasStarted(); 183 | 184 | session_id($sessionId); 185 | } 186 | 187 | /** 188 | * Updates the current session id with a newly generated one. 189 | * 190 | * @throws SessionNotStartedException if session was not started. 191 | */ 192 | public function regenerateId(bool $deleteOldSession = false): bool 193 | { 194 | $this->throwExceptionIfSessionWasNotStarted(); 195 | 196 | return session_regenerate_id($deleteOldSession); 197 | } 198 | 199 | /** 200 | * Gets the session name. 201 | */ 202 | public function getName(): string 203 | { 204 | $name = session_name(); 205 | 206 | return $name ? $name : ''; 207 | } 208 | 209 | /** 210 | * Sets the session name. 211 | * 212 | * @throws SessionStartedException if session already started. 213 | */ 214 | public function setName(string $name): void 215 | { 216 | $this->throwExceptionIfSessionWasStarted(); 217 | 218 | session_name($name); 219 | } 220 | 221 | /** 222 | * Destroys the session. 223 | * 224 | * @throws SessionNotStartedException if session was not started. 225 | */ 226 | public function destroy(): bool 227 | { 228 | $this->throwExceptionIfSessionWasNotStarted(); 229 | 230 | return session_destroy(); 231 | } 232 | 233 | /** 234 | * Checks if the session is started. 235 | */ 236 | public function isStarted(): bool 237 | { 238 | return session_status() === PHP_SESSION_ACTIVE; 239 | } 240 | 241 | /** 242 | * Throw exception if the session have wrong options. 243 | * 244 | * @throws WrongSessionOptionException If setting options failed. 245 | */ 246 | private function throwExceptionIfHasWrongOptions(array $options): void 247 | { 248 | $validOptions = array_flip([ 249 | 'cache_expire', 'cache_limiter', 'cookie_domain', 'cookie_httponly', 250 | 'cookie_lifetime', 'cookie_path', 'cookie_samesite', 'cookie_secure', 251 | 'gc_divisor', 'gc_maxlifetime', 'gc_probability', 'lazy_write', 252 | 'name', 'read_and_close', 'referer_check', 'save_handler', 253 | 'save_path', 'serialize_handler', 'sid_bits_per_character', 'sid_length', 254 | 'trans_sid_hosts', 'trans_sid_tags', 'use_cookies', 'use_only_cookies', 255 | 'use_strict_mode', 'use_trans_sid', 256 | ]); 257 | 258 | foreach (array_keys($options) as $key) { 259 | if (!isset($validOptions[$key])) { 260 | throw new WrongSessionOptionException($key); 261 | } 262 | } 263 | } 264 | 265 | /** 266 | * Throw exception if headers have already been sent. 267 | * 268 | * @throws HeadersSentException if headers already sent. 269 | */ 270 | private function throwExceptionIfHeadersWereSent(): void 271 | { 272 | $headersWereSent = (bool) ini_get('session.use_cookies') && headers_sent($file, $line); 273 | 274 | $headersWereSent && throw new HeadersSentException($file, $line); 275 | } 276 | 277 | /** 278 | * Throw exception if the session has already been started. 279 | * 280 | * @throws SessionStartedException if session already started. 281 | */ 282 | private function throwExceptionIfSessionWasStarted(): void 283 | { 284 | $methodName = debug_backtrace()[1]['function'] ?? 'unknown'; 285 | 286 | $this->isStarted() && throw new SessionStartedException($methodName); 287 | } 288 | 289 | /** 290 | * Throw exception if the session was not started. 291 | * 292 | * @throws SessionNotStartedException if session was not started. 293 | */ 294 | private function throwExceptionIfSessionWasNotStarted(): void 295 | { 296 | $methodName = debug_backtrace()[1]['function'] ?? 'unknown'; 297 | 298 | !$this->isStarted() && throw new SessionNotStartedException($methodName); 299 | } 300 | } 301 | --------------------------------------------------------------------------------