How to load a component in console/shell

后端 未结 5 1548
耶瑟儿~
耶瑟儿~ 2020-12-20 17:22

In CakePHP, how do I load a component in a shell?

To use a component in a controller, you include an array of components in a property called $components. That doesn

相关标签:
5条回答
  • 2020-12-20 18:09

    I have some xml utilities that I use across some of my controllers. One of the controller launches a heavy task via the cake console, so that it can quietly run in the background via PHP CLI, while the user's request is immediately completed (once the task done, it will e-mail the results to the user).

    The xml utilities are generic enough to be used in controller and shell, are too specific to the application to warrant them vendor status. The offered solution with the Lib folder does not work as in CakePhp v3 there seems to be no Lib folder.

    After some quite some time spent, I managed to load my controller component to the shell task. Here is how to:

    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 can now be used across my entire shell class.

    0 讨论(0)
  • 2020-12-20 18:10

    //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
        }
    
    }
    
    0 讨论(0)
  • 2020-12-20 18:13

    I assume that you have a component named YourComponent:

    <?php
    
    App::uses('Component', 'Controller');
    
    class YourComponent extends Component {
    
        public function testMe() {
            return 'success';
        }
    }
    

    - with cake 2., you can load your component like this

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

    - with cake 3. you can load your component like this

    <?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();
        }
    }
    
    0 讨论(0)
  • 2020-12-20 18:18

    You simply don't.

    If you think you have to load a component in shell your application architecture is bad designed and should be refactored.

    Technically it is possible but it doesn't make sense and can have pretty nasty side effects. Components are not made to run outside of the scope of a request. A component is thought to run within the scope of a HTTP request and a controller - which is obviously not present in a shell.

    Putting things in the right place

    Why does XML manipulation stuff have to go into a component? This is simply the wrong place. This should go into a class, maybe App\Utility\XmlUtils for example and have no dependencies at all to the request nor controller.

    The logic is properly decoupled then and can be used in other places that need it. Also if you get incoming XML the right place to do this manipulation (by using your utility class) would be inside the model layer, not the controller.

    You want to learn about Separation of Concerns and tight coupling

    Because you've gone just against both principles.

    • https://en.wikipedia.org/wiki/Separation_of_concerns
    • What is the difference between loose coupling and tight coupling in the object oriented paradigm?

    Search before asking

    You could have tried to search via Google or on SO you would have found one of these:

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

    Be aware that some of them might encourage bad practice. I haven't checked them all.

    0 讨论(0)
  • 2020-12-20 18:19

    If you are trying to access a custom XyzComponent from a shell, then you probably have commonly-useful functionality there. The right place for commonly-useful functionality (that is also accessible from shells) is in /Lib/.

    You can just move your old XyzComponent class from /Controller/Component/XyzComponent.php to /Lib/Xyz/Xyz.php. (You should rename your class to remove the "Component" suffix, e.g., "XyzComponent" becomes "Xyz".)

    To access the new location, in your controller, remove 'Xyz' from your class::$components array. At the top of your controller file, add

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

    Now you just need to instantiate the class. In your method you can do $this->Xyz = new Xyz(); Now you're using the same code, but it can also be accessed from your Shell.

    0 讨论(0)
提交回复
热议问题