Optimizes class loading performance by generating a single PHP file containing all of the autoloaded files.

Overview

Class Preloader for PHP

This tool is used to generate a single PHP script containing all of the classes required for a specific use case. Using a single compiled PHP script instead of relying on autoloading can help to improve the performance of specific use cases. For example, if your application executes the same bootstrap code on every request, then you could generate a preloader (the compiled output of this tool) to reduce the cost of autoloading the required classes over and over.

Banner

What it actually does

This tool listens for each file that is autoloaded, creates a list of files, traverses the parsed PHP file using PHP Parser and any visitors of a Config object, wraps the code of each file in a namespace block if necessary, and writes the contents of every autoloaded file (in order) to a single PHP file.

Notice

This tool should only be used for specific use cases. There is a tradeoff between preloading classes and autoloading classes. The point at which it is no longer beneficial to generate a preloader is application specific. You'll need to perform your own benchmarks to determine if this tool will speed up your application.

Installation

Add ClassPreloader as a dependency to your composer.json file by adding "classpreloader/classpreloader": "^4.1" to your require block. Note that if you want to use the cli tool, then you need to also add "classpreloader/console": "^3.1" to the require block.

Using the tool

You use the ./vendor/bin/classpreloader compile command with a few command line flags to generate a preloader.

--config: A CSV containing a list of files to combine into a classmap, or the full path to a PHP script that returns an array of classes or a ClassPreloader\ClassLoader\Config object.

--output: The path to the file to store the compiled PHP code. If the directory does not exist, the tool will attempt to create it.

--skip_dir_file: (no value) Skip files with __DIR__ or __FILE__ to make the cache portable.

--fix_dir: (defaults to 1) Set to 0 to not replace __DIR__ constants with the actual directory of the original file.

--fix_file: (defaults to 1) Set to 0 to not replace __FILE__ constants with the actual location of the original file.

--strict_types: (defaults to 0) Set to 1 to enable strict types mode.

--strip_comments: (defaults to 0) Set to 1 to strip comments from each source file.

Writing a config file

Creating a PHP based configuration file is fairly simple. Just include the vendor/classpreloader/classpreloader/src/ClassLoader.php file and call the ClassPreloader\ClassLoader::getIncludes() method, passing a function as the only argument. This function should accept a ClassPreloader\ClassLoader object and register the passed in object's autoloader using $loader->register(). It is important to register the ClassPreloader\ClassLoader autoloader after all other autoloaders are registered.

An array or ClassPreloader\ClassLoader\Config must be returned from the config file. You can attach custom node visitors if you need to perform any sort of translation on each matching file before writing it to the output.

<?php

// Here's an example of creating a preloader for using the
// Amazon DynamoDB and the AWS SDK for PHP 2.

require __DIR__.'/src/Config.php';
require __DIR__.'/src/ClassNode.php';
require __DIR__.'/src/ClassList.php';
require __DIR__.'/src/ClassLoader.php';

use ClassPreloader\ClassLoader;

$config = ClassLoader::getIncludes(function (ClassLoader $loader) {
    require __DIR__.'/vendor/autoload.php';
    $loader->register();
    $aws = Aws\Common\Aws::factory([
        'key'    => '***',
        'secret' => '***',
        'region' => 'us-east-1'
    ]);
    $client = $aws->get('dynamodb');
    $client->listTables()->getAll();
});

// Add a regex filter that requires all classes to match the regex.
// $config->addInclusiveFilter('/Foo/');

// Add a regex filter that requires that a class does not match the filter.
// $config->addExclusiveFilter('/Foo/');

return $config;

You would then run the classpreloader script and pass in the full path to the above PHP script.

./vendor/bin/classpreloader compile --config="/path/to/the_example.php" --output="/tmp/preloader.php"

The above command will create a file in /tmp/preloader.php that contains every file that was autoloaded while running the snippet of code in the anonymous function. You would generate this file and include it in your production script.

Automating the process with Composer

You can automate the process of creating preloaders using Composer's script functionality. For example, if you wanted to automatically create a preloader each time the AWS SDK for PHP is installed, you could define a script like the following in your composer.json file:

{
    "require": {
        "classpreloader/console": "^3.1"
    },
    "scripts": {
        "post-autoload-dump": "@php vendor/bin/classpreloader compile --config=/path/to/the_example.php --output=/path/to/preload.php"
    },
    "config": {
        "bin-dir": "bin"
    }
}

