如何在自定义安装程序插件中卸载自动加载
P粉466909449
P粉466909449 2023-07-31 10:06:51
[PHP讨论组]
<p>我一直在尝试为我的Composer包编写自定义安装程序,但无法使其工作。我现在需要的是:</p><p><ul><li>我希望将我的包安装在根目录下。我的包名是rootdata21/hati,所以我将hati文件夹移动到项目的根目录中。</li><li>现在,我通过向composer.json文件的autoload psr4属性添加了一个条目来更新它,如下所示:{ "autoload": { "psr-4": { "hati": "hati/" } } }</li></ul></p><p>但是我实际上不知道如何让composer重新生成自动加载器,以反映composer.json文件中的这个新的autoload条目。以下是我的Installer类。</p><p><br /></p> <pre class="brush:php;toolbar:false;">&lt;?php namespace hatiinstaller; use ComposerInstallerLibraryInstaller; use ComposerIOIOInterface; use ComposerPackagePackageInterface; use ComposerPartialComposer; use ComposerRepositoryInstalledRepositoryInterface; use ComposerScriptScriptEvents; use haticonfigConfigWriter; use ReactPromisePromiseInterface; class Installer extends LibraryInstaller { private string $root; private string $hatiDir; protected $composer; public function __construct(IOInterface $io, PartialComposer $composer, $root) { $this -&gt; composer = $composer; $this -&gt; root = $root . DIRECTORY_SEPARATOR; $this -&gt; hatiDir = $root . DIRECTORY_SEPARATOR . 'hati' . DIRECTORY_SEPARATOR; parent::__construct($io, $composer); } public function getInstallPath(PackageInterface $package): string { return 'rootdata21'; } public function install(InstalledRepositoryInterface $repo, PackageInterface $package): ?PromiseInterface { if (file_exists($this -&gt; hatiDir)) { $choice = $this -&gt; io -&gt; ask('Existing hati folder found. Do you want to delete it? [y/n]: ', 'n'); if ($choice === 'y') { self::rmdir($this -&gt; hatiDir); } else { $this -&gt; io -&gt; critical('Hati installation has been cancelled. Please delete hati folder manually.'); return null; } } return parent::install($repo, $package)-&gt;then(function () { // Move hati folder to project root directory $old = $this -&gt; root . 'rootdata21'. DIRECTORY_SEPARATOR .'hati'; rename($old, $this -&gt; hatiDir); // delete the rootdata21 folder self::rmdir($this -&gt; root . 'rootdata21'); // generate/update the hati.json file on the project root directory $createNewConfig = true; if (file_exists($this -&gt; root . 'hati.json')) { while(true) { $ans = $this -&gt; io -&gt; ask('Existing hati.json found. Do you want to merge it with new config? [y/n]: '); if ($ans !== 'y' &amp;&amp; $ans !== 'n') continue; break; } $createNewConfig = $ans == 'n'; } require_once "{$this -&gt; hatiDir}config" . DIRECTORY_SEPARATOR . "ConfigWriter.php"; $result = ConfigWriter::write($this-&gt;root, $createNewConfig); // show the result to the user if ($result['success']) { $this -&gt; io -&gt; info($result['msg']); $welcomeFile = $this -&gt; hatiDir . 'page/welcome.txt'; if (file_exists($welcomeFile)) include($welcomeFile); } else { $this -&gt; io -&gt; error($result['msg']); } $this -&gt; dumpAutoload(); }); } public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target) { return parent::update($repo, $initial, $target) -&gt; then(function () { require_once "{$this -&gt; hatiDir}config" . DIRECTORY_SEPARATOR . "ConfigWriter.php"; $result = ConfigWriter::write($this-&gt;root); // show the result to the user if ($result['success']) { $this -&gt; io -&gt; info('Hati has been updated successfully'); } else { $this -&gt; io -&gt; error($result['msg']); } }); } public function supports($packageType): bool { return 'hati-installer' === $packageType; } private function dumpAutoload(): void { $composerJsonPath = $this -&gt; root . 'composer.json'; $composerJson = json_decode(file_get_contents($composerJsonPath), true); $composerJson['autoload']['psr-4']['hati\'] = 'hati/'; file_put_contents($composerJsonPath, json_encode($composerJson, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); // Regenerate the Composer autoload files to include your classes $this -&gt; composer -&gt; getEventDispatcher() -&gt; dispatchScript(ScriptEvents::POST_AUTOLOAD_DUMP); } public static function rmdir($dir): bool { if (!file_exists($dir)) return true; if (!is_dir($dir)) return unlink($dir); foreach (scandir($dir) as $item) { if ($item == '.' || $item == '..') continue; if (!self::rmdir($dir . DIRECTORY_SEPARATOR . $item)) return false; } return rmdir($dir); } }</pre> <p><br /></p>
P粉466909449
P粉466909449

全部回复(1)
P粉068510991

我已经成功实现了我想要做的事情。所以在这里,我将解释我所寻求的帮助。

通常情况下,如果不使用任何自定义的安装插件,Composer会将我的包安装在名为"rootdata21/hati"的vendor目录下。但由于某些原因,我的整个包源代码需要位于项目根目录下。而且我也不希望有名为rootdata21的父文件夹。

因此,我为此编写了一个插件。该插件将"rootdata21"作为安装路径返回。它将我的包放在了根目录下,但是文件夹结构现在变成了"rootdata21/hati"。因此,我不得不重写安装方法来修改它。然而,即使我通过从"rootdata21/hati"复制/重命名/删除文件夹来获得我想要的文件夹位置和结构,自动加载器对我重新定位的源代码仍然无效。然后,我不得不手动更新composer.json文件来重新生成自动加载器,这与拥有安装程序的目的相悖。这就是我想要实现的,即在将我的包文件夹移动到项目根目录后,自动加载器仍然能够正常工作。

这是我最终更新的安装程序代码,它按照我想要的方式工作。


public function getInstallPath(PackageInterface $package): string { return 'hati'; }
public function install(InstalledRepositoryInterface $repo, PackageInterface $package): ?PromiseInterface {

    // Setting custom psr-4 entry for hati folder being on project root
    $autoload = $package -> getAutoload();
    if (isset($autoload['psr-4'])) {
        $customPSR4 = ['hati\\' => '/',];
        $autoload['psr-4'] = array_merge($autoload['psr-4'], $customPSR4);

        // Let the composer know about this
        $package -> setAutoload($autoload);
    }

    return parent::install($repo, $package) -> then(function () {

        // Manipulate the hati/hati folder to hati on project root
        self::copy($this -> root . 'hati' . DIRECTORY_SEPARATOR . 'hati', $this -> root . '_temp');
        self::rmdir($this -> root . 'hati');
        rename($this -> root . '_temp',$this -> root . 'hati');

        // rest of the installation code goes here...
    });
}

在所有这些操作之后,vendor/composer/autoload_psr4.php文件正确地设置了类路径,您可以在截图中看到。

我不得不将"hati"作为安装路径返回,因为如果返回"rootdata21"并使用上面的安装代码,将会得到以下的autoload_psr4.php记录,而这并不能正常工作。


'hati\\' => array($baseDir . '/rootdata') 
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号