In CakePHP, what does parent::initialize() do? - cakephp

I see the line
parent::initialize();
in all the preloaded methods in CakePHP 3.x and in all the 3.x documentation.
Removing the line, or forgetting to add the line to new methods, doesn't seem to have any negative effects.
Which begs the question, what does it do?
Apologies is this is a totally noob question..

It is simple OOP. It calls the parent method of the same name.
Aclass {
public function foo() { echo 'bar'; };
}
Bclass extends Aclass {
public function foo() { parent::foo(); echo 'foobar'; }
}
Just try it and remove the parent call, you'll see what it does. The parents usually should be called, especially in methods like the initialize() callbacks. However, when to call or not to call them is a decision you have to make. It depends on if you want or need to call the parent methods logic or not. This is called "overloading".
This allows you to add functionality before or after the parent call of the method, which is a pretty common thing. I recommend you to read the OOP chapter of the php manual.

In your Controller’s initialize() method you can define any components you want loaded, and any
configuration data for them:
public function initialize()
{
parent::initialize();
$this->loadComponent('Security');
$this->loadComponent('Paginator');
$this->loadComponent('RequestHandler');
}

It is exactly what it says your running a method from the parent class. So the for example.
class AppController extends Controller {
public function initialize() {
echo 'hello world';
// do more sh*t
}
}
class UsersController extends AppController {
public function initialize() {
parent::initialize(); // this will run the method initialize from app controller that will echo 'hello world'
// do more sh*t
}
}

