Skip to content

Commit 5bb0439

Browse files
authored
Update the limitations section (#288)
1 parent ddcf428 commit 5bb0439

File tree

2 files changed

+125
-74
lines changed

2 files changed

+125
-74
lines changed

README.md

Lines changed: 119 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -592,35 +592,39 @@ composer dump-autoload --working-dir build --classmap-authoritative
592592

593593
There is 3 things to manage when dealing with isolated PHARs:
594594

595-
- The dependencies: which dependencies are you shipping? Fine controlled ones managed
596-
with a `composer.lock` or you always ship your application with up to date dependencies?
597-
- The PHAR format: there is some incompatibilities such as `realpath()` which will no
598-
longer work for the files within the PHAR since the paths are not virtual.
599-
- Isolating the code: due to the dynamic nature of PHP, isolating your dependencies will
600-
never be a trivial task and as a result you should have some end-to-end test to ensure
601-
your isolated code is working properly. You will also likely need to configure the
602-
[whitelists][whitelist] or [patchers][patchers].
603-
604-
As a result, you _should_ have end-to-end tests for your (at the minimum) your released
605-
PHAR.
606-
607-
Since dealing with the 3 issues mentioned above at once can be tedious, it is highly
608-
recommended to have several tests for each steps.
609-
610-
For example you can have a test for both your non-isolated PHAR and your isolated PHAR,
611-
this way you will know which step is causing an issue. If the isolated PHAR is not working,
612-
you can try to test the isolated code directly outside the PHAR to make sure the scoping
613-
process is not the issue.
595+
- The dependencies: which dependencies are you shipping? Fine controlled ones
596+
managed with a `composer.lock` or you always ship your application with up
597+
to date dependencies?
598+
- The PHAR format: there is some incompatibilities such as `realpath()` which
599+
will no longer work for the files within the PHAR since the paths are not
600+
virtual.
601+
- Isolating the code: due to the dynamic nature of PHP, isolating your
602+
dependencies will never be a trivial task and as a result you should have
603+
some end-to-end test to ensure your isolated code is working properly. You
604+
will also likely need to configure the [whitelists][whitelist] or
605+
[patchers][patchers].
606+
607+
As a result, you _should_ have end-to-end tests for your (at the minimum) your
608+
released PHAR.
609+
610+
Since dealing with the 3 issues mentioned above at once can be tedious, it is
611+
highly recommended to have several tests for each steps.
612+
613+
For example you can have a test for both your non-isolated PHAR and your
614+
isolated PHAR, this way you will know which step is causing an issue. If the
615+
isolated PHAR is not working, you can try to test the isolated code directly
616+
outside the PHAR to make sure the scoping process is not the issue.
614617

615618
To check if the isolated code is working correctly, you have a number of solutions:
616619

617-
- When using PHP-Scoper directly, by default PHP-Scoper dump the files in a `build` directory.
618-
Do not forget that
620+
- When using PHP-Scoper directly, by default PHP-Scoper dump the files in a
621+
`build` directory. Do not forget that
619622
[you need to dump the Composer autoloader for the isolated code to work!](#step-2-run-php-scoper).
620-
- When using [Box][box], you can use its `--debug` option from the `compile` command in order to have the
621-
code shipped in the PHAR dumped in the `.box` directory.
622-
- When using a PHAR (created by [Box][box] or any other PHAR building tool), you can use the
623-
[`Phar::extractTo()`][phar-extract-to] method.
623+
- When using [Box][box], you can use its `--debug` option from the `compile`
624+
command in order to have the code shipped in the PHAR dumped in the `.box`
625+
directory.
626+
- When using a PHAR (created by [Box][box] or any other PHAR building tool),
627+
you can use the [`Phar::extractTo()`][phar-extract-to] method.
624628

625629
Also take into consideration that bundling code in a PHAR is not guaranteed to work
626630
out of the box either. Indeed there is a number of things such as
@@ -630,42 +634,80 @@ For this reason, you should also h
630634

631635
## Limitations
632636

633-
### PSR-0 support
637+
### Dynamic symbols
634638

635-
With the following `composer.json` autoloading configuration:
639+
PHP-Scoper tries to prefix strings as well whenever possible. There will however be cases in which it will not be
640+
possible such as:
636641

637-
```json
638-
{
639-
"autoload": {
640-
"psr-0": {
641-
"Foo": "src/"
642-
}
643-
}
644-
}
645-
```
642+
- strings in regexps, e.g. `/^Acme\\\\Foo/`
643+
- concatenated strings strings, e.g.:
644+
- `$class = 'Symfony\\Component\\'.$name;`
645+
- `const X = 'Symfony\\Component' . '\\Yaml\\Ya_1';`
646646

647-
If following PSR-0, with the expected file structure is:
648647

649-
```
650-
src/
651-
Foo/
652-
A.php
653-
B.php
654-
```
648+
### Heredoc values
649+
650+
If you consider the following code:
651+
652+
```php
653+
<?php
654+
655+
<<<PHP_HEREDOC
656+
<?php
655657

656-
However this also works:
658+
use Acme\Foo;
657659

660+
PHP_HEREDOC;
658661
```
659-
src/
660-
Foo.php
662+
663+
The content of `PHP_HEREDOC` will not be prefixed. Some partial support could be added in the future but is bound to
664+
be very limited due to the dynamic nature of heredocs. If you consider the following for example:
665+
666+
```php
667+
<?php
668+
669+
<<<EOF
670+
<?php
671+
672+
{$namespaceLine}
673+
674+
// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
675+
676+
if (\\class_exists(\\Container{$hash}\\{$options['class']}::class, false)) {
677+
// no-op
678+
} elseif (!include __DIR__.'/Container{$hash}/{$options['class']}.php') {
679+
touch(__DIR__.'/Container{$hash}.legacy');
680+
return;
681+
}
682+
683+
if (!\\class_exists({$options['class']}::class, false)) {
684+
\\class_alias(\\Container{$hash}\\{$options['class']}::class, {$options['class']}::class, false);
685+
}
686+
687+
return new \\Container{$hash}\\{$options['class']}(array(
688+
'container.build_hash' => '$hash',
689+
'container.build_id' => '$id',
690+
'container.build_time' => $time,
691+
), __DIR__.\\DIRECTORY_SEPARATOR.'Container{$hash}');
692+
693+
EOF;
661694
```
662695

663-
This is unexpected as `Foo` is a file rather than a directory.
696+
It would be very hard to properly scope the relevant classes.
697+
698+
699+
### Callables
664700

665-
PHP-Scoper supports PSR-0 by transforming the configuration into a PSR-4 configuration.
666-
However support a case like above would require to scan the file structure which would
667-
add a significant overhead besides being more complex. As a result PHP-Scoper do not
668-
support the exotic case above.
701+
If you consider the two following values:
702+
703+
```php
704+
['Acme\Foo', 'bar'];
705+
'Acme\Foo::bar';
706+
```
707+
708+
The classes used there will not be scoped. It should not be impossible to add
709+
support for it but it is currently not supported. See
710+
[#286](https://github.com/humbug/php-scoper/issues/286).
669711

670712

671713
### String values
@@ -689,13 +731,15 @@ prefixed. But there is bound to have confusing cases. For example:
689731
is no way to know if it is a class name or a random string except for a
690732
handful of methods:
691733

734+
- `class_alias()`
735+
- `class_exists()`
736+
- `define()`
737+
- `defined()`
738+
- `function_exists()`
739+
- `interface_exists()`
692740
- `is_a()`
693741
- `is_subclass_of()`
694-
- `interface_exists()`
695-
- `class_exists()`
696742
- `trait_exists()`
697-
- `function_exists()`
698-
- `class_alias()`
699743

700744

701745
### Native functions and constants shadowing
@@ -711,13 +755,17 @@ is_array([]);
711755

712756
```
713757

714-
No use statement is used for the function `is_array`. This means that PHP will try to load the function `\Foo\is_array`
715-
and if fails to do so will fallback on `\is_array` (note that PHP does so only for functions and constants: not classes).
758+
No use statement is used for the function `is_array`. This means that PHP will
759+
try to load the function `\Foo\is_array` and if fails to do so will fallback
760+
on `\is_array` (note that PHP does so only for functions and constants: not
761+
classes).
716762

717-
In order to bring some performance optimisation, the call will nonetheless be prefixed in `\is_array`. This *will* break
718-
your code if you were relying on `\Foo\is_array` instead. This however should be _extremely_ rare, so if that happens
719-
you have two solutions: use a [patcher](#patchers) or simpler remove any ambiguity by making use of a use statement
720-
(which is unneeded outside of the context of prefixing your code):
763+
In order to bring some performance optimisation, the call will nonetheless be
764+
prefixed in `\is_array`. This *will* break your code if you were relying on
765+
`\Foo\is_array` instead. This however should be _extremely_ rare, so if that
766+
happens you have two solutions: use a [patcher](#patchers) or simpler remove
767+
any ambiguity by making use of a use statement (which is unneeded outside of
768+
the context of prefixing your code):
721769

722770
```php
723771
<?php
@@ -752,21 +800,24 @@ const Y = 'bar';
752800

753801
### Composer Autoloader
754802

755-
PHP-Scoper does not support prefixing the dumped Composer autoloader and autoloading files. This is why you have to
756-
manually dump the autoloader again after prefixing an application.
803+
PHP-Scoper does not support prefixing the dumped Composer autoloader and
804+
autoloading files. This is why you have to manually dump the autoloader again
805+
after prefixing an application.
757806

758807
Note: when using Box, Box is able to take care of that step for you.
759808

760809

761810
### Composer Plugins
762811

763-
Composer plugins are not supported. The issue is that for [whitelisting symbols](#whitelist) PHP-Scoper relies on the
764-
fact that you should load the `vendor/scoper-autoload.php` file instead of `vendor/autoload.php` to trigger the loading
765-
of the right classes with their class aliases. However Composer does not do that and as a result interfaces such as
812+
Composer plugins are not supported. The issue is that for
813+
[whitelisting symbols](#whitelist) PHP-Scoper relies on the fact that you
814+
should load the `vendor/scoper-autoload.php` file instead of
815+
`vendor/autoload.php` to trigger the loading of the right classes with their
816+
class aliases. However Composer does not do that and as a result interfaces such as
766817
`Composer\Plugin\Capability\Capable` are prefixed but the alias is not registered.
767818

768-
This cannot be changed easily so for now when you are using an isolated version of Composer, you will need to use the
769-
`--no-plugins` option.
819+
This cannot be changed easily so for now when you are using an isolated version
820+
of Composer, you will need to use the `--no-plugins` option.
770821

771822

772823
## Contributing

src/PhpParser/NodeVisitor/StringScalarPrefixer.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,15 @@
5656
final class StringScalarPrefixer extends NodeVisitorAbstract
5757
{
5858
private const SPECIAL_FUNCTION_NAMES = [
59-
'is_a',
60-
'is_subclass_of',
61-
'interface_exists',
62-
'class_exists',
63-
'trait_exists',
64-
'function_exists',
6559
'class_alias',
60+
'class_exists',
6661
'define',
6762
'defined',
63+
'function_exists',
64+
'interface_exists',
65+
'is_a',
66+
'is_subclass_of',
67+
'trait_exists',
6868
];
6969

7070
private $prefix;

0 commit comments

Comments
 (0)