I know how to pass variable from controller into a view:
$this->render('view_name', array('variable_name'=>'variable_value'));
however I'd like to pass some variables to layout. The only connection between controller and layout seems to be the public $layout attribute in controller class, like this:
public $layout='//layouts/column2';
However, I do not see a way to pass a variable to it?
Alternatively, you could add a property in the Controller such as
class SiteController extends CController {
public $myvar;
//...
And then output it in the layout (//layouts/column2)
echo isset($this->myvar) ? $this->myvar : '';
It doesn't really seem to be set up to do that easily from what I can tell, so if you are relying on it to pass a lot of data, you might want to think of a different way to set up your application.
A couple ways that you could do it are to use the Yii params via
Yii::app()->params['myvar'] = $mixed;
which you can set in the controller and access in the layout. Otherwise you can use regular PHP global vars, with all the issues that approach entails.
In your controller you would do something like:
global $testvar;
$testvar = 'hello';
and in the layout:
echo $GLOBALS['testvar'];
(Even if it's not in a function, you still need to retrieve it via GLOBALS.)
You could pass an object this way for more structured data, but you are still using a global var. Another, possibly even less desirable method, would be via a session var, e.g., Yii::app()->session['myvar'] or a Yii "flash message".
in controller pass the variable, then in VIEW (not layout yet)
create
$this->params['myvar'] = 'hello';
Now in layout you can access whole array with just
echo $this->params['myvar'];
Hope this helps you.
After sets of debugging in Yii2 I found out that the only variables (excluding global variables) that are accessible inside of a layout file are _file_ (path to current layout file) and _params_ (an array containing variable content that is a HTML output bufferized from a file passed for rendering from a controller).
Except answers provided by #ldg (which I consider as most useful and informative, but resource spending) and #Petra Barus.
I also came out with a good solution of dividing layout into explicit files and calling them inside of a rendered file:
echo $this->renderPhpFile(Yii::getAlias('#app/views/layouts/somelayout.php'), [
'var' => $variableThatIsAccessibleInRenderedFile,
]);
From your controller you can do something like this:
$this->render('/mail/registration',array('url'=>$url, 'description'=>'some description'));
and access the variables from your view like this:
<h3><?php echo $url; ?></h3>
and here is your answer; you can access these same variables from the layout like this:
<h3><?php echo $data['url']; ?></h3>
Related
I'm newbie in Codeigniter.
I have a table in my database called 'sysConfig' with columns such as title, money unit, license key and ... .
I want to get first line of this table record (it has only one record) to a global variable called '$Config' that it available in all views (If it was possible available in models and controllers).
Edit:
I can select any data from database and I dont have any problem with this. I want to select data on table sysConfig in a variable called $Config and access ti it directly like this <?php echo $Config['Title']; ?> or <?php echo $Config -> Title; ?>.
The best way to do this, if these are system config items is to load them in your own config file.
Create your own config file. Load it manually or in autoload.
$this->config->load('filename');
Access items in it like this
$this->config->item('item_name');
You can also set dynamicallly the config items using this:
$this->config->set_item('item_name', 'item_value');
You can read about it here in the docs: http://www.codeigniter.com/user_guide/libraries/config.html
Alternatively, if this is user based, collect the information into the current session and access that. Although accessing session variables in models or libraries is not a good idea. You should pass the required items as function arguments.
One approach is to add a property to any controller that will need sysConfig data. The name of the variable should not be $config because CI already uses that symbol - it is defined and set by the Config class. So for this answer I will use $sysConfig.
class Some_controller extends CI_Controller
{
protected $sysConfig; //class property with scope to this controller
public function __construct()
{
parent :: __construct();
$this->load->model('sysConfig_model');
}
sysConfig_model (not shown) manages the table you seem to have established. I'm making up functions for that model since you don't show us any code. The model function get($id) retrieves the "user" you want based on $id and returns the data in an array. (The setting of $id with a valid value is not shown.)
The controller can make use of the property as needed by way of $this->sysConfig as in this admittedly trivial made-up controller function.
The class definition continues with...
public function format_title()
{
if(isset($this->sysConfig){
$this->sysConfig['suckup'] = "the most highly regarded "
. $this->sysConfig['title']
. " in the world visit our site!";
}
}
Actually assigning a value to $this->sysConfig happens in this next bit of code. In this example, the controller's index() function can receive an argument that is the "ID" of the user we want to get from the database.
public function index($id = NULL)
{
//assign data to the class property $sysConfig from the model
$this->sysConfig = $this->sysConfig_model->get($id);
The property can be passed to a view quite easily. First we do some sucking up.
$this->format_title();
$data['userStuff'] = $this->sysConfig;
$this->load->view('some_view', $data);
} //end of index()
} //end of class Some_controller
some_view.php
<div>
<h4>Welcome <?php echo $userStuff['firstName']. " " . $userStuff['lastName']; ?></h4>
<p>I cannot say how swell it is to have <?php echo $userStuff['suckup']; ?></p>
</div>
The idea of a "global" is really contrary to OOP methodology in PHP - or any other OOP language.
Well, this is a tricky one, and I'm not really sure it's not breaking the MVC model.
I'm loading some data into the controller, retrieved from the model. I'm passing this object to the view almost in every action. I'm processing this data from a helper and I'm passing the object as an argument:
controller:
$this->('section', $section);
helper:
<h3><?php echo $parser->section_name($section); ?></h3>
However, I think it would be way better if I could pass that $section object as a private variable inside the parser helper. I could do this in the first line of each view:
$parser->section_object = $section;
And each parser method will look something like
function section_name(){
return $this->section_object['Section']['name'];
}
The question is: is there a way to automatizate this from the controller? Because the controller can't access the helper, I tried creating the helper from the controller and setting the local variable there:
function beforeFilter(){
$section = $this->Section->getOne();
App::import('Helper', 'Parser');
$ParserHelper = new ParserHelper();
$ParserHelper->section_object = $section;
$this->set('parser', $ParserHelper);
}
However, if the helper includes some other helpers, they won't be loaded and the helper will trigger a lot of errors.
Thanks.
You have to manually create the helpers used by your helper. For example, if your helper uses the HtmlHelper, you have to do something like:
App::import('Helper', 'Html');
$ParserHelper->Html = new HtmlHelper();
I have a view helper that manages generating thumbnails for images. The images are stored using a unique ID and then linked to a file resource in the database.
I am trying to find out if it is possible for the view helper that generates these images to access the model or controller directly, as it is not possible to load the image data at any other point in the controller work flow.
I know this is a bit of a hack really, but it is easier than trying to rebuild the entire data management stack above the view.
If you had set the data in the model or controller you could access it. So you'd have to think ahead in the controller. As you said you can't load it in the controller, perhaps you need to write a specific controller function, which you can call from the view using $this->requestAction() and pass in the image name or similar as a parameter.
The only disadvantage of this is using requestAction() is frowned upon, as it initiates an entirely new dispatch cycle, which can slow down your app a bit.
The other option, which may work is creating a dynamic element and passing in a parameter into the element and have it create the image for you. Although I'm not too sure how this would work in practise.
How are you generating the thumbnails using the helper in the view if you aren't passing data into it from a controller or model? I mean if it was me, I would be setting the 'database resource' in the controller, and passing it to the view that way, then having the helper deal with it in the view. That way you could bypass this issue entirely :)
$this->params['controller'] will return what you want.
According to the ... you can put this code in a view.ctp file then open the URL to render the debug info:
$cn = get_class($this);
$cm = get_class_methods($cn);
print_r($cm);
die();
You could write a helper and build in a static function setController() and pass the reference in through as a parameter and then store it in a static variable in your helper class:
class FancyHelper extends FormHelper {
static $controller;
public static function setController($controller) {
self::$controller = $controller;
}
... more stuff
}
Then in your Controller class you could import the FancyHelper class and make the static assignment in the beforeFilter function:
App::uses('FancyHelper', 'View/Helper');
class FancyController extends AppController {
public $helpers = array('Fancy');
function beforeFilter() {
FancyHelper::setController($this);
}
... more stuff
}
And then you could access the controller from other public functions inside FancyHelper using self::$controller.
You can check the code(line ☛366 and
line ☛379) of the FormHelper, try with:
echo $this->request->params['controller'];
echo Inflector::underscore($this->viewPath);
I have a controller with different methods, but they all have to set a variable containing a list of items to be shown in a box in the view, I extract data from the DB and set $data['categories'].
Can I set it once and have it visible by all methods?
In addition to this, if you are only using $this->data to get the values into your views, instead of doing:
$this->data->something = 'whatever';
Then doing
$this->load->view('something', $this->data);
You can instead set it with:
$this->load->vars('something', 'whatever');
Then later on use the normal localized $data array (or whatever you like) as the variable will be globally available to all loaded view files.
I'm not suggesting either way is better, just letting you know how else it could be done. I personally use a mix of these methods. :-)
make it a property of the class
class Controller {
protected $data;
and use '$this' to access in in your methods:
class Controller {
function foo() {
$this->data etc...
I have a controller which has several methods which should all share common informations. Let's say my URI format is like this:
http://server/users/id/admin/index
http://server/users/id/admin/new
http://server/users/id/admin/list
http://server/users/id/admin/delete
I need to retrieve some informations from the database for id and have them available for all methods instead of writing a line in each of them to call the model. How can I do this?
class users extends Controller {
private $mydata = array();
function users()
{
parent::Controller();
....
$this->mydata = $this->model->get_stuff($this->uri->segment(2));
}
function index()
{
$this->mydata; //hello data!
}
Here I simply hardcoded the array (which probably is a really bad idea). Nevertheless you can store the data in a codeigniter session if you need to. Codeigniter can store this data in a cookie (if it's total is less than 4kb) otherwise you can store bigger blobs of data in the database (see the docs on how to do this).
See: http://codeigniter.com/user_guide/libraries/sessions.html
Subsection: Saving Session Data to a Database
Here's some session exercise:
$this->session->set_userdata('mydata', $mydata);
....
$mydata = $this->session->userdata('mydata');
If this cannot be solved from CodeIgniters Hook mechanism, you could override the constructor method in your controller and call your own. Judging from their SVN repository you'd probably would do something like
class YourController extends Controller
{
function YourController()
{
parent::Controller();
$this->_preDispatch();
}
function _preDispatch()
{
// any code you want to run before the controller action is called
}
Might be that the call to preDispatch has to be before the call to parent. Just try it and see if it works. I didnt know they still use PHP4 syntax. Ugh :(
Based on your url structure, and the fact that codeignitor uses a MVC pattern, I'm assuming you're using mod_rewrite to format the url path into a query string for index.php. If this is the case, the value of "id" should be available at $_REQUEST['id'] at any point in the execution of the script...