Skip to content

Latest commit

 

History

History
211 lines (152 loc) · 6.18 KB

further-reading.md

File metadata and controls

211 lines (152 loc) · 6.18 KB

Further Reading

How to deal with unknown third-party symbols

If you consider the following code:

<?php

namespace Acme;

use function wp_list_users;

foreach (wp_list_users() as $user) {
    // ...
}

It would be scoped as follows:

<?php

namespace ScopingPrefix\Acme;

use function ScopingPrefix\wp_list_users;

foreach (wp_list_users() as $user) {
    // ...
}

This however will be a problem if your code (or your vendor) never declares wp_list_users.

There is "two" ways to deal with this:

  • excluding the symbol (recommended)
  • exposing the symbol (fragile)

Excluding the symbol (see excluded-symbols) marks it as "internal", as if this symbol was coming from PHP itself or a PHP extension. This is the most appropriate solution.

Exposing the symbol may work but is more fragile. Indeed, exposing the symbol will result in an alias being registered (see exposed-symbols), which means you need to have the function declared within your codebase at some point.

Autoload aliases

Class aliases

When exposing a class, an alias will be registered.

Function aliases

When exposing a function or when a globally declared excluded-function declaration is found (see #706), an alias will be registered.

Laravel support

PHP-Scoper supports laravel out of the box for the most part. There is one problematic piece that is not supported and that is the views. However, this can be fixed by hand without too much problems:

// scoper.inc.php
<?php declare(strict_types=1);

use Isolated\Symfony\Component\Finder\Finder;

$consoleViewFiles = array_map(
    static fn (SplFileInfo $fileInfo) => $fileInfo->getPathname(),
    iterator_to_array(
        Finder::create()
            ->in('vendor/laravel/framework/src/Illuminate/Console/resources/views')
            ->files(),
        false,
    ),
);

return [
    'exclude-files' => [
        ...$consoleViewFiles,
    ],
    'patchers' => [
        static function (string $filePath, string $prefix, string $contents): string {
            if (!str_ends_with($filePath, 'vendor/laravel/framework/src/Illuminate/Console/View/Components/Factory.php')) {
                return $contents;
            }

            return str_replace(
                '$component = \'\\\\Illuminate\\\\Console\\\\View\\\\Components\\\\\' . ucfirst($method);',
                '$component = \'\\\\'.$prefix.'\\\\Illuminate\\\\Console\\\\View\\\\Components\\\\\' . ucfirst($method);',
                $contents,
            );
        },
    ],
];

Symfony Support

When using PHP configuration files for your services, some elements may not be prefixed correctly due to being strings. For example (taken directly from the Symfony docs):

<?php // config/services.php

namespace Symfony\Component\DependencyInjection\Loader\Configurator;

return function(ContainerConfigurator $container): void {
    // default configuration for services in *this* file
    $services = $container->services()
        ->defaults()
            ->autowire()      // Automatically injects dependencies in your services.
            ->autoconfigure() // Automatically registers your services as commands, event subscribers, etc.
    ;

    // makes classes in src/ available to be used as services
    // this creates a service per class whose id is the fully-qualified class name
    $services->load('App\\', '../src/')
        ->exclude('../src/{DependencyInjection,Entity,Kernel.php}');

    // order is important in this file because service definitions
    // always *replace* previous ones; add your own service configuration below
};

The string 'App\\' from $services->load() will not be made into 'Prefix\\App\\'. To address this you need to use patchers. Alternatively, PHP-Scoper provides one which should should handle such cases:

<?php // scoper.inc.php

$symfonyPatcher = (require __DIR__.'/vendor/humbug/php-scoper/res/create-symfony-php-services-patcher.php')('config/services.php');

return [
    'patchers' => [$symfonyPatcher],
    // ...
];

Note that the path is the "regular path(s)" that can be passed to patchers.

Wordpress Support

When writing a Wordpress plugin, you need to exclude Wordpress' symbols. To facilitate this task, Snicco created a third-party CLI tool php-scoper-excludes that can be used to generate PHP-Scoper compatible symbol lists for any PHP codebase you point it.

Example for WordPress Core

composer require sniccowp/php-scoper-wordpress-excludes
// scoper.inc.php

function getWpExcludedSymbols(string $fileName): array
{
    $filePath = __DIR__.'/vendor/sniccowp/php-scoper-wordpress-excludes/generated/'.$fileName;

    return json_decode(
        file_get_contents($filePath),
        true,
    );
}

$wp_classes   = getWpExcludedSymbols('exclude-wordpress-classes.json');
$wp_functions = getWpExcludedSymbols('exclude-wordpress-functions.json');
$wp_constants = getWpExcludedSymbols('exclude-wordpress-constants.json');

return [
  'exclude-classes' => $wp_classes,
  'exclude-constants' => $wp_functions,
  'exclude-functions' => $wp_constants,
  // ...
];


« ConfigurationLimitations »