Cakephp splitting long view.ctp into smaller ones - php

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.

Related

How to avoid adding the same navbar template to every .html page

I'm new at the scene and I'm using Bootstrap 3 and this template for the first time. I need help with the navbar. In the template each content.html has their own navbar.
I need the navbar in a separate file, because I do not want to make changes in every single content.html file.
In my old site without Bootstrap I worked with:
<?php
include("includes/navigation.html");
Can someone help me?
You need configure to put your repeated html data's in a single file and include that one into another.
Lets simple,
if your Project structure like this
project(folder)
db(folder)
Dbconnection.php(file)
js(folder)
jquery.js(file)
css(folder)
bootstrap.css(file)
index.php(file)
page1.php(file)
page2.php(file)
Create a new file with contents of your navbar html tags alone.
For ex. in your nav-menu.php contains
<navbar>
......
......
</navbar>
and save them into new includes folder in your project. So now your project structure will be like this one,
project(folder)
db(folder)
Dbconnection.php(file)
js(folder)
jquery.js(file)
css(folder)
bootstrap.css(file)
includes(folder)
nav-menu.php(file)
index.php(file)
page1.php(file)
page2.php(file)
Now you should include this file(nav-menu.php) in all the template files using php include method, like
include("includes/nav-menu.php");
Add this above code in all of your common files.
You can use
<?php include("includes/navigation.php") ?>
in this project too.
Fastest way that comes to my mind is to just include the code you need to change for every page in a separate switch/case and call the different cases at the top of the page that is including the navbar.
Just note your navigation file needs to be .php, not .html like your example.

Yii add another $content to template

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

Newbie Question about adding an array element on a page (php script)

Apologize me if the question is unclear.
I'm a total newbie php user and I have this script that I want to edit.
The script have uses .tpl for the theme.
In the memberprofile.tpl there is the first name element $profilearray[0].firstname I want to add the result of this element also in another .tpl file called docs.tpl
I tried copying and pasting `$profilearray[0].firstname in docs.tpl but it did not work.
I noticed that docs.tpl uses its own $docsarray[0].xxx
So guys any idea how to do this? because there are some information in the member profile that I would like to add them inside the docs page.
I tried playing with mysql but I don't know how to use the same element firstname for both memberprofile and docs tables
I'm sure there is an easy way to do it.
Here's the full code from memberprofile.tpland I want to show some of these info in that theme docs.tpl
<p class="gray">
{$lang112}: <b>{$profilearray[0].firstname} {$profilearray[0].lastname}</b><br>
{$lang130}: <b>{$profilearray[0].birthday}</b><br>
{$lang134}: <b>{if $profilearray[0].gender eq "1"}Male{elseif $profilearray[0].gender eq "0"}Female{/if}</b><br>
{$lang140}: <b>{$profilearray[0].city}</b> <br>
{$lang139}: <b>{$profilearray[0].country}</b> <br>
{$lang113}: <b>{insert name=get_stripped_phrase value=a assign=pdesc details=$profilearray[0].description}{$pdesc}</b> <br>
{$lang259}: <b>{$profilearray[0].url|stripslashes|truncate:20:"...":true}</b> <br>
{$lang260}: <b>{insert name=get_time_to_days_ago value=var time=$profilearray[0].lastlogin}</b> <br>
{$lang261}: <b>{insert name=get_time_to_days_ago value=var time=$profilearray[0].addtime}</b>
</p>
Smarty has a tag you can google for called {include} that will do what you want. http://www.smarty.net/docsv2/en/language.function.include.tpl Use that tag on your docs.tpl file and you will be fine.
$profilearray
in your example is assigned to smarty template before the template is called in some fashion simmilar to this
$smarty->assign('profilearray',$somearray);
you'll need to find what is setting that in your first file then make sure that is included in your second template call
but you should certainly read the smarty documentation to understand what you are trying to do.
To step back for a moment... There are two parts to all this. The first part is the PHP code which actually takes user input, queries the database, processes the data, etc. The second part is the TPL file. As much as possible, the TPL file should only be concerned with presentation, not with data-processing, data-cross-referencing, etc.
All that database-reading and cross-referencing should happen inside a plain PHP file, not inside the TPL.
In order to add "Author information" to the "Documents List" (or whatever you call docs.tpl) page, you need to find the PHP code which pulls up the list of documents. Find the PHP code where it says something like:
$smarty->assign('docsarray',$document_list);
Now what you want to do is pass more information to the smarty template (TPL file) so that it can display it. Something like:
for($document_list as $index => $doc){
$owner = $doc['owner']; // Get the owner of the document
$profile = getProfile($owner); // Create one of the same things that go into $profilearray elsewhere
$document_list[$index]['profile'] = $profile; // Modify original array
}
$smarty->assign('docsarray',$document_list);
Then go into docs.tpl and find where it displays information about each document, and add smarty template code to read from the new per-document information you added. (Check the Smarty reference page for details.)
For example, if docs.tpl shows a table of documents, you might add a new column that shows the author's first/last name:
<tr>
<td>{$docsarray[$index].title}</td>
<td>{$docsarray[$index].created_date}</td>
<!-- Next line is new -->
<td>{$docsarray[$index].profile.firstname} {$docsarray[$index].profile.lastname}</td>
</tr>
If you want something that looks exactly like the "profile box", you can do that too. In fact, using {include} you can create profilebox.tpl and use it in both places to reduce redundant code.

How do you include PHP files in the view file of a Zend/MVC?

Maybe I dont understand the MVC convention well enough, but I'm trying to include a file to the index.phtml view for the main Index Controller, and it keeps giving me an Application Error. I have no idea what this error is or why its not working. But I'm using a standard include_once(...) in the view.
Is this even allowed?
A view in Zend is still just a php file. If you are getting errors in a view using include_once(), they are probably because the file you want can't be found in your include path. Trying dumping get_include_path() into the view and you will see what directories PHP is searching to find your included file.
As an alternative to include_once, you could use
<? echo $this->render('{module}/{action}.phtml') ?>
to pull in the file.
There are partial views for such purpose
http://framework.zend.com/manual/en/zend.view.helpers.html (ctrl+f Partial Helper)
The view is only the HTML that will be rendered. It's the very last thing that is processed. The controller is called first, then it calls whatever models are needed within. After passing all the data to the view, the view's HTML is rendered.
In short: whatever you include in the view, the controller isn't aware of it. You need to run your PHP includes earlier in the code. If you do it in the controller, it should work OK, I suppose (not tested, so I don't guarantee anything).
You can use Zend View Helpers for this purpose
last time this works fine for me. You can try this:
<?php echo $this->partial('common/left_menu.phtml'); ?>

CakePHP how to addScript() from inside element?

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.

Categories