如何在 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)将在模型层内,而不是控制器内。
您想了解关注点分离和紧耦合
因为你违背了这两个原则。
- https://en.wikipedia.org/wiki/Separation_of_concerns
- What is the difference between loose coupling and tight coupling in the object oriented paradigm?
提问前搜索
您可以尝试搜索 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();
}
}
在 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)将在模型层内,而不是控制器内。
您想了解关注点分离和紧耦合
因为你违背了这两个原则。
- https://en.wikipedia.org/wiki/Separation_of_concerns
- What is the difference between loose coupling and tight coupling in the object oriented paradigm?
提问前搜索
您可以尝试搜索 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();
}
}