Skip to content

Latest commit

 

History

History
284 lines (188 loc) · 7.75 KB

limitations.md

File metadata and controls

284 lines (188 loc) · 7.75 KB

Limitations

Dynamic symbols

PHP-Scoper tries to prefix strings as well whenever possible. There will however be cases in which it will not be possible such as:

  • strings in regexps, e.g. /^Acme\\\\Foo/
  • concatenated strings, e.g.:
    • $class = 'Symfony\\Component\\'.$name;
    • const X = 'Symfony\\Component' . '\\Yaml\\Ya_1';

Date symbols

You code may be using a convention for the date string formats which could be mistaken for classes, e.g.:

const ISO8601_BASIC = 'Ymd\THis\Z';

In this scenario, PHP-Scoper has no way to tell that string 'Ymd\THis\Z' does not refer to a symbol but is a date format. In this case, you will have to rely on patchers. Note however that PHP-Scoper will be able to handle some cases such as, see the date-spec.

Heredoc values

If you consider the following code:

<?php

<<<PHP_HEREDOC
<?php

use Acme\Foo;

PHP_HEREDOC;

The content of PHP_HEREDOC will not be prefixed. Some partial support could be added in the future but is bound to be very limited due to the dynamic nature of heredocs. If you consider the following for example:

<?php

<<<EOF
<?php

{$namespaceLine}

// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.

if (\\class_exists(\\Container{$hash}\\{$options['class']}::class, false)) {
    // no-op
} elseif (!include __DIR__.'/Container{$hash}/{$options['class']}.php') {
    touch(__DIR__.'/Container{$hash}.legacy');
    return;
}

if (!\\class_exists({$options['class']}::class, false)) {
    \\class_alias(\\Container{$hash}\\{$options['class']}::class, {$options['class']}::class, false);
}

return new \\Container{$hash}\\{$options['class']}(array(
    'container.build_hash' => '$hash',
    'container.build_id' => '$id',
    'container.build_time' => $time,
), __DIR__.\\DIRECTORY_SEPARATOR.'Container{$hash}');

EOF;

It would be very hard to properly scope the relevant classes.

To fix such cases, you will need to resort to patchers.

Callables

If you consider the two following values:

['Acme\Foo', 'bar'];
'Acme\Foo::bar';

The classes used there will not be scoped. It should not be impossible to add support for it, but it is currently not supported. See #286.

To fix such cases, you will need to resort to patchers.

String values

PHP-Scoper tries whenever possible to prefix strings as well:

class_exists('Acme\Foo');

// Will be prefixed into:

\class_exists('Humbug\Acme\Foo');

PHP-Scoper uses a regex to determine if the string is a class name that must be prefixed. But there is bound to have confusing cases. For example:

  • If you have a plain string 'Acme\Foo' which has nothing to do with a class, PHP-Parser will not be able to tell and will prefix it
  • Classes belonging to the global scope: 'Foo' or 'Acme_Foo', because there is no way to know if it is a class name or a random string except for a handful of methods such as class_alias, function_exists, etc.

To fix such cases, you will need to resort to patchers.

Native functions and constants shadowing

In the following example:

<?php

namespace Foo;

is_array([]);

No use statement is used for the function is_array. This means that PHP will try to load the function \Foo\is_array and if fails to do so will fallback on \is_array (note that PHP does so only for functions and constants, not classes).

In order to bring some performance optimisation, the call will nonetheless be prefixed in \is_array. This will break your code if you were relying on \Foo\is_array instead. This however should be extremely rare, so if that happens you have two solutions: use a patcher or simply remove any ambiguity by making use of a use statement (which is unneeded outside of the context of prefixing your code):

<?php

namespace Foo;

use function Foo\is_array;

is_array([]);

The situation is exactly the same for constants.

Composer Autoloader

PHP-Scoper does not support prefixing the dumped Composer autoloader and autoloading files. This is why you have to manually dump the autoloader again after prefixing an application.

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

PHP-Scoper also can not handle Composers static file autoloaders. This is due to Composer loading files based on a hash which is generated from package name and relative file path. For a workaround see #298.

To fix such cases, you will need to resort to patchers.

Composer Plugins

Composer plugins are not supported. The issue is that for Exposing symbols PHP-Scoper relies on the fact that you should load the vendor/scoper-autoload.php file instead of vendor/autoload.php to trigger the loading of the right classes with their class aliases. However Composer does not do that and as a result interfaces such as Composer\Plugin\Capability\Capable are prefixed but the alias is not registered.

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

PSR-0 Partial support

As of now, given the following directory structure:

src/
  JsonMapper.php
  JsonMapper/
    Exception.php

with the following configuration:

{
  "autoload": {
     "psr-0": {"JsonMapper": "src/"}
  }
}

The autoloading will not work. Indeed, PHP-Scoper attempts to support PSR-0 by transforming it to PSR-4, i.e. in the case above:

{
  "autoload": {
     "psr-4": {"PhpScoperPrefix\\JsonMapper": "src/"}
  }
}

If this works for the classes under src/JsonMapper/, it will not for JsonMapper.php.

Exposing/Excluding traits

There is currently no way to expose or exclude a trait. Since there is no aliasing mechanism for traits, it could be still possible by declaring a trait that extends the scoped trait, but this is currently not implemented.

Exposing/Excluding enums

There is currently no way to expose or exclude an enum. The problem being there is no way to alias one.

Declaring a custom namespaced function function_exists()

When PHP-Scoper encounters a call such as this one:

namespace App;

function_exists('NewApp\main');

That the string contained by function_exists is a fully-qualified class name. This is true however if function_exists() is the native PHP one. However, technically, if the function App\function_exists() does exist, then the call above would call App\function_exists() and not function_exists().

This is a very unlikely scenario which is why PHP-Scoper will assume it is the PHP native one.

If, by any chance, this is a problem, you will have to fix it with patchers.



« Further ReadingTable of Contents »