如何在控制台/ shell中加载组件

MM.*_*MM. 7 cakephp

在CakePHP中,如何在shell中加载组件?

要在控制器中使用组件,请在名为$ components的属性中包含一组组件.这对我的壳牌不起作用.文档中没有提供"即时"加载.

class MakePdfsShell extends Shell {
    public $components = array('Document'); // <- this doesn't work
    public function main()
    {
        $this->Document = $this->Components->load('Document'); // <- this doesnt work either
        $this->Document->generate(); // <- this is what I want to do
    }
    ...
Run Code Online (Sandbox Code Playgroud)

小智 9

我有一些xml实用程序,我在我的一些控制器中使用.其中一个控制器通过蛋糕控制台启动繁重的任务,以便它可以通过PHP CLI在后台安静地运行,同时用户的请求立即完成(任务完成后,它会将结果通过电子邮件发送给用户) .

xml实用程序非常通用,可以在控制器和shell中使用,对于应用程序来说太具体了,无法保证它们的供应商状态.Lib文件夹提供的解决方案不起作用,CakePhp v3因为似乎没有Lib文件夹.

花了一些时间后,我设法将我的控制器组件加载到shell任务.这是如何:

namespace App\Shell;

use Cake\Console\Shell;

use Cake\Core\App;
use Cake\Controller\Component;
use Cake\Controller\ComponentRegistry;
use App\Controller\Component\XmlUtilitiesComponent;   // <- resides in your app's src/Controller/Component folder

class XmlCheckShell extends Shell
{

    public function initialize() {
        $this->Utilities = new XmlUtilitiesComponent(new ComponentRegistry());
    }

...
Run Code Online (Sandbox Code Playgroud)

$this->Utilities 现在可以在我的整个shell类中使用.


bur*_*zum 6

你根本就没有.

如果您认为必须在shell中加载组件,那么您的应用程序架构设计得很糟糕,应该进行重构.

从技术上讲它是可能的,但它没有意义,可以有非常讨厌的副作用.组件不会在请求范围之外运行.组件被认为在HTTP请求和控制器的范围内运行 - 这显然不存在于shell中.

把东西放在正确的地方

为什么XML操作必须进入组件?这只是错误的地方.这应该进入一个类,App\Utility\XmlUtils例如,对请求和控制器都没有依赖性.

逻辑正确地解耦,然后可以在需要它的其他地方使用.此外,如果您获得传入的XML,那么执行此操作的正确位置(通过使用您的实用程序类)将位于模型层内,而不是控制器.

您想了解分离关注和紧密耦合

因为你违背了这两个原则.

在询问前搜索

您可以尝试搜索通过谷歌在SO你会发现其中之一:

请注意,其中一些可能会鼓励不良做法.我还没有检查过它们.

  • -1.坚定的答案,但你听起来像一个混蛋.礼貌和听起来很有帮助,因为你提出你的答案在这种类型的网站上是正确的.不是每个人都像你一样聪明或有经验. (7认同)
  • @burzum 为什么你必须如此居高临下? (2认同)
  • @schnauss我不认为我居高临下。直接,但不居高临下。如果您想进一步讨论这个问题,请在 IRC 或 Slack 上与我联系。ctlockey 太棒了,对正确答案投了反对票,而另一个则因为人身攻击而给出了错误的建议...... (2认同)

MM.*_*MM. 6

如果您尝试从 shell 访问自定义 XyzComponent,那么您可能在那里拥有常用功能。常用功能(也可以从 shell 访问)的正确位置在/Lib/.

您可以将旧的 XyzComponent 类从/Controller/Component/XyzComponent.php/Lib/Xyz/Xyz.php。(您应该重命名您的类以删除“Component”后缀,例如,“XyzComponent”变为“Xyz”。)

要访问新位置,请在控制器中从class::$components阵列中删除“Xyz” 。在控制器文件的顶部,添加

App::uses('Xyz', 'Xyz'); // that's ('ClassName', 'folder_under_/Lib/')
Run Code Online (Sandbox Code Playgroud)

现在你只需要实例化这个类。在您的方法中,您可以$this->Xyz = new Xyz();使用相同的代码,但也可以从您的 Shell 访问它。

  • 这本身,没有额外的建议/预防措施,是一种不好的做法。您应该注意仔细检查代码的使用/与其他组件的互连(以及任何以前的“使用”声明),如果代码在 XYZ 类中的唯一原因只是 CakePHP 的架构,则从类中一起删除代码即便如此,建议使用 require/require_once 加载这些部分。我们有一个内部“将组件代码复制到 lib”的案例,并且浪费了一些不必要的调试时间。 (2认同)

小智 6

我假设您有一个名为YourComponent的组件:

<?php

App::uses('Component', 'Controller');

class YourComponent extends Component {

    public function testMe() {
        return 'success';
    }
}
Run Code Online (Sandbox Code Playgroud)

-使用 cake 2.,你可以像这样加载你的组件

App::uses('ComponentCollection', 'Controller');
App::uses('YourComponent', 'Controller/Component');

class YourShell extends AppShell {

    public function startup() {
        $collection = new ComponentCollection();
        $this->yourComponent = $collection->load('Your');
    }

    public function main() {
        $this->yourComponent->testMe();
    }
}
Run Code Online (Sandbox Code Playgroud)

-使用 cake 3.你可以像这样加载你的组件

<?php

namespace App\Shell;


use App\Controller\Component\YourComponent;
use Cake\Console\Shell;
use Cake\Controller\ComponentRegistry;

class YourShell extends Shell {

    public function initialize() {
        parent::initialize();
        $this->yourComponent = new YourComponent(new ComponentRegistry(), []);
    }

    public function main() {
        $pages = $this->yourComponent->testMe();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 确切的答案,我需要...谢谢 (2认同)