I'am using a codeigniter 2.x. What i need is to insert a values into an array of config/template.php from inside of a view file /views/home.php.
I've created a custom config file application/config/template.php:
$config['site_name'] = "Sitename";
$config['site_lang'] = "En-en";
$config['page_name'] = "Pagename";
$config['css_page'] = "default";
$config['alias'] = "";
$config['head_meta'] = array(
'description' => 'description',
'keywords' => 'meta, keywords',
'stylesheets' => array(
'template.css'
),
'scripts' => array(
'jquery.js',
'template.js'
),
'charset' => 'UTF-8'
);
$config['sidebars'] = array();
Then, i use application/views/template/template.php as my main HTML layout, where at the beginning I include a file application/views/template/includes/inc-tpl-cfg.php which globalize my configurations for a template into an one file with arrays, so i could access them a little bit easier. Here is the content of that inc-tpl-cfg.php:
<?php
// No direct acces to this file
if (!defined('BASEPATH')) exit('No direct script access allowed');
/* Template configuration needs to be defined to make them accessible in the whole template */
$cfg_template = array(
'sitename' => $this->config->item('site_name'),
'sitelang' => $this->config->item('site_lang'),
'pagename' => $this->config->item('page_name'),
'csspage' => $this->config->item('css_page'),
'charset' => $this->config->item('charset','head_meta'),
'description' => $this->config->item('description','head_meta'),
'keywords' => $this->config->item('keywords','head_meta'),
'stylesheets' => $this->config->item('stylesheets','head_meta'),
'scripts' => $this->config->item('scripts','head_meta'),
'sidebars' => $this->config->item('sidebars')
);
/* Template variables */
$cfg_assetsUrl = base_url() . 'assets';
// If pagename exists than concatenate it with a sitename, else output only sitename
if(!empty($cfg_template['pagename'])){
$title = $cfg_template['pagename'] . ' - ' . $cfg_template['sitename'];
}else{
$title = $cfg_template['sitename'];
}
And one part in my main template layout is block with sidebars:
<div id="tpl-sidebar">
<?php foreach($cfg_template['sidebars'] as $sidebar):?>
<?php $this->load->view('modules/'. $sidebar);?>
<?php endforeach ;?>
</div>
And at last, it loads a application/views/home.php into the specific div block inside applications/views/template/template.php. This is a /views/home.php:
<?php
// No direct acces to this file
if (!defined('BASEPATH')) exit('No direct script access allowed');
// Page configuration
$this->config->set_item('page_name','Homepage');
$this->config->set_item('css_page','home');
$this->config->set_item('alias','home');
?>
<p>
WELCOME BLABLABLA
</p>
</h3>
There is a section where i can define/overwrite a default values from config/template.php and use a specific ones for each views. So my questions is, how can i extend a $config[sidebar] array inside this view file by inserting some new items, for exemple: recent.php,rss.php etc... ?
Sorry for a big code.
Thanks in advance.
Why don't you set config variables in controller?
Views are not meant for logics.
You shouldn't do that in the views, setting that data should be done from the controllers.
The views should only handle view logic, not setting the logic itself...
Then you pass the vars from the controller, when it's all set and ready to go, into the view.
Ok, i got it:
this is what i should insert inside of a views/home.php:
$this->config->set_item('sidebars',array(
'recent',
'rss'
));
Thanks anyway.
Related
I am currently working on some upgrades of a small personal framework that uses MVC.
The way it works currently is that when Init.php is included in a certain file, instead of looking for a variable, it gets the text content of the file (The actual source code) and just "cuts out" the variables. I believe it's heavily unorthodox and honestly, just bad.
A fellow developer also worked on a framework that also used MVC and was able to do what I was wanting to do the correct way.
<?php
require 'Init.php';
$page['id'] = 'index';
$page['name'] = 'Home';
That's what both of our files look like, however, if I was to let's say, use a variable instead of a string on the $page['name'] element, the title of the page would literally be the variable name (Imagine "Sitename - $variable")
I've been for about 2 days looking for an answer, and I found one promising one that was basically using require_once and ob_get_contents, however, I do not wish to use require_once.
How could I do what my fellow developer has done?
Edit
Here's my current attempt at getting the array, it only works when using require_once.
/************* CONTENT PARSING **************/
global $page;
$buffer = explode('/', $_SERVER['PHP_SELF']);
$filename = $buffer[count($buffer) - 1]; // index.php in our case
var_dump($page); // Dumps NULL
ob_start();
include($filename);
echo $page['id']; // Echoes nothing
echo ob_get_contents(); // Echoes nothing
echo $page['id']; // Dumps nothing
ob_flush(); // Returns nothing
var_dump($page); // Dumps nothing
EDIT 2
Here's the way files are included and variables are declared
config.php and pageTpl.php are included in Init.php
config.php contains the $page array and is included before pageTpl.php
index.php includes Init.php
In a few words, the value that I want to assign to the id and name element of the $page array can only be accessed if you're on index.php, I would like it for the developer to access the variable globally. (Where Init.php is included)
I attempted to run a var_extract($page) on each of those files and the results were as follows:
config.php (Where the $page array is declared):
array ( 'id' => '', 'name' => '', ),
Init.php (Where config.php is included):
array ( 'id' => '', 'name' => '', ),
index.php (Where the values are changed):
array ( 'id' => 'index', 'name' => 'Test', )
pageTpl.php (File included in Init.php, attempts to access the $page array):
NULL
Okay, so after going around the documentation a few times and reading over the code of a few frameworks I noticed that the only way to get the final value of all those variables was using the PHP register_shutdown_function that is the function that is called after script execution finishes, this means that all variables are processed, calculated and can therefore all be accessed from that function as long as they are global.
Example:
index.php
<?
require 'Init.php';
$page['id'] = 'index';
$page['name'] = 'Home';
Then, on Init.php we do all the complicated frameworky-stuff, but we also include the kernel, that will contain the shutdown function
Init.php
<?
require 'inc/kernel.php';
new Kernel;
Now, the kernel, of course
kernel.php
<?
class Kernel
{
public function __construct()
{
register_shutdown_function('Kernel::Shutdown'); // Registers shutdown callback
spl_autoload_register('Kernel::LoadMod'); // Not exactly sure why is this function necessary, but it is. All I know is that it tries to files of called classes that weren't included
}
static function Shutdown()
{
global $page;
var_dump($page); // Will print what we defined in the $page array
Module::LoadTpl($page); // We pass the $page array to the tpl module that will do the rest
}
}
module.php
class Module
{
static function LoadTpl($page)
{
var_dump($page); // Will also print $page, but now we're not confined to kernel.php
}
}
Then, from the Module class you can pass the $page array to other classes/files.
When you define an array, with indexes, you need to do it in a specific way.
config.php:
<?php
$page = array('id' => "", 'name' => "");
var_export($page);
?>
This will create array called $page, with an index of id & name that have values of nothing.
Now in your index.php, you can assign values:
<html>
<body>
<pre>
<?php
include 'Init.php';
$page['id'] = basename($_SERVER['PHP_SELF']);
$page['name'] = 'Home';
var_export($page);
?>
</pre>
</body>
</html>
This should result in a page that shows:
array ( 'id' => '', 'name' => '', )
array ( 'id' => 'index.php', 'name' => 'Home', )
I am building an application for companies which sends anonymous-links to customers for filling out a questionnaire. The company should be able to change the colors and the logo of the questionnaire to reflect the affiliation to the company's CI.
My idea was to make a folder for every company (in my case, represented as doctrine entity Client) and load the layout's style.css and logo.png etc. dynamically from this folder.
The question: how do I implement this? How can I change a variable in the layout file from the controller? Or do I have to place the whole layout inside the view.phtml file for the ViewModel?
Thanks in advance!
If I had to have several layouts depending on some condition.
I would make the layouts for every company, set them in module.config.php
'view_manager' => array(
'template_path_stack' => array(
'module' => __DIR__ . '/../view/',
),
'template_map' => array(
'layout/company1' => __DIR__ . '/../view/layout/company1.phtml',
'layout/company2' => __DIR__ . '/../view/layout/company2.phtml',
)
),
Then in gloabal.php or in the same module.config.php would add some options:
'companies_layouts' => array(
'IDofComapny1' => 'layout/company1',
'IDofComapny2' => 'layout/company2',
)
And finally in the controller would do something like this:
public function indexAction()
{
$sm = $this->getServiceLocator();
// Getting company identifier
$companyId = $this->params()->fromRoute( 'companyId' );
// do something
...
$this->layout( $sm->get('Config')['companies_layouts'][$comanyId] );
return new ViewModel();
}
If you just need to set css depending on some conditions.
You can just do this in the view file:
switch( true ){
case some condition:
$css = 'file1.css';
break;
case some condition:
$css = 'file2.css';
break;
}
$this->headLink()->appendStylesheet( $css );
And in the layout file you should have next line:
<head>
...
<?= $this->headLink() ?>
...
</head>
You need to set style.css and logo file path according to company name in you action and then you can access this vairable in you layout also as same as you access in view file.
And set you css with headLink() function. and assign logo file in layout header.
You don't need to place layout code in view file.
Write below code on you controller. you can also access style variable in you layout.
return new ViewModel(array( 'style' => $style ,'logo' => $logo));
In both cakephp-1.2 and cakephp-1.3 I have used the following code snippet in an element named head called from the blog layout:
$this->preMetaValues = array(
'title' => __('SiteTitle', true).' '.$title_for_layout,
'desc' => Configure::read('siteTitle').', '.Configure::read('siteSlogan'),
'keywords' => Configure::read('keywords'),
'type' => 'article',
'site_name' => __('SiteTitle', true),
'imageURL' => $html->url('/img/logo.png', true)
);
if(!isset($this->metaValues)){
$this->metaValues = $this->preMetaValues;
}
else{
$this->metaValues = array_merge($this->preMetaValues, $this->metaValues);
}
<?php echo $html->meta('description',$this->metaValues['desc']); ?>
<?php echo $html->meta('keywords', $this->metaValues['keywords']);?>
I used the above code to define or modify meta-tags values from the any view file. The preMetaValues is regarded as the default values. If there is any metaValues defined in the view, this code will modify it and make the metaValues ready to be used.
Now with cakephp-2.4, the described code generates the following error:
Helper class metaValuesHelper could not be found.
Error: An Internal Error Has Occurred.
Indeed, I don't know why CakePHP regards this variable as helper? and how could I fix this issue?
You can do it by setting the variable from your controller action:
$this->set('title_for_layout', 'Your title');
And then in the view, printing it with:
<title><?php echo $title_for_layout?></title>
You have an example of this at the documentation:
http://book.cakephp.org/2.0/en/views.html#layouts
Just treat them as any other variable.
Why you're using $this object? Can't you use a simple solution like this:
$preMetaValues = array(
'title' => __('SiteTitle', true).' '.$title_for_layout,
'desc' => Configure::read('siteTitle').', '.Configure::read('siteSlogan'),
'keywords' => Configure::read('keywords'),
'type' => 'article',
'site_name' => __('SiteTitle', true),
'imageURL' => $html->url('/img/logo.png', true)
);
if(!isset($metaValues)){
$metaValues = $preMetaValues;
}
else{
$metaValues = array_merge($preMetaValues, $metaValues);
}
<?php echo $html->meta('description',$metaValues['desc']); ?>
<?php echo $html->meta('keywords', $metaValues['keywords']);?>
Finally I have found the solution. It is simply about how to set a variable for the layout from a view. It seems that in earlier versions of cakephp the view was processed before the layout while now in cakephp-2.4 the layout is processed first, so any override of any variable defined in the layout from the view will not success.
Hence, the solution will depend on the set method of the view object something as follows:
//in some view such as index.ctp
$this->set('metaValues', array(
'title', 'The title string...',
'desc' => 'The description string...'
)
);
Also as Alvaro regarded in his answer, I have to access those variable without $this, i.e as local variables.
This answer is inspired from: Pass a variable from view to layout in CakePHP - or where else to put this logic?
i wanted to know in which file we can set common code, for example i wanted to set timezone to UTC, instead of putting same code in all controllers file is there any way to put the code once and it will be reflect in all files.
You may create your file in ''components'' folder. You can see this folder in "protected" folder.
Or you can write your code in controller.php
File path: webroot/protected/components/Controller.php
Can you please try to add the codes in bootstrap.php file
If you need to set the server time you can check here.It is a simple method
Change time zone
Use application params, ie:
// config part
return array(
// ...
'params' => array(
'myParam' => 123
)
// ...
);
// Then in app use
Yii::app()->params['myParam'] // Will return 123
You can also create your own params holder as component, ie:
// config part
'components' => array(
'myConfigs' => array(
'class' => 'ext.MyConfigs'
'myParam1' => 123,
'myParam2' => 'blah'
)
)
// Component in extensions
class MyConfigs extends CComponent
{
public $myParam1;
public $myParam2 = 'defaultValue';
}
// Then in app use it:
Yii::app()->myConfigs->myParam1 // will return 123
So I have this part in my View:
<body>
<div id = "content">
<?php echo $catalog ?>
</div>
</body>
There are also other variables in it. Here is the part of my Controller where I send them to the View:
$this->load->view('layout',array(
'categories' => $categories,
'home_menu' => $home_menu,
'information' => $information,
'favourite' => $favourite,
'new_products' => $new_products,
'bestsellers' => $bestsellers,
'login_info' => $login_info,
'catalog' => ''
));
I want to create second controller, which when activated sends a second view to the variable $catalog.
Something like this (similar to Kohana):
$this->layout->catalog = $this->load->view('products/catalog', array(
'name' => $name,
'description' => $description));
But it's not working.
My question is, how can I show this second nested view after clicking on a link that activates the second Controller?
EDIT:
But I want to send the catalog view to $catalog variable after the user has clicked on a link that activates second controller, which look something like this:
$products = $this->Product_model->list_products($category_id);
foreach ($products as $row)
{
$name = $row->name;
$description = $row->description;
}
.. after that I want $name and $description to be passed to:
$this->load->view('products/catalog', array(
'name' => $name,
'description' => $description));
..which itself to be passed to $catalog in the layout view defined in the first controller
You can call a $this->load->view within the view's code but I would not recommend it.
Instead pass true as the 3rd parameter in the load view function and this will return the view rather than echo it straight out. Then you can assign that returned code to your original view.
I'm hoping I'm understanding your question fully, but if not, I apologize.
My guess is that you're loading the page with all of the 'extras' and want to be able to update the 'content' part of your page through a user initiated click.
If you're implementing a javascript based solution, then you just need a controller that will output the html fragment and inject that into the current page via an ajax call.
If you're not implementing javascript, then it would be an entire page refresh, so you would just rebuild the page and pass the selected catalog content to the controller.
UPDATE
To do this without ajax or hmvc, you need to get the contents from another controller into this controller, so you could just make an additional request with php:
$catalog_content = file_get_contents('/url_to_second_controller.html');
$this->load->view('layout',array(
'categories' => $categories,
'home_menu' => $home_menu,
'information' => $information,
'favourite' => $favourite,
'new_products' => $new_products,
'bestsellers' => $bestsellers,
'login_info' => $login_info,
'catalog' => $catalog_content
));