├── LICENSE ├── README.md ├── composer.json └── src └── Url.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 URL library 2 | 3 | [![Latest Stable Version](https://poser.pugx.org/josantonius/url/v/stable)](https://packagist.org/packages/josantonius/url) 4 | [![License](https://poser.pugx.org/josantonius/url/license)](LICENSE) 5 | [![Total Downloads](https://poser.pugx.org/josantonius/url/downloads)](https://packagist.org/packages/josantonius/url) 6 | [![CI](https://github.com/josantonius/php-url/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/josantonius/php-url/actions/workflows/ci.yml) 7 | [![CodeCov](https://codecov.io/gh/josantonius/php-url/branch/main/graph/badge.svg)](https://codecov.io/gh/josantonius/php-url) 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 to access URL information. 15 | 16 | Provides an improved replacement for the access to the components of a URL offered by PHP's 17 | `parse_url` and `pathinfo` functions. 18 | 19 | This library does not format the provided URL, it only makes it easier to access the components. 20 | For something more advanced you can use something like `league/uri-components`. 21 | 22 | --- 23 | 24 | - [Requirements](#requirements) 25 | - [Installation](#installation) 26 | - [Available Classes](#available-classes) 27 | - [Url Class](#url-class) 28 | - [Usage](#usage) 29 | - [Tests](#tests) 30 | - [TODO](#todo) 31 | - [Changelog](#changelog) 32 | - [Contribution](#contribution) 33 | - [Sponsor](#sponsor) 34 | - [License](#license) 35 | 36 | --- 37 | 38 | ## Requirements 39 | 40 | - Operating System: Linux | Windows. 41 | 42 | - PHP versions: 8.1 | 8.2. 43 | 44 | ## Installation 45 | 46 | The preferred way to install this extension is through [Composer](http://getcomposer.org/download/). 47 | 48 | To install **PHP URL library**, simply: 49 | 50 | ```console 51 | composer require josantonius/url 52 | ``` 53 | 54 | The previous command will only install the necessary files, 55 | if you prefer to **download the entire source code** you can use: 56 | 57 | ```console 58 | composer require josantonius/url --prefer-source 59 | ``` 60 | 61 | You can also **clone the complete repository** with Git: 62 | 63 | ```console 64 | git clone https://github.com/josantonius/php-url.git 65 | ``` 66 | 67 | ## Available Classes 68 | 69 | ### Url Class 70 | 71 | `Josantonius\Url\Url` 72 | 73 | Create a new instance: 74 | 75 | ```php 76 | /** 77 | * If no URL is provided, the URL of the current page will be generated. 78 | * 79 | * The generated URL will exclude ports 80 and 443 and include the rest. 80 | */ 81 | public function __construct(null|string $url = null); 82 | ``` 83 | 84 | Gets authority: 85 | 86 | ```php 87 | /** 88 | * The authority, in "[user-info@][host][:port]" format. 89 | * 90 | * @var string URL authority or empty string. 91 | */ 92 | public readonly string $authority; 93 | ``` 94 | 95 | Gets the base URL: 96 | 97 | ```php 98 | /** 99 | * The base URL, in "[scheme:][//domain][:port]" format. 100 | * 101 | * @var string Base URL or empty string. 102 | */ 103 | public readonly string $base; 104 | ``` 105 | 106 | Gets the path basename: 107 | 108 | ```php 109 | /** 110 | * The path basename, in "[filename][.extension]" format. 111 | * 112 | * @var string URL path basename or empty string. 113 | */ 114 | public readonly string $basename; 115 | ``` 116 | 117 | Gets the path dirname: 118 | 119 | ```php 120 | /** 121 | * The path dirname, in "[dirname]" format. 122 | * 123 | * @var string URL path dirname or empty string. 124 | */ 125 | public readonly string $dirname; 126 | ``` 127 | 128 | Gets the path basename extension: 129 | 130 | ```php 131 | /** 132 | * The path basename extension, in "[extension]" format. 133 | * 134 | * @var string URL path basename extension or empty string. 135 | */ 136 | public readonly string $extension; 137 | ``` 138 | 139 | Gets the path filename: 140 | 141 | ```php 142 | /** 143 | * The path filename, in "[filename]" format. 144 | * 145 | * @var string URL path filename or empty string. 146 | */ 147 | public readonly string $filename; 148 | ``` 149 | 150 | Gets fragment: 151 | 152 | ```php 153 | /** 154 | * URL fragment in "[fragment]" format. 155 | * 156 | * @var string URL fragment or empty string. 157 | */ 158 | public readonly string $fragment; 159 | ``` 160 | 161 | Gets the full URL: 162 | 163 | ```php 164 | public readonly string $full; 165 | ``` 166 | 167 | Gets hashed fragment: 168 | 169 | ```php 170 | /** 171 | * URL hashed fragment in "[#fragment]" format. 172 | * 173 | * @var string URL hashed fragment or empty string. 174 | */ 175 | public readonly string $hash; 176 | ``` 177 | 178 | Gets host: 179 | 180 | ```php 181 | /** 182 | * URL host in "[subdomain.][domain][.tld]" format. 183 | * 184 | * @var string URL host or empty string. 185 | */ 186 | public readonly string $host; 187 | ``` 188 | 189 | Gets path: 190 | 191 | ```php 192 | /** 193 | * URL path in "[path]" format. 194 | * 195 | * @var string URL path or empty string. 196 | */ 197 | public readonly string $path; 198 | ``` 199 | 200 | Gets the query parameters: 201 | 202 | ```php 203 | /** 204 | * URL query parameters in array format. 205 | * 206 | * @var array URL query parameters or empty string. 207 | */ 208 | public readonly array $parameters; 209 | ``` 210 | 211 | Gets password: 212 | 213 | ```php 214 | /** 215 | * URL password in "[password]" format. 216 | * 217 | * @var string URL password or empty string. 218 | */ 219 | public readonly string $password; 220 | ``` 221 | 222 | Gets port: 223 | 224 | ```php 225 | /** 226 | * URL port in "[port]" format. 227 | * 228 | * @var string URL port or empty string. 229 | */ 230 | public readonly int|string $port; 231 | ``` 232 | 233 | Gets scheme: 234 | 235 | ```php 236 | /** 237 | * URL scheme in "[scheme]" format. 238 | * 239 | * @var string URL scheme or empty string. 240 | */ 241 | public readonly string $scheme; 242 | ``` 243 | 244 | Gets path segments: 245 | 246 | ```php 247 | /** 248 | * URL path segments in array format. 249 | * 250 | * @var string[] URL path segments or empty string. 251 | */ 252 | public readonly array $segments; 253 | ``` 254 | 255 | Gets query: 256 | 257 | ```php 258 | /** 259 | * URL query in "[query]" format. 260 | * 261 | * @var string URL query or empty string. 262 | */ 263 | public readonly string $query; 264 | ``` 265 | 266 | Gets username: 267 | 268 | ```php 269 | /** 270 | * URL username in "[username]" format. 271 | * 272 | * @var string URL username or empty string. 273 | */ 274 | public readonly string $username; 275 | ``` 276 | 277 | ## Usage 278 | 279 | Example of use for this library: 280 | 281 | ### Create a new instance using the current URL 282 | 283 | ```php 284 | use Josantonius\Url\Url; 285 | 286 | $url = new Url(); 287 | ``` 288 | 289 | ### Create a new instance using custom URL 290 | 291 | ```php 292 | use Josantonius\Url\Url; 293 | 294 | $url = new Url('https://domain.com'); 295 | ``` 296 | 297 | ### Gets authority 298 | 299 | ```php 300 | use Josantonius\Url\Url; 301 | 302 | $url = new Url(); // https://domain.com 303 | 304 | $url->authority; // "domain.com" 305 | 306 | 307 | $url = new Url('https://user:pass@sub.domain.com:90/en/'); 308 | 309 | $url->authority; // "user:pass@sub.domain.com:90" 310 | 311 | 312 | $url = new Url('https://user:pass@sub.domain.com/en/'); 313 | 314 | $url->authority; // "user:pass@sub.domain.com" 315 | 316 | 317 | $url = new Url('https://sub.domain.com/en/'); 318 | 319 | $url->authority; // "sub.domain.com" 320 | ``` 321 | 322 | ### Gets base URL 323 | 324 | ```php 325 | use Josantonius\Url\Url; 326 | 327 | $url = new Url(); // https://user:pass@domain.com:80/en/ 328 | 329 | $url->base; // "https://domain.com" 330 | 331 | 332 | $url = new Url('https://domain.com:80/?tag=bug'); 333 | 334 | $url->base; // "https://domain.com:80" 335 | 336 | 337 | $url = new Url('https://domain.com/en/'); 338 | 339 | $url->base; // "https://domain.com" 340 | ``` 341 | 342 | ### Gets the path basename 343 | 344 | ```php 345 | use Josantonius\Url\Url; 346 | 347 | $url = new Url(); // https://domain.com/search.php 348 | 349 | $url->basename; // "search.php" 350 | 351 | 352 | $url = new Url('https://domain.com/en/web/docs/search.php?tag=bug'); 353 | 354 | $url->basename; // "search.php" 355 | 356 | 357 | $url = new Url('https://domain.com/en/web/docs?tag=bug'); 358 | 359 | $url->basename; // "docs" 360 | ``` 361 | 362 | ### Gets the path dirname 363 | 364 | ```php 365 | use Josantonius\Url\Url; 366 | 367 | $url = new Url(); // https://domain.com/search.php 368 | 369 | $url->dirname; // "/" 370 | 371 | 372 | $url = new Url('https://domain.com/en/web/docs/search.php?tag=bug'); 373 | 374 | $url->dirname; // "/en/web/docs" 375 | 376 | 377 | $url = new Url('https://domain.com/en/web/docs?tag=bug'); 378 | 379 | $url->dirname; // "/en/web" 380 | ``` 381 | 382 | ### Gets the path basename extension 383 | 384 | ```php 385 | use Josantonius\Url\Url; 386 | 387 | $url = new Url(); // https://domain.com/search.php 388 | 389 | $url->extension; // "php" 390 | 391 | 392 | $url = new Url('https://domain.com/en/web/docs/search.php?tag=bug'); 393 | 394 | $url->extension; // "php" 395 | 396 | 397 | $url = new Url('https://domain.com/en/web/docs?tag=bug'); 398 | 399 | $url->extension; // "" 400 | ``` 401 | 402 | ### Gets the path filename 403 | 404 | ```php 405 | use Josantonius\Url\Url; 406 | 407 | $url = new Url(); // https://domain.com/search.php 408 | 409 | $url->filename; // "search" 410 | 411 | 412 | $url = new Url('https://domain.com/en/web/docs/search.php?tag=bug'); 413 | 414 | $url->filename; // "search" 415 | 416 | 417 | $url = new Url('https://domain.com/docs?tag=bug'); 418 | 419 | $url->filename; // "docs" 420 | ``` 421 | 422 | ### Gets fragment 423 | 424 | ```php 425 | use Josantonius\Url\Url; 426 | 427 | $url = new Url(); // https://domain.com#top 428 | 429 | $url->fragment; // "top" 430 | 431 | 432 | $url = new Url('https://domain.com/en/web/docs#top'); 433 | 434 | $url->fragment; // "top" 435 | 436 | 437 | $url = new Url('https://domain.com'); 438 | 439 | $url->fragment; // "" 440 | ``` 441 | 442 | ### Gets the full URL 443 | 444 | ```php 445 | use Josantonius\Url\Url; 446 | 447 | $url = new Url(); // https://domain.com:80 448 | 449 | $url->full; // "https://domain.com" 450 | 451 | 452 | $url = new Url('https://user:pass@sub.domain.com:90/en/'); 453 | 454 | $url->full; // "https://user:pass@sub.domain.com:90/en/" 455 | ``` 456 | 457 | ### Gets hashed fragment 458 | 459 | ```php 460 | use Josantonius\Url\Url; 461 | 462 | $url = new Url(); // https://domain.com#top 463 | 464 | $url->hash; // "#top" 465 | 466 | 467 | $url = new Url('https://domain.com/en/web/docs#top'); 468 | 469 | $url->hash; // "#top" 470 | 471 | 472 | $url = new Url('https://domain.com'); 473 | 474 | $url->hash; // "" 475 | ``` 476 | 477 | ### Gets host 478 | 479 | ```php 480 | use Josantonius\Url\Url; 481 | 482 | $url = new Url(); // https://sub.domain.com 483 | 484 | $url->host; // "sub.domain.com" 485 | 486 | 487 | $url = new Url('https://sub.domain.com/en/web/docs#top'); 488 | 489 | $url->host; // "sub.domain.com" 490 | 491 | 492 | $url = new Url('https://domain.com'); 493 | 494 | $url->host; // "domain.com" 495 | 496 | 497 | $url = new Url('https://localhost'); 498 | 499 | $url->host; // "localhost" 500 | ``` 501 | 502 | ### Gets path 503 | 504 | ```php 505 | use Josantonius\Url\Url; 506 | 507 | $url = new Url(); // https://domain.com/en 508 | 509 | $url->path; // "/en/web/docs/search.php" 510 | 511 | 512 | $url = new Url('https://domain.com/en/web/docs/search.php'); 513 | 514 | $url->path; // "/en/web/docs/search.php" 515 | 516 | 517 | $url = new Url('https://domain.com/en/web/docs/'); 518 | 519 | $url->path; // "/en/web/docs/" 520 | 521 | 522 | $url = new Url('https://domain.com/en?tag=bug'); 523 | 524 | $url->path; // "/en" 525 | 526 | 527 | $url = new Url('https://domain.com?tag=bug'); 528 | 529 | $url->path; // "" 530 | ``` 531 | 532 | ### Gets the query parameters 533 | 534 | ```php 535 | use Josantonius\Url\Url; 536 | 537 | $url = new Url(); // https://domain.com/en?tag=bug&order=asc#top 538 | 539 | $url->parameters; // ["tag" => "bug", "order" => "asc"] 540 | 541 | 542 | $url = new Url('https://domain.com/en/web/docs/search.php'); 543 | 544 | $url->parameters; // "" 545 | ``` 546 | 547 | ### Gets password 548 | 549 | ```php 550 | use Josantonius\Url\Url; 551 | 552 | $url = new Url(); // https://:pass@domain.com 553 | 554 | $url->password; // "pass" 555 | 556 | 557 | $url = new Url('https://user:pass@domain.com'); 558 | 559 | $url->password; // "pass" 560 | 561 | 562 | $url = new Url('https://user@domain.com'); 563 | 564 | $url->password; // "" 565 | ``` 566 | 567 | ### Gets port 568 | 569 | ```php 570 | use Josantonius\Url\Url; 571 | 572 | $url = new Url(); // https://domain.com:90 573 | 574 | $url->port; // 90 575 | 576 | 577 | $url = new Url(); // https://domain.com:80 578 | 579 | $url->port; // "" 580 | 581 | 582 | $url = new Url(); // https://domain.com:443 583 | 584 | $url->port; // "" 585 | 586 | 587 | $url = new Url('https://domain.com:80/en/'); 588 | 589 | $url->port; // 80 590 | 591 | 592 | $url = new Url('https://domain.com:443/en/'); 593 | 594 | $url->port; // 443 595 | 596 | 597 | $url = new Url('https://domain.com/en/'); 598 | 599 | $url->port; // "" 600 | ``` 601 | 602 | ### Gets scheme 603 | 604 | ```php 605 | use Josantonius\Url\Url; 606 | 607 | $url = new Url(); // http://domain.com 608 | 609 | $url->scheme; // "http" 610 | 611 | 612 | $url = new Url('https://domain.com'); 613 | 614 | $url->scheme; // "https" 615 | ``` 616 | 617 | ### Gets path segments 618 | 619 | ```php 620 | use Josantonius\Url\Url; 621 | 622 | $url = new Url(); // https://domain.com?tag=bug 623 | 624 | $url->segments; // [] 625 | 626 | 627 | $url = new Url('https://domain.com/en/web/docs/search.php'); 628 | 629 | $url->segments; // ['en', 'web', 'docs', 'search.php'] 630 | ``` 631 | 632 | ### Gets query 633 | 634 | ```php 635 | use Josantonius\Url\Url; 636 | 637 | $url = new Url(); // https://domain.com?tag=bug 638 | 639 | $url->query; // "tag=bug" 640 | 641 | 642 | $url = new Url('https://domain.com?tag=bug&order=asc#top'); 643 | 644 | $url->query; // "tag=bug&order=asc" 645 | 646 | $url = new Url('https://domain.com'); 647 | 648 | $url->query; // "" 649 | ``` 650 | 651 | ### Gets username 652 | 653 | ```php 654 | use Josantonius\Url\Url; 655 | 656 | $url = new Url(); // https://user@domain.com 657 | 658 | $url->username; // "user" 659 | 660 | 661 | $url = new Url('https://:pass@domain.com'); 662 | 663 | $url->username; // "" 664 | 665 | 666 | $url = new Url('https://user:pass@domain.com'); 667 | 668 | $url->username; // "user" 669 | 670 | 671 | $url = new Url('https://domain.com'); 672 | 673 | $url->username; // "" 674 | ``` 675 | 676 | ## Tests 677 | 678 | To run [tests](tests) you just need [composer](http://getcomposer.org/download/) 679 | and to execute the following: 680 | 681 | ```console 682 | git clone https://github.com/josantonius/php-url.git 683 | ``` 684 | 685 | ```console 686 | cd php-url 687 | ``` 688 | 689 | ```console 690 | composer install 691 | ``` 692 | 693 | Run unit tests with [PHPUnit](https://phpunit.de/): 694 | 695 | ```console 696 | composer phpunit 697 | ``` 698 | 699 | Run code standard tests with [PHPCS](https://github.com/squizlabs/PHP_CodeSniffer): 700 | 701 | ```console 702 | composer phpcs 703 | ``` 704 | 705 | Run [PHP Mess Detector](https://phpmd.org/) tests to detect inconsistencies in code style: 706 | 707 | ```console 708 | composer phpmd 709 | ``` 710 | 711 | Run all previous tests: 712 | 713 | ```console 714 | composer tests 715 | ``` 716 | 717 | ## TODO 718 | 719 | - [ ] Add new feature 720 | - [ ] Improve tests 721 | - [ ] Improve documentation 722 | - [ ] Improve English translation in the README file 723 | - [ ] Refactor code for disabled code style rules (see phpmd.xml and phpcs.xml) 724 | 725 | ## Changelog 726 | 727 | Detailed changes for each release are documented in the 728 | [release notes](https://github.com/josantonius/php-url/releases). 729 | 730 | ## Contribution 731 | 732 | Please make sure to read the [Contributing Guide](.github/CONTRIBUTING.md), before making a pull 733 | request, start a discussion or report a issue. 734 | 735 | Thanks to all [contributors](https://github.com/josantonius/php-url/graphs/contributors)! :heart: 736 | 737 | ## Sponsor 738 | 739 | If this project helps you to reduce your development time, 740 | [you can sponsor me](https://github.com/josantonius#sponsor) to support my open source work :blush: 741 | 742 | ## License 743 | 744 | This repository is licensed under the [MIT License](LICENSE). 745 | 746 | Copyright © 2017-present, [Josantonius](https://github.com/josantonius#contact) 747 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "josantonius/url", 3 | "description": "PHP library to access URL information.", 4 | "license": "MIT", 5 | "type": "library", 6 | "keywords": [ 7 | "http", 8 | "https", 9 | "path", 10 | "php", 11 | "uri", 12 | "url", 13 | "parse" 14 | ], 15 | "authors": [ 16 | { 17 | "name": "Josantonius", 18 | "email": "hello@josantonius.dev", 19 | "homepage": "https://josantonius.dev", 20 | "role": "Developer" 21 | } 22 | ], 23 | "support": { 24 | "issues": "https://github.com/josantonius/php-url/issues", 25 | "source": "https://github.com/josantonius/php-url", 26 | "discussions": "https://github.com/josantonius/php-url/discussions" 27 | }, 28 | "require": { 29 | "php": "^8.1" 30 | }, 31 | "require-dev": { 32 | "phpmd/phpmd": "^2.6", 33 | "phpunit/phpunit": "^9.5", 34 | "squizlabs/php_codesniffer": "^3.7" 35 | }, 36 | "minimum-stability": "stable", 37 | "autoload": { 38 | "psr-4": { 39 | "Josantonius\\Url\\": "src/" 40 | } 41 | }, 42 | "autoload-dev": { 43 | "psr-4": { 44 | "Josantonius\\Url\\Tests\\": "tests/" 45 | } 46 | }, 47 | "config": { 48 | "preferred-install": "dist" 49 | }, 50 | "extra": { 51 | "branch-alias": { 52 | "dev-master": "1.0-dev" 53 | } 54 | }, 55 | "scripts": { 56 | "coverage": "vendor/bin/phpunit --coverage-clover=coverage.xml", 57 | "fix": [ 58 | "vendor/bin/phpcbf src tests" 59 | ], 60 | "htmlCoverage": "vendor/bin/phpunit --coverage-html coverage", 61 | "phpcs": "vendor/bin/phpcs --standard=phpcs.xml $(find . -name '*.php');", 62 | "phpmd": "vendor/bin/phpmd src,tests text ./phpmd.xml", 63 | "phpunit": "vendor/bin/phpunit", 64 | "tests": [ 65 | "clear", 66 | "@phpmd", 67 | "@phpcs", 68 | "@phpunit" 69 | ] 70 | } 71 | } -------------------------------------------------------------------------------- /src/Url.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\Url; 15 | 16 | /** 17 | * Access URL components. 18 | */ 19 | class Url 20 | { 21 | /** 22 | * The authority of the URL, in "[user-info@][host][:port]" format. 23 | * 24 | * @var string URL authority or empty string. 25 | */ 26 | public readonly string $authority; 27 | 28 | /** 29 | * The base URL, in "[scheme:][//domain][:port]" format. 30 | * 31 | * @var string Base URL or empty string. 32 | */ 33 | public readonly string $base; 34 | 35 | /** 36 | * The path basename of the URL, in "[filename][.extension]" format. 37 | * 38 | * @var string URL path basename or empty string. 39 | */ 40 | public readonly string $basename; 41 | 42 | /** 43 | * The path dirname of the URL, in "[dirname]" format. 44 | * 45 | * @var string URL path dirname or empty string. 46 | */ 47 | public readonly string $dirname; 48 | 49 | /** 50 | * The path basename extension of the URL, in "[extension]" format. 51 | * 52 | * @var string URL path basename extension or empty string. 53 | */ 54 | public readonly string $extension; 55 | 56 | /** 57 | * The path filename of the URL, in "[filename]" format. 58 | * 59 | * @var string URL path filename or empty string. 60 | */ 61 | public readonly string $filename; 62 | 63 | /** 64 | * The fragment of the URL, in "[fragment]" format. 65 | * 66 | * @var string URL fragment or empty string. 67 | */ 68 | public readonly string $fragment; 69 | 70 | /** 71 | * The full URL. 72 | */ 73 | public readonly string $full; 74 | 75 | /** 76 | * The hashed fragment of the URL, in "[#fragment]" format. 77 | * 78 | * @var string URL hashed fragment or empty string. 79 | */ 80 | public readonly string $hash; 81 | 82 | /** 83 | * The host of the URL, in "[subdomain.][domain][.tld]" format. 84 | * 85 | * @var string URL host or empty string. 86 | */ 87 | public readonly string $host; 88 | 89 | /** 90 | * The path of the URL, in "[path]" format. 91 | * 92 | * @var string URL path or empty string. 93 | */ 94 | public readonly string $path; 95 | 96 | /** 97 | * The query parameters of the URL, in array format. 98 | * 99 | * @var array URL query or empty string. 100 | */ 101 | public readonly array $parameters; 102 | 103 | /** 104 | * The password of the URL, in "[password]" format. 105 | * 106 | * @var string URL password or empty string. 107 | */ 108 | public readonly string $password; 109 | 110 | /** 111 | * The port of the URL, in "[port]" format. 112 | * 113 | * @var string URL port or empty string. 114 | */ 115 | public readonly int|string $port; 116 | 117 | /** 118 | * The scheme of the URL, in "[scheme]" format. 119 | * 120 | * @var string URL scheme or empty string. 121 | */ 122 | public readonly string $scheme; 123 | 124 | /** 125 | * The path segments of the URL, in array format. 126 | * 127 | * @var string[] URL path segments or empty array. 128 | */ 129 | public readonly array $segments; 130 | 131 | /** 132 | * The query of the URL, in "[query]" format. 133 | * 134 | * @var string URL query or empty string. 135 | */ 136 | public readonly string $query; 137 | 138 | /** 139 | * The user name of the URL, in "[username]" format. 140 | * 141 | * @var string URL username or empty string. 142 | */ 143 | public readonly string $username; 144 | 145 | /** 146 | * Result of parse URL. 147 | */ 148 | private array|bool $components; 149 | 150 | /** 151 | * Creates new instance. 152 | * 153 | * If no URL is provided, the URL of the current page will be generated. 154 | * The generated URL will not include ports 80 and 443 in it. 155 | */ 156 | public function __construct(?string $url = null) 157 | { 158 | $this->full = $url ?? $this->getCurrentUrl(); 159 | 160 | $components = parse_url($this->full) ?: []; 161 | 162 | $this->components = [...$components, ...pathinfo($components['path'] ?? '')]; 163 | 164 | $this->setAttributes(); 165 | 166 | unset($this->components); 167 | } 168 | 169 | /** 170 | * Sets URL scheme. 171 | */ 172 | private function getCurrentUrl(): string 173 | { 174 | $path = $_SERVER['REQUEST_URL'] ?? ''; 175 | $port = $_SERVER['SERVER_PORT'] ?? ''; 176 | $host = $_SERVER['SERVER_NAME'] ?? ''; 177 | $https = $_SERVER['HTTPS'] ?? ''; 178 | 179 | $scheme = $https === 'on' ? 'https:' : 'http:'; 180 | 181 | $port = in_array($port, ['80', '443']) ? '' : ':' . $port; 182 | 183 | return strtolower($scheme . ($host ? '//' . $host : '')) . $port . $path; 184 | } 185 | 186 | private function setAttributes(): void 187 | { 188 | $this->setFragment(); 189 | $this->setHost(); 190 | $this->setHash(); 191 | $this->setPath(); 192 | $this->setPort(); 193 | $this->setSegments(); 194 | $this->setQuery(); 195 | $this->setParameters(); 196 | $this->setFilename(); 197 | $this->setDirname(); 198 | $this->setBasename(); 199 | $this->setExtension(); 200 | $this->setScheme(); 201 | $this->setUsername(); 202 | $this->setPassword(); 203 | $this->setAuthority(); 204 | $this->setBase(); 205 | } 206 | 207 | private function setAuthority(): void 208 | { 209 | $port = $this->port ? ':' . $this->port : ''; 210 | $password = $this->password ? ':' . $this->password : ''; 211 | 212 | $userInfo = ($this->username . $password) ? $this->username . $password . '@' : ''; 213 | 214 | $this->authority = $userInfo . $this->host . $port; 215 | } 216 | 217 | private function setBase(): void 218 | { 219 | $scheme = $this->scheme ? $this->scheme . ':' : ''; 220 | $host = $this->host ? '//' . $this->host : ''; 221 | $port = $this->port ? ':' . $this->port : ''; 222 | 223 | $this->base = $scheme . $host . $port; 224 | } 225 | 226 | private function setBasename(): void 227 | { 228 | $this->basename = $this->components['basename'] ?? ''; 229 | } 230 | 231 | private function setDirname(): void 232 | { 233 | $this->dirname = $this->components['dirname'] ?? ''; 234 | } 235 | 236 | private function setExtension(): void 237 | { 238 | $this->extension = $this->components['extension'] ?? ''; 239 | } 240 | 241 | private function setFilename(): void 242 | { 243 | $this->filename = $this->components['filename'] ?? ''; 244 | } 245 | 246 | private function setFragment(): void 247 | { 248 | $this->fragment = $this->components['fragment'] ?? ''; 249 | } 250 | 251 | private function setHash(): void 252 | { 253 | $this->hash = $this->fragment ? '#' . $this->fragment : ''; 254 | } 255 | 256 | private function setHost(): void 257 | { 258 | $this->host = $this->components['host'] ?? ''; 259 | } 260 | 261 | private function setParameters(): void 262 | { 263 | $params = []; 264 | 265 | parse_str($this->query, $params); 266 | 267 | $this->parameters = $params; 268 | } 269 | 270 | private function setPassword(): void 271 | { 272 | $this->password = $this->components['pass'] ?? ''; 273 | } 274 | 275 | private function setPath(): void 276 | { 277 | $this->path = $this->components['path'] ?? ''; 278 | } 279 | 280 | private function setPort(): void 281 | { 282 | $this->port = $this->components['port'] ?? ''; 283 | } 284 | 285 | private function setQuery(): void 286 | { 287 | $this->query = $this->components['query'] ?? ''; 288 | } 289 | 290 | private function setScheme(): void 291 | { 292 | $this->scheme = $this->components['scheme'] ?? ''; 293 | } 294 | 295 | private function setSegments(): void 296 | { 297 | $this->segments = $this->path ? explode('/', trim($this->path, '/')) : []; 298 | } 299 | 300 | private function setUsername(): void 301 | { 302 | $this->username = $this->components['user'] ?? ''; 303 | } 304 | } 305 | --------------------------------------------------------------------------------