Using the above composer.json file, each time the project's autoloader is recreated using the install or update command, the classpreloader.php file will be executed. This script would generate a preload.php containing the classes required to run the previously demonstrated "the_example.php" configuration file.

Security

If you discover a security vulnerability within this package, please send an email to Graham Campbell at [email protected]. All security vulnerabilities will be promptly addressed. You may view our full security policy here.

License

Class Preloader is licensed under The MIT License (MIT).

For Enterprise

Available as part of the Tidelift Subscription

The maintainers of classpreloader/classpreloader and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. Learn more.

Comments
  • PSR-4 Autoloading And Added Tests

    PSR-4 Autoloading And Added Tests

    This switches us to psr-4 autoloading, adds some tests, and bumps the version to 1.1. The actual 1.1.0 tag can come after the php parser stuff has gone through as previously discussed.

    • The test suite here is not 100% complete, but does cover the bulk of things.
    • There's travis config in here too, so you should be able to enable travis for this repo now.
    • Travis is passing on my fork: https://travis-ci.org/GrahamCampbell/ClassPreloader/builds/34125496.
    • Note that enabling code coverage with process isolation causes very poor performance.

    Running the tests just with process isolation takes 1-2 seconds. Running the tests with code coverage enabled too takes 1-2 minutes, and even longer on php 5.3.

    opened by GrahamCampbell 12
  • Not possible add a class without the namespace?

    Not possible add a class without the namespace?

    PHP Fatal error: Cannot mix bracketed namespace declarations with unbracketed namespace declarations in /var/www/laravel.local/bootstrap/compiled.php on line 10906

    opened by paveleremin 10
  • Use a visitor to wrap non-namespaced code in an empty namespace.

    Use a visitor to wrap non-namespaced code in an empty namespace.

    I found that some of the classes were outputted without a namespace, causing a PHP Fatal error: No code may exist outside of namespace {}. A quick fix was implemented in #7, but this ignores files with the character sequence namespace, regardless of its position. It may appear in a comment, for example.

    I've implemented a node visitor that ensures all code is wrapped in an empty/root namespace. I didn't feel it was necessary to make this configurable, so I did not implement an additional command line option.

    opened by rjkip 10
  • Cannot instantiate interface PhpParser\Parser

    Cannot instantiate interface PhpParser\Parser

    in ClassPreloader/src/Factory.php file line 64 , I find this code return new Parser(new Lexer()) , but the Parser is interface in the nikic/php-parser/lib/PhpParser/Parser.php , so I think it is a bug because we cant new a interface.

    opened by Awezome 9
  • Write file atomically

    Write file atomically

    On my production Laravel site I get some errors while "php artisan optimize" is running because this takes a few seconds to write the file, and it writes it line by line. While it is writing the file visitors are accessing the site and Laravel loads the vendor/compiled.php file this generates, but it is only half-written.

    I've changed it so it writes to a temporary file, then moves it into its final destination using PHP's rename() function.

    opened by antriver 9
  • What is wrong? PHP Fatal error:  Class 'ClassPreloader\Application' not found

    What is wrong? PHP Fatal error: Class 'ClassPreloader\Application' not found

    php vendor/bin/classpreloader.php compile --config="public/preloaderConfig.php" --output="public/preloader.php"
    PHP Fatal error:  Class 'ClassPreloader\Application' not found in /home/.../vendor/classpreloader/console/classpreloader.php on line 20
    
    
    opened by seyfer 7
  • skip/exclude classes with DIR or FILE

    skip/exclude classes with DIR or FILE

    Like written in https://github.com/mtdowling/ClassPreloader/issues/37

    New command: --skip_dir_file when given, all PHP classes with a DIR or FILE constant are skipped from caching

    opened by ThaDafinser 7
  • Upgrade To PHP Parser 1.0

    Upgrade To PHP Parser 1.0

    This upgrades us to php parser 1.0.

    ~~I've bumped our version from 1.0 to 1.1 for this change. A php parser stable tag will come in 2 week's time (https://github.com/nikic/PHP-Parser/issues/125#issuecomment-53990700), so if you like this, it might be a good idea to stamp the 1.1.0 release after php parser has a stable tag.~~ The version bump was done as part of another pull.

    It might be a good idea to stamp the 1.1.0 release after php parser has a stable tag.

    opened by GrahamCampbell 7
  • Fix wrap namespaces

    Fix wrap namespaces

    There is problem with checking for namespace keyword at this moment: if we have this keyword in comments we will wrap code and sometimes it gives probles.

    Sometimes we need to skip wrapping at from this point I've added special option to skip wrap.

    opened by damnedest 7
  • Replace substr in getCode() to cover more cases.

    Replace substr in getCode() to cover more cases.

    The current replacer does not cover all cases to remove declare statements regarding 'strict_types' definitions.

    Currently not covered:

    • If there is more than one line break before the declare statement
    • If there are arbitrary spaces within the declare statement
    • If there is a comment before the declare statement

    To not build the whole statemachine by ourself I decided to use a regex to tackle those problems. As this will in most cases only be ran if the boostrap needs to be regenerated we should be safe with the implied performance hit regarding the usage of regex here.

    Rundown on the Regex parts:

    • ^ - Match the beginning of the file only
    • (<\?php)? - Match starting PHP Tags (if existent)
    • ([\s]*/\*\*?.*?\*/[\s]*)? - Match file comments (if existent)
    • [\s]* - Match arbitrary number of spaces
    • (declare[\s]*\([\s]*strict_types[\s]*=[\s]*1[\s]*\);)? - Match strict definition (if existent)

    This should handle the whole pretty cleanup more gracefully regarding external/vendored codebases which may not apply to some predefined CodingStandard.

    opened by Blackskyliner 6
  • Classes without namespace

    Classes without namespace

    I'm having the same problem as https://github.com/ClassPreloader/ClassPreloader/issues/29

    Follow this steps:

    compiled.php

    <?php
    namespace Illuminate\Contracts\Container;
    
    use Closure;
    
    interface Container
    {
        public function bound($abstract);
        public function alias($abstract, $alias);
    }
    
    namespace MyApp\Foo;
    
    class MyClass
    {
        public function doSomething()
        {
    
        }
    }
    
    namespace {
        class MyClass
        {
            public function doSomething()
            {
    
            }
        }
    }
    

    My test file:

    index.php

    <?php
    
    require "compiled.php";
    
    $class = new MyApp\Foo\MyClass();
    var_dump($class);
    
    $class2 = new MyClass();
    var_dump($class2);
    

    Throws this error:

    Fatal error: Cannot mix bracketed namespace declarations with unbracketed namespace declarations in /Users/kennedytedesco/Documents/www/compiled.php on line 22
    

    But if I change my compiled.php file to have just bracketed namespaces:

    <?php
    namespace Illuminate\Contracts\Container {
        use Closure;
    
        interface Container
        {
            public function bound($abstract);
            public function alias($abstract, $alias);
        }
    }
    
    namespace MyApp\Foo {
        class MyClass
        {
            public function doSomething()
            {
    
            }
        }
    }
    
    namespace {
        class MyClass
        {
            public function doSomething()
            {
    
            }
        }
    }
    

    Works fine:

    object(MyApp\Foo\MyClass)#1 (0) { } 
    object(MyClass)#2 (0) { }
    

    I'm working with php 5.6.9.

    PHP 5.6.9 (cli) (built: May 15 2015 21:32:02) 
    Copyright (c) 1997-2015 The PHP Group
    Zend Engine v2.6.0, Copyright (c) 1998-2015 Zend Technologies
    

    This PR https://github.com/ClassPreloader/ClassPreloader/pull/25 need to be merged, or, another option is add brackets to all namespaces, like shown before.

    opened by KennedyTedesco 6
Releases(4.2.0)
  • 4.2.0(Aug 28, 2021)

    This is the second release in the 4.2.x series.

    This release contains the following improvements:
    • Added support for PHP 8.1 (af9284543aedb45ed58359374918141c0ac7ae34)

    https://github.com/ClassPreloader/ClassPreloader/compare/4.1.0...4.2.0

    Source code(tar.gz)
    Source code(zip)
  • 4.1.0(Dec 31, 2020)

    This is the first release in the 4.1.x series.

    This release contains the following improvements:
    • Added support for PHP 8.0 (db3c991fe626fc69e4f33e6f4ae29b92b8f0a842)

    https://github.com/ClassPreloader/ClassPreloader/compare/4.0.1...4.1.0

    Source code(tar.gz)
    Source code(zip)
  • 4.0.1(Apr 13, 2020)

    This is the first patch release in the 4.0.x series.

    This release fixes the following regressions:
    • Updated funding information (a1264c8a6c079a6a0b8cfc5358b215293c399000)

    https://github.com/ClassPreloader/ClassPreloader/compare/4.0.0...4.0.1

    Source code(tar.gz)
    Source code(zip)
  • 3.2.1(Apr 12, 2020)

    This is the first patch release in the 3.2.x series.

    This release fixes the following regressions:
    • Updated funding information (297db07cabece3946f4a98d23f11f90aa10e1797)

    https://github.com/ClassPreloader/ClassPreloader/compare/3.2.0...3.2.1

    Source code(tar.gz)
    Source code(zip)
  • 4.0.0(Jan 1, 2020)

    This is the first release in the 4.0.x series.

    We've dropped support for PHP 5 and older PHP Parser versions. It's still possible to parse PHP 5 code, but not to run Class Preloader on PHP 5. This is the first release of Class Preloader to support the all the new syntax in PHP 7.3 and 7.4.

    We've also renamed some of our classes, and marked some of our code as internal. What used to be the Factory and ClassPreloader classes are now merged into one class called CodeGenerator. Management of the output file has been extracted to a new class called OutputWriter. Note also that our exception namespace has changed from ClassPreloader\Exceptions to ClassPreloader\Exception.


    https://github.com/ClassPreloader/ClassPreloader/compare/3.2.0...4.0.0

    Source code(tar.gz)
    Source code(zip)
  • 3.2.0(Dec 10, 2017)

    This is the first release in the 3.2.x series.

    This release contains the following improvements:
    • More robust strict declare parsing (#61)

    https://github.com/ClassPreloader/ClassPreloader/compare/3.1.0...3.2.0

    Source code(tar.gz)
    Source code(zip)
  • 3.1.0(Dec 2, 2016)

    This is the first release in the 3.1.x series.

    This release fixes the following regressions:
    • Fixed classes with phpdoc before the namespace (#59)
    This release contains the following improvements:
    • Support PHP 7.1 and PHP Parser 3 (#60)

    https://github.com/ClassPreloader/ClassPreloader/compare/3.0.0...3.1.0

    Source code(tar.gz)
    Source code(zip)
  • 3.0.0(Nov 9, 2015)

    This is the first release in the 3.0.x series.

    This release adds support enabling strict types, and skipping files with strict types enabled if we don't want the compiled file to have strict types enabled. It also includes allowing usage with either PHP Parser 1.x or 2.x, rather than just 1.x, previously. Finally, the addition of a Factory class can help you get started even quicker if you're not using the Console package provided.


    https://github.com/ClassPreloader/ClassPreloader/compare/2.0.0...3.0.0

    Source code(tar.gz)
    Source code(zip)
  • 2.0.0(Jun 28, 2015)

    This is the first release in the 2.0.x series.

    This release contains internal refactoring and the abstraction of the console command to a separate package. We also have fewer dependencies so this package should be installable in even more places without conflict. Also note that we now only support php 5.5.9+.


    https://github.com/ClassPreloader/ClassPreloader/compare/1.4.0...2.0.0

    Source code(tar.gz)
    Source code(zip)
  • 1.4.0(May 28, 2015)

    This is the first release in the 1.4.x series.

    This release fixes the following regressions:
    • Fixed classes without namespace (#29, #48, #49)
    This release contains the following improvements:
    • Various minor changes

    https://github.com/ClassPreloader/ClassPreloader/compare/1.3.0...1.4.0

    Source code(tar.gz)
    Source code(zip)
  • 1.3.0(Apr 18, 2015)

    This is the first release in the 1.3.x series.

    This release fixes the following regressions:
    • PHP 7 Support (2d5a5b17002186d9f878b22d0287f95011a4ea8e, bf9f7436a2463c234bb24d3a1bb3403f868d304d, 30fa71d70196b238b957b8fd74a024eec8438746)
    This release contains the following improvements:
    • Tweaked phpunit config (0544616ba33fb2a6b792b3a7822650810c6d65d9)
    • Various minor fixes (a9a6ef9b1a6960d45481ce7fdf375177eeb7007f, 259b79f9685e5ef6d25e5b66918a6ce9ab3e3aee)
    • Minor cs fixes (82786dcc589932f71dc1e014a63a158143bfaa13, 642bf438ce3fcdcaddb89927295115e62c60870c, 32d7fd2f7731c45f719e4bcd2e5ba7916de4a687, b19768c7eb7170d52f0f4470b0fa6bcfe062406a)

    https://github.com/ClassPreloader/ClassPreloader/compare/1.2.0...1.3.0

    Source code(tar.gz)
    Source code(zip)
  • 1.2.0(Jan 26, 2015)

    This is the first release in the 1.2.x series.

    This release fixes the following regressions:
    • Fixed The Console Command On Windows (#36)
    • Fixed Multiple Class Declarations (#39)
    • Fixed The Readme Instructions (76dc4466dc85ca31efe135ff51cf30d663a41269)
    • Fixed Issues With ClassLoader Extension (a6b67d6e6837437959d6f69bf245eec7cb441a3b)
    • Added Missing Version Info To The Application (f0bfbf71fb3335c9473f695d4d966ba2fb879a9f)
    This release contains the following improvements:
    • Added Support For Skipping Classes With DIR Or FILE (#42)
    • Improved Docblocks (#32, f69e254a4aa4e395890de183f2160d42dbdcbe88)

    https://github.com/ClassPreloader/ClassPreloader/compare/1.1.0...1.2.0

    Source code(tar.gz)
    Source code(zip)
  • 1.1.0(Sep 23, 2014)

    This is the first release in the 1.1.x series.

    This release fixes the following regressions:
    • Fixed Non-Existent Classes (#26)
    This release contains the following improvements:
    • Upgraded To PHP Parser 1.0 (#27)
    • PSR-4 Autoloading (ae497b8c8bc86cab0dd49b81026b97acde304af6)

    https://github.com/ClassPreloader/ClassPreloader/compare/1.0.2...1.1.0

    Source code(tar.gz)
    Source code(zip)
  • 1.0.2(Sep 7, 2014)

    This is the second patch release in the 1.0.x series.

    This release fixes the following regressions:
    • Fixed An Undefined Variable Issue (e45cfc00f40d74a26876e18112dea750363659fa)
    • Composer Fixes (526394d57ddbf06b38e3f991764147b415de1910)
    This release also contains the following improvements:
    • Tweaked Some Docblocks (8a13e719477a212f2ed18ae74e60aa668ad41a32)
    • Tweaked The Readme (ac526397f05362cd084282e5c53193c5efd2855a)

    https://github.com/ClassPreloader/ClassPreloader/compare/1.0.1...1.0.2

    Source code(tar.gz)
    Source code(zip)
  • 1.0.1(Sep 7, 2014)

    This is the first patch release in the 1.0.x series.

    This release fixes the following regressions:
    • Windows Path Fix (bec3c8ba4b2a09bc2e9c45626e58f6c7d9b21ef5)
    This release also contains the following improvements:
    • Add A Branch Alias (3279a898baab198f553166681823a82bfff844bd)
    • Support Interfaces (8130c630e533b0ff8f9a9b762d757f7fac89ed5c, 1a50f7945b725ff2c60f234e51407d1d6e7c77c5)

    https://github.com/ClassPreloader/ClassPreloader/compare/1.0.0...1.0.1

    Source code(tar.gz)
    Source code(zip)
  • 1.0.0(Sep 7, 2014)

Owner
Class Preloader
Class Preloader
Repository containing all the PHPStan rules from the book "Recipes for Decoupling"

PHPStan rules from the book "Recipes for Decoupling" by Matthias Noback In the book "Recipes for Decoupling" we discuss how to decouple from web and C

Matthias Noback 19 Sep 21, 2022
This PHP script optimizes the speed of your RAM memory

██████╗░██╗░░██╗██████╗░░█████╗░██╗░░░░░███████╗░█████╗░███╗░░██╗███████╗██████╗░ ██╔══██╗██║░░██║██╔══██╗██╔══██╗██║░░░░░██╔════╝██╔══██╗████╗░██║██╔

Érik Freitas 7 Feb 12, 2022
High-performance, low-memory-footprint, single-file embedded database for key/value storage

LDBA - a fast, pure PHP, key-value database. Information LDBA is a high-performance, low-memory-footprint, single-file embedded database for key/value

Simplito 12 Nov 13, 2022
Ip2region is a offline IP location library with accuracy rate of 99.9% and 0.0x millseconds searching performance. DB file is ONLY a few megabytes with all IP address stored. binding for Java,PHP,C,Python,Nodejs,Golang,C#,lua. Binary,B-tree,Memory searching algorithm

Ip2region是什么? ip2region - 准确率99.9%的离线IP地址定位库,0.0x毫秒级查询,ip2region.db数据库只有数MB,提供了java,php,c,python,nodejs,golang,c#等查询绑定和Binary,B树,内存三种查询算法。 Ip2region特性

Lion 12.6k Dec 30, 2022
A wrapper around symplify/config-transformer used to update recipes and using easy coding standard for generating readable config files.

Symfony Recipes Yaml to PHP Converter This is a wrapper around the symplify/config-transformer used to convert Symfony core recipes which uses .yaml c

Alexander Schranz 3 Nov 24, 2022
A plugin that teleports to world with Fancy Loading screen like WaterdogPE!

FancyTeleportScreen This is was made by Dyzer Development This plugin was allows you to teleport other world with LoadingScreen! Information This is w

Dyzer Development 1 Feb 11, 2022
🧬 Nano is a zero-config, no skeleton, minimal Hyperf distribution that allows you to quickly build a Hyperf application with just a single PHP file.

Nano is a zero-config, no skeleton, minimal Hyperf distribution that allows you to quickly build a Hyperf application with just a single PHP file.

Hyperf 273 Jan 4, 2023
Simple, single-file and dependency-free AWS S3 client.

Simple, single-file and dependency-free AWS S3 client. Why? In some scenarios we want the simplest and lightest S3 client possible. For example in Bre

Matthieu Napoli 28 Nov 15, 2022
Laravel Larex lets you translate your whole Laravel application with a single CSV file.

Laravel Larex Laravel Larex lets you translate your whole Laravel application with a single CSV file. You can import translation entries from lang fol

Luca Patera 68 Dec 12, 2022
Exploiting and fixing security vulnerabilities of an old version of E-Class. Project implemented as part of the class YS13 Cyber-Security.

Open eClass 2.3 Development of XSS, CSRF, SQLi, RFI attacks/defences of an older,vulnerable version of eclass. Project implemented as part of the clas

Aristi_Papastavrou 11 Apr 23, 2022
PHP library for generating random avatars based on avataaars

PHP Avataaar PHP library for generating random avatars based on avataaars. Installation Dependencies PHP 8.0 Composer 2.0 Install Install the library

John Ciacia 2 Feb 27, 2022
DTO Generator - PHP library for generating DTO classes

DTO Generator PHP library for generating DTO classes. Installation Use the package manager composer to install micro/dto. composer require micro/dto U

Micro PHP Framework 6 Dec 31, 2022
A comprehensive library for generating differences between two strings in multiple formats (unified, side by side HTML etc). Based on the difflib implementation in Python

PHP Diff Class Introduction A comprehensive library for generating differences between two hashable objects (strings or arrays). Generated differences

Chris Boulton 708 Dec 25, 2022
Allows generate class files parse from json and map json to php object, including multi-level and complex objects;

nixihz/php-object Allows generate class files parse from json and map json to php object, including multi-level and complex objects; Installation You

zhixin 2 Sep 9, 2022
This PHP class uploads files and manipulates images very easily

This PHP class uploads files and manipulates images very easily. It is in fact as much as an image processing class than it is an upload class. Compatible with PHP4, 5 and 7. Supports processing of local files, uploaded files, files sent through XMLHttpRequest.

Colin Verot 795 Dec 21, 2022
Basic class library to read, write and view files using PHP.

File Basic class library to read, write and view files using PHP. Supported PHP Versions Build Status (dev) Main Aim of The Library The main aim of th

WebFiori 2 May 13, 2022
🔨 Prefixes all PHP namespaces in a file/directory to isolate the code bundled in PHARs.

PHP-Scoper PHP-Scoper is a tool which essentially moves any body of code, including all dependencies such as vendor directories, to a new and distinct

Humbug 590 Jan 2, 2023