I have deployed an app using cakephp. Now i have some data which i want to render on some logic. This data should be showed as a page including some inputs and other fields.
One thing is to do this in javascript side but it will not be a suitable option to make a whole html in javascript.
Other solution on which i am working is to pass the data to the .ctp file. Get the html and pas this to my content.
I am trying to do this as
$html = $this->render('myview');
$this->set('html', $view);
but it render the myview as a page not as html to be shown to my view.
Follow the code to achieve the same, (this code in your controller's method/action)
//Variables used in view
$data = $this->Admins->newEntity();
// create a builder
$builder = $this->viewBuilder();
// configure as needed
$builder->setLayout('default');
$builder->setTemplate('/Admins/login'); //Here you can use elements also
$builder->setHelpers(['Html']);
// create a view instance
$view = $builder->build(compact('data')); //Pass the variables to the view
// render to a variable
$output = $view->render();
//Print output
pr($output);
die;
From what I understood from your question and comments, you want to render something in a certain place of your view, but you want to put code for that component in separate .ctp file. CakePHP already has built in tools to achieve this - Elements and Cells.
Elements are reusable pieces of code, which resides in src/Template/Element directory. To create an element, simply create new .ctp file (eg. myelement.ctp) in this directory, and output it in your main view using:
<?= $this->element("myelement") ?>
Elements have access to variables passed to view from which are called, but if needed, one can also pass variables as second argument:
<?= $this->element("myelement", ["somevariable" => "somevalue"]) ?>
On the other hand, you have also Cells, which should be used in need to create an reusable component which depends on some logic which should be separated from controller code. Cell consists of two parts - a Cell class, which is equivalent for controller, and template file. It can be baked by:
bin/cake bake cell Sample
This command will create src/View/Cell/SampleCell.php and src/Template/Cell/Sample/display.ctp files. In first of them, a standard controller logic can be performed. In second, you can put HTML and access to passed variables. Cell can be rendered into a view by using:
<?= $this->cell("Sample") ?>
More info can be found in docs:
Elements
View Cells
Related
I have Yii template that structure is:
Include CSS files in
echo $content right after
Include Javascript files (like JQPlot) after $content
What I would like to do is add custom mix of Javascript/PHP code after including all Javascript files. I know this can be done just adding the code to the template.
But I have many pages with custom JS/PHP code and I would like to include only the specific code for that page to avoid long load times.
Can I create new element that works like $content, but it would include for example "js.php" from the same View folder as "index.php"? The "js.php" would be in every view folder I need custom code and contain the js/php mix of code for that specific page.
Thanks for the help!
Clips are your best bet, as #jfrej suggests by pointing you to a forum topic where clips are discussed.
Under conventional circumstances, every controller has associated a folder where all its views are placed, and it is the case that you want to include at the end of the layout (this is how they are refered, rather than templates) some PHP+Javascript content that is common to all the actions in the controller.
I would override CController::afterRender() method to capture the content for you clip; lets call your clip controller_content:
afterRender(string $view, string &$output)
$this->beginClip('controller_content');
// output here any content you want to capture into your clip
// e.g. renderPartial, echo, etc.
...
$this->endClip();
parent::afterRender($view, $output);
}
Then, in your layout, you would render your clip after all the stuff that is always there, e.g.:
// register your CSSs
// output $content variable
// register Javascript
...
<?= $this->clips['controller_content'] ?>
Of course, there are various ways for you to generate your clip content. Here I overrode the CController::afterRender() method, but you could also use filters, behaviors or any other approach that best suits your needs.
You can try :
Yii::app()->clientScript->registerCssFile(Yii::app()->baseUrl.'/css/example.css');
Yii::app()->clientScript->registerScriptFile(Yii::app()->baseUrl.'/css/example.js');
You can call it from controller
One of my view file in cake is getting very long, like 300+ lines already. And i find it very difficult to keep track of the understanding.
Is it a good idea to split them up into smaller files and then including them in the parent view file?
If its ok to be done,
In what extension should i create the smaller files? .ctp or .php?
Including them with require_once(view-child1.ext) should be fine, right?
Im fairly new to cakePHP. So i prefer advises from the experts over here. Please put me in the right direction.
EDIT
Thanks for the help guys.
I tried it. But i cant seem to pass the variable. echo $this->Element('reviews/view-goal',$history); Parent view shows and error saying undefined variable in that element.
Im calling the elements from this loop:
foreach($histories as $date => $history)
Cant pass $history. But $histories is being passed correctly.
You should make elements in View/Elements folder with .ctp extension.
This link would help you to make clean separation of your view files with the related/repeated code.
An element is basically a mini-view that can be included in other views, in layouts, and even within other elements. Elements can be used to make a view more readable, placing the rendering of repeating elements in its own file. They can also help you re-use content fragments in your application.
Elements live in the /app/View/Elements/ folder, and have the .ctp filename extension. They are output using the element method of the view:
<?php echo $this->element('helpbox'); //without extension ?>
You can pass variables from your view to the element.
In your view:
<?php echo $this->Element('reviews/view-goal', array('history' => $history));
In view-goal.ctp element you can directly access $history variable.
Yes, it is a very good idea. But don't use the normal require() of PHP.
CakePHP has a feature called "elements", a mechanism to put parts of a view into separate .ctp files. The files go in a special folder, View/Elements
You can include an element like this:
echo $this->element('sidebar/recent_comments');
If you need any variables inside the element, you need to pass them in an additional array parameter:
echo $this->element('sidebar/recent_comments', array('variable_name' => /* Variable content */));
In order to keep your view files small, you should also make sure that you put stuff that is shared by most pages (header, footer) into the Layout file. And obviously: keep JS and CSS in external files.
I want to create a multi column page. I am not sure about which way I should prefer for adapting myself to cakephp's coding discipline.
Should I create columns on my view//index.ctp or on layouts/default.ctp
If layouts/default.ctp is the sutiable way, how can I fetch the other content? As you know, there is a line for fetching controller's view content like <?php echo $this->fetch('content'); ?> How can I fetch another content?
Simply declare a block somewhere else, in your view file for example, use start() and stop() to define a block and output it with fetch(). For example start('menu'); and then calling fetch('menu') will display the content between the start and stop call.
Read this:
http://book.cakephp.org/2.0/en/views.html#extending-views
http://book.cakephp.org/2.0/en/views.html#view-blocks
http://book.cakephp.org/2.0/en/views.html#using-view-blocks
http://book.cakephp.org/2.0/en/views.html#displaying-blocks
I have a navigation menu inside a CakePHP element file (views/elements/nav_default.ctp).
The file is included inside another element that is the header (views/elements/header_default.ctp) which is then included in the layout file (views/layouts/default.ctp).
I am trying to tell Cake to load a js file (webroot/js/mega_drop.js) from within the nav element like so:
<?php
$this->addScript('mega_drop');
?>
It does not get included. I looked at the documentation for addScript which just says:
Adds content to the internal scripts
buffer. This buffer is made available
in the layout as $scripts_for_layout.
This method is helpful when creating
helpers that need to add javascript or
css directly to the layout. Keep in
mind that scripts added from the
layout, or elements in the layout will
not be added to $scripts_for_layout.
This method is most often used from
inside helpers, like the Javascript
and Html Helpers.
The key part:
Keep in mind that scripts added from the layout, or elements in the layout will not be added to $scripts_for_layout.
So how do I do it then?
I guess I could add a <script src="/js/mega_drop.js"></script> to the default.ctp layout. That doesn't feel right though as it would tightly tie the layout and the element together.
Whats the CakePHP best practice way to do this?
addScript() does not load a file; it adds actual code to the $scripts_for_layout variable. The idea being that the layout is a good, common place to load your JavaScript files and code. That way you can output all the code in one location - in the head block or at the end - either way it's together. So if you are in a situation where you've got JavaScript code in the view, rather than output it inline, you can pass it up to the layout.
The best way to load a script file is with the HTML Helper- echo $this->Html->script("script or array('of', 'scripts')"); With that in mind, you could $this->set('scripts', 'mega_drop'); in the element and then call the Html Helper with that $scripts variable from the layout.
The problem with that: it won't work if your nav_default.ctp is called from the layout. $this->set() works inside of a view (or an element called from a view) because the View is rendered before the Layout. If you are calling your element from the layout, then it is too late to be setting viewVars for use in the layout. The best thing to do is set() the scripts variable from the Controller and use a if(isset($scripts)) { echo $this->Html->script($scripts); } in the layout.
Correct and valid 1.3.x CakePHP 2.0 Dev is from example.ctp file:
$this->addScript($this->Javascript->link('tab_enabler'));
$this->addScript($this->Html->css('jquery.tabs'));
This is an example of how to properly include CSS and JS files from the view and adding in the variable $scripts_for_layout to not generate validation error with the W3C as it is not correct to add the link to a css file in <BODY></BODY>
try
$this->Html->script('mega_drop', $inline=false);
in your element without the echo.
The Second parameter says to add it to the $scripts_for_layout variable.
You should be able to do this in your element, so that the javascript is only included when the element is.
I have a controller and including two views from one function as below
$this->load->view('includes/header',$data);
$this->load->view('view_destinations',$data);
The view file view_destinations.php including a php menu file as follows
<? $this->load->view('includes/top_menu'); ?>
My question is, how can I pass data that is fetched from the controller to this included top_menu.php ?
Thank you guys
Inside your controller, have
$data['nestedView']['otherData'] = 'testing';
before your view includes.
When you call
$this->load->view('view_destinations',$data);
the view_destinations file is going to have
$nestedView['otherData'];
Which you can at that point, pass into the nested view file.
<? $this->load->view('includes/top_menu', $nestedView); ?>
And inside your top_menu file you should have $otherData containing 'testing'.
castis's solution works
however if you want to do this on a more finely grained level you can use:
//in your controller
$data['whatever'] = 'someValue';
.
//In your view
echo $whatever //outputs 'someValue';
//pass $whatever on
$this->load->view('some/view', Array('whatever' => $whatever));
This Codeigniter forum post should help you ;)
You can either make your $data (example) global in the controller, or pass just like #castis mentioned from within your view (variables only in your view)
More details here:
http://codeigniter.com/forums/viewthread/88335/
I have seen in my view files, if I'm passing data from controller to view and from that view to included nested view files. there is no need to transfer
$data
for your nested view it is already available. you can directly access it, within your inner view.
Also try this to if you want every single CodeIgniter view data in a subview:
echo $this->view('subview', get_defined_vars()['_ci_data']['_ci_vars'])