Best Way To Create Multi Column Page on CakePhp - php

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

Related

get the html of .ctp file in CAKEPHP

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

Where to hook in to alter View output in Laravel 5?

For some kind of output filter, I need to access the final rendered output string that includes both view data as well as 'hardcoded' text in the view file.
For example:
welcome.blade.php
<div>This is bad and you are {{ $variable }}</div>
controller, composer, or something else that attaches variables
view()->with('variable', 'bad')
The final output would be
<div>This is bad and you are bad</div>
But now let's pretend we want to replace each instance of 'bad' with 'good', so we get:
<div>This is good and you are good</div>
Altering view data is well supported, but how to apply some altering logic to the fully rendered content? (since I think this is the only way to also alter contents of a view file itself?)
Note: if and only if possible, I'd prefer a 'hook-in' solution instead of an 'extend-core' one..
Take a look at the CompilerEngine (Illuminate\View\Engines\CompilerEngine).
You could use it to get the evaluated contents of a view by using the get method.
Maybe combine that with a registered ServiceProvider to manipulate the views content. Also check out the BladeCompiler maybe you can combine those.
But trying to change hardcoded text seems a bit odd. Why not just use variables in the first place. I mean why is it hardcoded if you want to change it afterwards?

How to output data after all php is executed?

I am creating breadcrumbs on my simple site.
I have some helper classes. I use them like this (just example):
$Breadcrumbs = new Breadcrumbs();
$Breadcrumbs->add(new Breadcrumb("/", "page1"));
$Breadcrumbs->add(new Breadcrumb("/", "page2"));
$Breadcrumbs->add(new Breadcrumb("/", "page3"));
$breadcrumb->show(); returns this:
<ol class="breadcrumb">
<li>page1</li>
<li>page2</li>
<li class="active">page3</li>
</ol>
So, in my project I have some switch-case constructions in which I include some files.
In this files I am using $breadcrumbs->add(...). This code:
<div class="container body">
<? $Breadcrumbs->show();?>
<?
$page = isset($_GET['page']) ? $_GET['page'] : null;
switch($page):
case "suppliers":
require_once($DOCUMENT_ROOT."/modules/suppliers.php");
break;
default:
require_once($DOCUMENT_ROOT."/modules/default.php");
break;
endswitch;
?>
<? $Breadcrumbs->show();?>
</div>
gives me this result:
Well, it works like it must work. I am using $breadcrumbs->add(...) in require files after I called $breadcrumb->show() first time thats why 1st call returns blank result. 2nd call of show() is after all breadcrumbs are added, so it returns fine result.
The questions is how to output breadcrumbs before switch blocks but with right content. Maybe I need a buffer or idk?
This is a good example of why it is such a good idea to separate out logic from presentation: you have a nice abstraction for crumb links, but can't use it properly because your other code is outputting as it goes along, rather than working with abstract data.
Obviously, you could throw away your current structure and port both logic and display directly into a new framework, but assuming you want to migrate from where you are now, here's one approach:
Create an object or array that represents the "result" of whatever module is called. Replace all current use of echo or ?> with concatenation to a string called something like $results['generic_output']. This is effectively like buffering your output, and is enough to let you use your existing abstractions like $breadcrumbs at any time. At this stage, your "template" would consist mostly of echo $results['generic_output'], plus the boilerplate header and footer which is probably already gathered in one place.
Start breaking down the output into sections. Particularly look for sections which are similar on multiple pages. For instance, if you have a "sidebar" with different content on each page but similar styling, make a $results['sidebar_content'] with just the content of that sidebar; the boilerplate to lay it out can then go into your template, and you've reduced the amount of code duplication.
Make the data you pass to the template increasingly abstract, with the goal of eventually having no HTML outside of the template(s). For instance, maybe the sidebar is made up of panels; you might start with an array of HTML blocks, one for each panel, but then turn it into an array of objects based on the actual data being displayed (say, a special offer, or the customer's current basket), with a set of templates for handling different kinds of panel. Eventually, it should be theoretically possible to build a plain-text version of your site with no HTML, just by changing the template layer, and none of the original modules.
The final step is to separate decisions about what to show from decisions about what to do. Continuing with my imaginary sidebar, your template could always receive the current basket as a general variable for use somewhere on the page, rather than as "sidebar item 1". This allows you to completely separate the actions that led into a page from the output that eventually results.
I would like to stress that this is not the way to a perfect framework, or the definitive solution to your situation, but it's one way of organising existing code (and existing thinking) in the right direction.
In the above, the "templates" could just be a set of PHP files using ?> or echo to produce the output, or it could be a dedicated templating system such as Smarty or Twig. Indeed, the point of the separation is that you could change your mind on that front later, because the result of the code modules would be an array of data to be displayed, which is just what Smarty or Twig would need as input.

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

Zend organization question

So I had a question on general organization of code for the Zend framework with regard to the layout.
My layout is basically this:
(LAYOUT.PHTML)
<div id='header'>
<?= $this->Layout()->header ?>
</div>
<div id='main'>
<?= $this->Layout()->main ?>
</div>
<div id='footer'>
<?= $this->Layout()->footer ?>
</div>
and so on and so forth. Now, in order to keep my code in my header separate from the code of my main and the code of my footer, I've created a folder for my view that holds header.phtml, main.phtml, footer.phtml. I then use this code to assign the content of header.phtml into $this->layout()->header:
(INDEX.PHTML)
$this->Layout()->header = file_get_contents('index/header.phtml');
$this->Layout()->main = file_get_contents('index/main.phtml');
$this->Layout()->footer = file_get_contents('index/footer.phtml');
That was working great, but I've hit a point where I don't want main to be static HTML anymore. I would like to be able to insert some values with PHP. So in my Controller in indexAction, I want to be able to load from my database and put values into index/main.phtml. Is there a way to do this without restructuring my site?
If not is there a way to do it so that I can have:
The ability to put code into different sections of my layout, such as Layout()->header, Layout->footer.
Separate these pieces into different files, so that they're easy to find and organize, like my index/footer.phtml, index/main.phtml etc.
Not have to put that code into quotes unnecessarily to turn it into a string to pass it to Layout()->header etc.
Thank you guys so much for your help.
-Ethan
Here is an idea:
Assign layout()->header the filename instead of the contents.
Put your code in this file
In your layout file, include() or require() the layout->header().
Since your layout headers/footers are now parsed, you can use them just like a view.
The ->header in $this->layout()->header is response segment. You can render parts of response using $this->_helper->viewRenderer->setResponseSegment('header'); in an action.
If you use
$this->layout()->header = $this->render('index/header.phtml');
It will even use the view, therefore keeping all your variables defined when rendering the header.
I would suggest using something like
<?php echo ($header = $this->layout()->header)?
$header : $this->render('headerDefault.phtml'); ?>
in your layout file - it will render a default header from the layout folder if the view script doesn't override it.
Have you tried looking at view helpers. They are a way of structuring view logic into reusable and modular code. In this case you would use a view helper to generate each of your required segments. So your example view script would look like
$this->Layout()->header = $this->header();
$this->Layout()->main = $this->main();
$this->Layout()->footer = $this->footer();
The benefit of using view helpers over include and require statements is that all of the file handling and name resolution is handled by the framework. The manual has more information on how to set up the paths and usage examples etc.
helpers are good. Another option is like the above, putting filenames in header/footer - put the template names and use $this->render($this->layout()->header)), etc etc. This is just like the include/require above, but more consistent.

Categories