如何在 console/shell 中加载组件

How to load a component in console/shell

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

要在控制器中使用组件,您需要在名为 $components 的 属性 中包含一个组件数组。这对我的 Shell 不起作用。文档中建议的 "on-the-fly" 加载也没有。

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
    }
    ...

你根本不知道。

如果您认为必须在 shell 中加载组件,则您的应用程序架构设计不佳,应该进行重构。

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

把东西放在正确的地方

为什么 XML 操作内容必须进入组件?这简直就是错误的地方。这应该进入 class,例如 App\Utility\XmlUtils,并且对请求和控制器完全 没有 依赖性。

这样逻辑就很好的解耦了,可以用在其他需要的地方。此外,如果你收到传入 XML 进行此操作的正确位置(通过使用你的实用程序 class)将在模型层内,而不是控制器内。

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

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

提问前搜索

您可以尝试搜索 via Google or on SO 您会找到其中之一:

  • using components in Cakephp 2+ Shell
  • CakePHP using Email component from Shell cronjob
  • Using a plugin component from shell class in cakephp 2.0.2
  • ...

请注意,其中一些可能会鼓励不良做法。我没有全部检查过。

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

您只需将旧的 XyzComponent class 从 /Controller/Component/XyzComponent.php 移动到 /Lib/Xyz/Xyz.php。 (您应该重命名 class 以删除 "Component" 后缀,例如,"XyzComponent" 变为 "Xyz"。)

要访问新位置,请在您的控制器中从 class::$components 数组中删除 'Xyz'。在控制器文件的顶部,添加

App::uses('Xyz', 'Xyz'); // that's ('ClassName', 'folder_under_/Lib/')

现在您只需要实例化class。在您的方法中,您可以执行 $this->Xyz = new Xyz(); 现在您使用的是相同的代码,但也可以从 Shell.

访问它

我在一些控制器上使用了一些 xml 实用程序。其中一个controller通过cake控制台启动一个繁重的任务,这样它就可以在后台通过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());
    }

...

$this->Utilities 现在可以用于我的整个 shell class.

//TestShell.php

class TestShell extends AppShell{

    public function test(){
        //to load a component in dis function
     App::import('Component', 'CsvImporter');
     $CsvImporter = new CsvImporterComponent();
     $data = $CsvImporter->get();
    }

}

//CsvImporterComponent.php

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

class CsvImporterComponent extends Component {

    function get(){
    //your code
    }

}

我假设您有一个名为 YourComponent:

的组件
<?php

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

class YourComponent extends Component {

    public function testMe() {
        return 'success';
    }
}

- 对于蛋糕 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();
    }
}

- 蛋糕 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();
    }
}