It's not doing anything when you remove it because there's nothing inside the parent initialize function, but it's there just in case you want to extend functionality from your parent controller to a child controller. For example:
In AppController there's a beforeFilter function that defines what I want to run before the page loads. Let's say I want a function to run on every single page - a simple redirect function if the user isn't logged in:
if (!$this->Auth->user()) {
$this->redirect('Users/login');
}
Instead of putting this in the beforeFilter on every single controller I go to, I can put it inside the beforeFilter of AppController.
My other controllers, like UsersController, extend from AppController:
class UsersController extends AppController {
So in the beforeFilter in my UsersController I can do:
public function beforeFilter(Event $event) {
parent::beforeFilter($event);
}
Now I inherit this redirect behavior from the parent controller(AppController), so that same code also runs in my child controller (UsersController) - and no matter what controller users go to they get redirected to the login page if they're not logged in.
This works the same way with parent::initialize(); you're inheriting what functionality exists inside the initialize function in the parent controller. This is just functionality included to eliminate redundant code.
So basically, if you see code that you're using on every single page, find a way to make it a bit object oriented by removing it and placing it in a file that your code can inherit from. It's along the same vein of moving the header and footer code out of HTML documents and placing them in their own php files so you can make a change in one area and have all affected derivatives updated, rather than editing the header and footer in every HTML document.

Related

CakePHP index() vs view() and URL components

I am confused about the distinction and treatment of the index() and view() functions inside CakePHP 2.4.
Specifically, I am trying to modify a 3rd party API authored in CakePHP 2.4
Consider this Controller:
class EventsController extends AppController {
<snip>
public function index() {
if ($this->request->params['named']) {
$conditions = $this->request->params['named'];
} else {
$conditions = array();
}
}
This allows me to construct a URL like http://myserver/api/events/index/StartTime >=:12/EndTime <=15.json and the StartTime and EndTime get passed into conditions when I do a find.
That's great.
Now that same Controller has this additional function:
public function view($id) {
}
This function seems to be called when I invoke a url like http://myserver/api/events/1234.json
I am trying to extend view with more parameters, just like index. For example, I'd like to invoke:
http://myserver/api/events/1234/MonitorId =:3.json and MonitorId =:3 gets passed as a parameter to handle in view. I don't want to add these into the function definitions - it can be anything.
If I try and do this, I get a "Controller" not found, but this same approach works in index()
Can someone help me achieve my goal and help explain what is going on?
(IF it helps, the full code of the controller is here)
As I can see, you are using CakePHP RESTful routing routes.php
Here,
index is used for listing all the resources e.g. all blog posts. URL /events/index is getting mapped to index method in controller automagically.
view is used for showing a specific resource which can be identified by some unique identifier like id or uuid e.g. specific blog post. URL /events/<some_identifier> gets mapped to view method
What you need to do is modify view definition to read all query string parameters that you pass in URL and call Model accordingly. By default. routes parses the first string after events in URL to resource ID and passes it as first argument to view method in controller. This is scaffolded code.
You can use named parameters $this->request->params['named'] in your view definition and construct your queries. No hard-coding.
It turns out that I need to explicitly call the view action to pass it more parameters.
So api/events/view/218245/AlarmFrames >=: 80.json works as intended and then I can get the parameters with $conditions = $this->request->params['named'];

Can I use AppController and ModuleController at a same time?

I have a table called settings. I created a controller for this as settings controller.
<?php
class SettingsController extends AppController {
....
....
}
?>
By default I have app controller
<?php
class AppController extends Controller {
....
....
}
?>
In app controller I put some logic in beforeFilter method which is common for all controllers, Now I have to user some logics in beforeFilter in settings controller. But, I am unable to do so.. If I put beforeFilter in settings controller it doesn't access logics from appController before filetr,
Can anyone advice regarding this?
Can anyone advice regarding this?
Yes, learn about the basics of OOP in php first before trying to use an OOP based framework. Especially pay attention to the overloading section for what you want to do.
SettingsController already inherits the code from AppController because it extends it. The examples in the manual of the framework should already show you this:
public function beforeFilter() {
// Your code here
parent::beforeFilter();
// Your code here
}
You need to call the parent method.

In CakePHP, how do I call an AppController method from a helper?

Follow up question to: In CakePHP, where would I put a method that performs a check on the Session User?
Background: In my previous question, I was informed that the correct place to place a method such as levelCheck() which performs a semi-complicated evaluation of a user's level, and is needed in practically all my controllers, is the AppController.
Now, this method is also incredibly useful for the way I design menu layouts and other view devices. For that reason, I would like to create a helper that can make use of that method.
Problem: I recognize that it's generally frowned upon to call a controller method from the view... however there is no viable way for me to pass data to replicate the function of this method, nor do I want to replicate the method in two places (violating DRY methodology).
Question: How then do I call this method from a helper, or is there a better way to provide use of this method in the view/elements?
Put the method in AppController, also - set a variable that will save the result.
In the beforeRender callback, set the result as a viewVar.
some code:
// AppController
class AppController extends Controller
{
$levelCheckResult = null;
function levelCheck(){
$this->levelCheckResult = true/false;
}
function beforeRender(){
$this->set('levelCheckResult', $this->levelCheckResult);
}
}
that's it, now you can access it in the view.
edit
create a public function in the app_controller, and in the beforeRender(), send the app_controller itself, to the view.
class AppController extends Controller
{
function levelCheck(){
....
}
function beforeRender(){
$this->set('TheApp', $this);
}
}
// in the view
$TheApp::levelCheck();
However, please consider again the design. this kind of manipulation is strongly suggest that you should change some stuff there.
In short - the view is still backend execution of the program and not the client side, so in definition - it should and can be controlled, from the controller...
The solution I ended up using was to move the method to a component (CurrentUserComponent).
From there, it was as simple as calling the component in the head of my helper...
App::uses('CurrentUserComponent', 'Controller/Component');
And referencing the component's static method:
CurrentUserComponent::levelCheck(x,y,z);
I don't think this is entirely within the intention of the MVC pattern, but it doesn't pervert it horribly, and allows access to the method from anywhere in the application.

temporarily disable controller redirect

I'm trying to re-use a plugin's controller method for adding a user (the plugin is usermgmt, a purchased plugin). The plugin's method does everything I need, however it finishes by doing a redirect to another page.
I don't want to modify the plugin code, and I am wondering if it is possible to temporarily disable the Controller:redirect method
class MyController extends AppController{
function signUpUser(){
//populate $this->request->data to be what plugin controller method is looking for
//temporarily disable Controller::redirect
//make call to plugin's controller method
$usersController = new UsersController();
$usersController->constructClasses();
$usersController->addUser();
//re-enable Controller::redirect
//Do my own redirect
$this->redirect('/welcome');
}
}
You are not supposed to use controllers that way, there's probably a model or component which you could use instead. Extending the users controller may also be an option. Anyways, since you said you've bought it, why don't you contact the support, they should know best how their stuff works?
That being said, let me answer the actual question. In order to be able to disable redirection via your controller, you would have to override the Controller::redirect() method and implement some logic that allows you to disable the functionality.
Here's an untested example, it uses a property which defines whether redirects are enabled:
public $redirectEnabled = true;
public function redirect($url, $status = null, $exit = true) {
if($this->redirectEnabled) {
parent::redirect($url, $status, $exit);
}
}
This should be pretty much self-explantory.
In your controller you could set $this->redirectEnabled to true/false to enable/disable the redirect functionality.

How to use a helper function in a controller?

I wrote some function in app_helper file. now i need to call that function in my controller
how i can do this in CAKEPHP
You can't.*
If your functions are so universal as to be used outside of views, create them in bootstrap.php or make a custom library/class in the libs/ directory.
* You can load anything anywhere using App::import('Helper', 'NameOfHelper') or ClassRegistry::init, but you really shouldn't. The point of MVC separation is to keep your app well organized.
App::uses('HtmlHelper', 'View/Helper');
$yourTmpHtmlHelper = new HtmlHelper(new View());
Is finally the version which works with Cakephp 2.3
You can use the helper in Controller as bellow
App::uses('YourHelper', 'View/Helper');
class yourController extends AppController {
public function index(){
$yourHelper = new YourHelper(new View());
$yourHelper->yourMethod();
}
}
App::import('Helper', 'Forum.Common');
$commonHelper = new CommonHelper(new View())
If you want to use some common functions in all of your controllers like the helper does for views,
you must use Components
http://book.cakephp.org/2.0/en/controllers/components.html
rather using App::import('Helper', 'NameOfHelper'), this keeps the MVC standard correct and your app well organized.
you can call helper function this way. suppose you helper is DemoHelp
and call to helper function call_function() then you can use this.
App::import('Helper', 'DemoHelp');
$DemoHelp = new DemoHelpHelper();
$DemoHelp->call_function()
You can use Component, they are stored in Controller/Component/
For example if you have Controller/Component/SomeComponent.php
and want call it on the fly in single action inside controller:
$this->SomeComponent = $this->Components->load('SomeComponent');
$this->SomeComponent->someFunction();

Resources