How to call controller within another conroller in cakephp - cakephp

I am using cakephp v2.6 to develop a web app.
Is it possible to call a controller within another controller in CAKEPHP.
Is it correct way for doing the same
In SecondController.php
App::uses('FirstController','Controller');
class SecondController extends AppController
{
$firstcontrollerobject=$this->FirstController;
}
Thanqs

Short answer is Yes, but you shouldn't.
You should use either a component or a model. Or put your action in AppController if you want it to be used by other controllers.
App::uses('FirstController','Controller');
class SecondController extends AppController
{
public function test() {
$FirstController = new FirstController();
$Firstcontroller->action();
}
}

Put PHP code in the Component, if you want to share between several controllers
Components are packages of logic that are shared between controllers. CakePHP comes with a fantastic set of core components you can use to aid in various common tasks. You can also create your own components. If you find yourself wanting to copy and paste things between controllers, you should consider creating your own component to contain the functionality. Creating components keeps controller code clean and allows you to reuse code between projects.
http://book.cakephp.org/2.0/en/controllers/components.html

Related

How to reference an AppController public function in a Plugins AppController in CakePHP 3

Something that should be trivial in IMHO.
I have a public function in my webapp AppController - call it getDbConfig()
I have a plugin and I want to reference the getDbConfig() function that was defined in the system-wide AppController.
Obviously $this->getDbConfig() does not work - since $this refers to the local context - but for the life of me I cannot figure out how to specify the path to public functions in the system AppController in Plugin AppControllers
Doesn't make sense IMHO. A plugin is made to live outside you application. Ideally you could make you plugin public so that other developers could use it inside their application.
If you reference a function that you (and only you) have in your AppControll your plugin is no more a plugin.
I think that this is the typical case where you should create a Component. Put the getDbConfig() inside a Component so that you can call that component both from the Plugin and the AppController
but for the life of me I cannot figure out how to specify the path to public functions in the system AppController in Plugin AppControllers
Read about php OOP namespace basics. You need to import and alias the class. And inherit from your apps AppController. This would make the plugin rely on having the App namespace available, however, at least I have never seen a CakePHP app using another namespace. If it's another one the developer can still fork and use that fork and make the change to it.
Alternatively make the code in question a component or utility class and check in your plugins AppController if that class exists and then instantiate the utility lib it or load the component.
You should pass the function to your plugin/component as a configuration parameter, or the results from getDbConfig() (I assume it won't change much).
So:
class MyComponent extends Component
{
private $dbconfig = null;
public function initialize (array $config)
{
parent::initialize ($config);
if (isset ($config['dbconfig']))
{
$this->dbconfig = $config['dbconfig'];
}
}
}
Then, in your controller:
class MyController extends AppController
{
public function initialize()
{
parent::initialize();
$this->loadComponent ('My', ['dbconfig' => $this->getDbConfig()]);
}
}
If you really must reference a function and call it, use variable functions.

CakePHP how to log API requests globally?

I have an API based on CakePHP, controller with name AccessLogController is responsible for saving access log into the database.
Question is:
What is the best practice for global logging in CakePHP?
I thought that I will call AccessLogController method from inherited AppController in before filter callback like this:
public function beforeFilter() {
$accessLogCtrl = new AccessLogsController();
$accessLogCtrl->add($param1, $param2);
}
But i not sure that is it a good way how to do it..
Many Thanks for any advice..
That's not how you should use controllers, never ever, except maybe in your test suite!
That being said, using AppController::beforeFilter() to globally log controller action requests is generally fine, just make sure that you always invoke parent::beforeFilter() in case you are overriding the filter in an extending controller.
However, you should definitely refactor your logging functionality into either a utility class, a component, a model, or even directly into AppController, depending on how it's actually logging things, and if you need to use it in places other than in AppController.

Components issue on extending custom AppController class

I have a custom structure in my CakePHP app which goes like this:
class AppController extends Controller // default
class ExtendedAppController extends AppController
class ChildController extends ExtendedAppController
The components I declare in ExtendedAppController get erased when I declare components in a ChildController class. I guess I will have this same problem with helpers also. How do I merge the arrays to avoid this?
Cake merges the current controller's variables with only ONE parent class which by default is set in the variable $_mergeParent = 'AppController'; in the core Controller class.
You can override this variable in your ChildController by defining:
class ChildController extends ExtendedAppController {
protected $_mergeParent = 'ExtendedAppController';
}
However, this will ignore all the helpers and components defined in AppController, so copy the components and helpers from your AppController to your ExtendedAppController. This should answer your question I guess as you will be able to use ExtendedAppController's components from your ChildController and other controllers extending AppController will use AppController's components.
It is the way the Controller::_mergeControllerVars() method is written in the core. This is precisely why the book says:
The HtmlHelper, FormHelper, and SessionHelper are available by
default, as is the SessionComponent. But if you choose to define your
own $helpers array in AppController, make sure to include HtmlHelper
and FormHelper if you want them still available by default in your
Controllers.

CakePHP - centralizing controller logic

Using CakePHP, I am finding that I'm duplicating some code between controller actions. I have a dozen or so actions (belonging to various controllers) that all need to run the same query and set() the same 10 variables for the use in a particular layout. They also need to handle any errors in the same way and render an error page.
I know that components are intended to centralize logic used among controllers, but in my case, this logic needs access to the set() and render() methods of the controller. What is the suggested approach to this situation?
Thanks, Brian
Put the logic in your AppController class which your controller should extend from.
Check out the docs: http://book.cakephp.org/view/957/The-App-Controller
Ended up rolling my own sort of business logic layer on this one. Example below. Thoughts/comments welcome.
class MyController extends AppController {
public function my_action() {
// The BLL class is specific for this action and gets the entire
// controller so has access to the set() method as well as components.
$this->Bll = new MyActionLogic($this);
$this->Bll->do_whatever();
}
}

CakePHP: Layout, variables and question

I got layout, nothing special, three columns, just to learn CakePHP. In documentation I found nothing about this case.
I got some statistics in sidebars, si I send them to layout file (default.ctp) cause they are displayed on every page.
I build (thanks to one user here) a component:
class SidebarComponent extends object {
function startup(&$controller) {
$this->controller = $controller; // Stores reference Controller in the component
}
function count_articles() {
$articles = ClassRegistry::init('Articles')->count_articles();
$this->controller->set(compact('articles'));
}
}
Everything is working perfectly. I got question about my technique. I needed to load component method in controller by putting:
$this->Sidebar->count_articles();
So I decided to make it a bit shorter, cause I will have to put it in every controller. So, I created new component's function:
function sidebars($userid) {
return array(
$this->top_articles(),
$this->random_article()
);
}
And I initialize it in controller that way:
$this->Sidebar->sidebars();
Everything is working correctly, I need only advice/feedback if it's good way I do this :)
Thanks for your time.
you don't need to call it explicitly in every controller. component's startup() method is called automatically before every action in the controller that is using your component.
so you can use startup() to get and set your data for views, and if you need some initialization before (like getting reference to controller), put it in component's initialize() method.
If you have sidebars with the same things in them, also sounds like a case for elements as well

Resources