Imagine a typical CakePHP application, in which a Controller passes various bits of data to the View using $this->set in the typical way:
class ThingsController extends AppController {
function test() {
$this->set('someparam', 5);
}
}
If the corresponding View was to define and use a small helper function which outputs some HTML, is there any way to access that variable $some_param from within the function? I would have thought you could just access it as a global variable, but it always come out with the value NULL.
<?php
function helper_function() {
global $someparam;
echo var_dump($someparam); // Just prints NULL
}
?>
<h1>I am a View!</h1>
<?php helper_function(); ?>
To be honest, an even simpler use case is for the helper_function to be able to access things like the $html and $javascript helpers.
In the situation you describe, you're going to be operating on the value after you've set it for the view. You may or may not be changing that value. Either way it could get confusing. It would be clearer - and make life easier when you've forgotten how this app works - to do something like
function test() {
$myVar = 5;
$this->helper_function($myVar);
$this->set('some_param', $myVar);
}
As for accessing the helper functions, you can do this and there are times when there doesn't seem to be an alternative, but it is best avoided wherever possible as it breaks MVC.
This:
<h1>I am a View!</h1>
<?php helper_function(); ?>
just isn't right (assuming you have written the function in the controller). I would be calling that function in the view's controller action and passing the result out as a variable. Just try to remember, use the controller to prepare data for the view. Use the view to display the data.
Why not write your own helper? That would appear to be the way to solve your problems.
The view isn't in the global scope, and $this->set() doesn't make the variable available to the global scope.
If you want the variable available in helper_function(), you should just pass it in as an argument:
function helper_function( $arg )
{
// Do stuff with $arg here
}
Accessing other helpers is something a custom helper can do:
class SomeHelper extends AppHelper
{
// Use the same syntax as the controller to add helpers to your custom helper
var $helpers = array('Html','Javascript','Form');
// Then in the methods, refer to these other helpers thus:
function helper_function( $arg )
{
$out = '';
$out .= $this->Html->div('class','text here');
$this->Javascript->codeBlock("some jQuery here",array('inline'=>false));
$out .= $this->Form->input('Model.fieldName',array('type'=>'hidden','value'=>$arg));
return $out;
}
}
use configure::read and write -
sounds like they are some kind of configuration stuff in your app
this way you can access them anywhere you want
Related
In cakephp 2.x I could define a variable in app model public $someVar = false; and it would be accessible in all models. I could even access/set it from controller for any model: e.g.
$this->User->someVar = true;
Since there is no app model, is there any way to achieve the same thing in cake 3. I have global event listeners set up as in this answer
Cakephp 3 callbacks, behaviors for all models
So, the purpose is to have a variable, which will be accessible in those global listeners, all models' callbacks as well as from controller through model's object - similar to cake 2: for app model's callbacks, all models' callbacks and from controller respectively.
edit: would not prefer to use Configure
Thanks
It looks like I figured it out
Create a Behavior and load it in initialize global event. similar to example here
Cakephp 3 callbacks, behaviors for all models
This way it will be available in all models and callbacks. Create a variable in that behavior public $someVar = null. However accessing directly the behavior's variable is not possible (as it is treated as an association)
https://github.com/cakephp/cakephp/issues/9153
So, you can define method to set/get the value
// inside Behavior
public function setSomeVar($val = null) {
if ($val === null) {
return $val;
}
return $this->myVar = $val;
}
To access/modify that variable
// inside callbacks/event listeners
$event->subject()->setSomeVar(); // to get
$event->subject()->setSomeVar('smth'); // to set
// from controller
$this->Users->setSomeVar(); // to get
$this->Users->setSomeVar('smth'); // to set
I am using Cakephp 2.3 , i want to perform lots of common calculation in my several controllers. so i write those functions in my appcontroller and i cached some datas..
but what happens is my appController will become fatty.. so i create some component to perform these actions.. i dont know my approach is right or not..? please suggest..
i want to use cache in my component, i tried this code. but nothing is cached..
public $helpers =array('Cache');
and
$result = Cache::read('fm_data', 'long');
if (!$result) {
$result =
$this->TFmStation->find('all',array('contain'=>array('TLocation',
'TLanguage','TMediaOrg','TContactPerson',
'TAddress','TFmProgram'=>array('TTargetGroup'))));
Cache::write('fm_data', $result, 'long');
}
return $result;
please help me to how to use cache in component
how to effectively use component class in cakephp in the case of more common functions in the application.. when i write these functions in appController it load all the functions so according to memory prespective, how to effectively use component
Model TFmStation is best place to have the above logic. Components are there for generic functionality like UploadComponent, EmailComponent, RecaptchaComponent etc. If your logic part have something to do with model, then it should go into that model.
A Model can be called from AppController.php in a similar fashion as you calling your Component.
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.
In my controller, I would like to set some values and have them exist (or live) throughout the different views in my app.
I read somewhere that I need to use beforeFilter function, but I am not sure if that is correct and how I go about doing that.
So in my controller I want to have
public function page1() {
$this->Model->setId('123');
}
public function page2() {
$this->Model->getId(); // would able to get the Id that was set from page1 function
$this->Model->setName('Bob');
}
public function page3() {
$this->Model->getId();
$this->Model->getName();
}
Let me know if you have questions.
To have this kind of "persistence" throughout the views, I guess the most simple approach is sessions.
Note that with the code you provided (I know is not a working example), you want the variable to be persistent inside a model, but that same model wont be maintained between actions of the same controller (or other controller for that matter).
You have to set that variable in sessions and retrieve it when you want to use it, or in the database and create methods in the model to get the last inserted id, for example.
So your code would be like
public function page1() {
$this->Session->write('id', '123');
}
public function page2() {
$this->Session->read('id');
$this->Session->write('name', 'Bob');
}
public function page3() {
$this->Session->read('id');
$this->Session->read('name');
}
Have a single model method that returns all your data in an array like
return array('varName' => $value, 'varName2' => $value2);
You can then call this model method from the controllers before filter and simply do
$this->set(ClassRegistry::init('MyModel')->commonViewVars());
If you would describe for what you think you need to do that I could give you a better advice like using requestAction() for example, this might be another option depending on what you're trying to do.
Depending on what data you want to pass to every page you should really consider to cache it. If its a menu for example cache it "forever" and just update the cache when the menu changes.
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();