Search code examples
cakephpcomponents

CAKEPHP. How to invoke a controller method into a controller?


I'm designing an app in which all entities (articles, suppliers, customers, contacts, etc.) have a special object called, well... Object (each row of each table have an object_id column). I thought this because there are a lot common behaviors and relations that can be invoked to all entities in the same way (ex. audit trail, object_id=32665, user_id=312, detail=update_field, bla bla).

So, I want to create a Component with a method (maybe create_new_object) that will call add method from Objects Controller (I altered that method to create a new entity without human interaction, my code below).

Is it a good idea? How can I to call a Controller method from a Component?

Edition

I forgot to put my code, my apologies.

This is my ObjectController

<?php
namespace App\Controller;

use App\Controller\AppController;

class ObjectsController extends AppController
{
   public function add($type = null)
    {       
        if($type)
        {
            $object = $this->Objects->newEntity();
            
            $object = $this->Objects->patchEntity($object, $this->request->getData());
            
            $object->type = $type;
            
            if ($this->Objects->save($object)) {
                $this->Flash->success(__('The object has been saved.'));

                $resultJ = json_encode(array('result' => 'success',
                                             'object_id' => $object->id));
            }
            else
            {
                $resultJ = json_encode(array('result' => 'error',
                                             'message' => 'The object could not be save. Please, try again.'));
            }
        }
        else
        {
            $resultJ = json_encode(array('result' => 'error',
                                         'message' => 'An object type is necessary. Please, try again.o'));
        }
            
        $this->response->type('json');
                
        $this->response->body($resultJ);
                
        return $this->response;
    }
}

I have three important entities...

  1. Articles.
  2. Customers.
  3. Suppliers.

Then, I have another kind of entities (I called them, secondary order), live Contacts, Addresses, Telephones, emails, Cities, Countries, etc.

Each object of each entity (main and secondary) must have an object_id property referred to an Object object () this will be useful for audit trailfor example. So, I'm planning to create a Component, called IdentificationComponent with this content...

public function create_and_object()
{
    bla bla bla... Object->add($type_of_object);
    
    return $generated_object_id;
}

Finally, I want to implement my Component in AppController (with a specific exception for ObjectController). I hope that each entity creates a new Object object when they are created.


Solution

  • Well, finally I created a Component (the CookBook indicates this is the right way to write reusable code for controllers).

    In one hand, this is my Component Code...

    <?php
        namespace App\Controller\Component;
    
        use Cake\Controller\Component;
    
        use App\Controller\ObjectsController;
    
    
        class ObjectToolsComponent extends Component
        {
            public function getNewObjectId($object_type)
            {   
                return (new ObjectsController())->add($object_type);
            }
        }
    ?>
    

    On the other hand, this is the call of Controller Method...

    public function add()
    {
        $article = $this->Articles->newEntity();
        if ($this->request->is('post')) {
            $article = $this->Articles->patchEntity($article, $this->request->getData());
    
    
            /* The call */
            $article->object_id = $this->ObjectTools->getNewObjectId(Inflector::underscore($this->name));
    
            if ($this->Articles->save($article)) {
                $this->Flash->success(__('The article has been saved.'));
    
                return $this->redirect(['action' => 'index']);
            }
            $this->Flash->error(__('The article could not be saved. Please, try again.'));
        }
        $objects = $this->Articles->Objects->find('list', ['limit' => 200]);
        $articleStatuses = $this->Articles->ArticleStatuses->find('list', ['limit' => 200]);
        $suppliers = $this->Articles->Suppliers->find('list', ['limit' => 200]);
        $this->set(compact('article', 'objects', 'articleStatuses', 'suppliers'));
    }
    

    As you can see, I called the getNewObjectId method with controller's name like parameter.

    I hope this will be helpful for somebody in the future.

    Thanks @GregSchmidt and @ndm for your opinions and help.

    Have a nice day.