I'm working on a CakePHP 1.2 app where I don't have control over the /app directory and have relocated my views folder to, say /path/to/mycomponent/views and can render my views by setting my controller's default view path
var $viewPath = "mycomponent/views";
I have some layouts (including basic.ctp) under /path/to/mycomponent/views/layouts
Is there a way to render my views inside a specific layout?
Calling this from my controller gives me a page not found error:
function index()
{
$this->autoLayout = true;
$this->pageTitle = 'Browse items';
$this->render("browse", "basic");
// also tried: $this->render("browse", "/path/to/mycomponent/views/layouts/basic.ctp");
}
Finally got it to work by adding a path to the viewPaths array of the app configuration. This code goes in you controller constructor or in the override beforeFilter metod:
$config = Configure::getInstance();
$config->viewPaths[] = " /path/to/mycomponent/views/";
Now I can just specify the following:
$this->layout = 'basic';
And my controller's views render in the basic.ctp layout.
Just for any further reference.
I believe in cakePhp 2.x it's to be done this way.
public function beforeRender() {
parent::beforeRender();
$this->layout = 'mylayout';
}
which would go to the path: /app/View/Layouts/mylayout.ctp
Note:
If you want to modify the view paths for some controller, add before the controller class declaration:
App::build(array('View' => '/Folder/'));
class ExampleController extends AppController{...}
which will set the path for all rendered view for Example controller to /app/Views/Folder/
so the full example would be:
App::build(array('View' => '/Folder/'));
class ExampleController extends AppController{
public function beforeRender() {
parent::beforeRender();
$this->layout = 'mylayout';
}
public function index() {
$this->render('Home');
//This will load view: "/app/Views/Folder/Home.ctp"
//From layout: "/app/Views/Layouts/mylayout.ctp"
}
}
Related
I am using cakephp 2.0.4 (Doing Changes in existing project)
My controller function is..
class PagesController extends AppController {
public function getlocations($string = ''){
$this->autoRender = false;
$aResult = array(0=>'Florida', 1=>'London');
echo json_encode($aResult);
}
}
And also I have try $this->autoLayout = $this->autoRender = false;
When I am calling this action directly in browser mysite/app/pages/getlocations it will give following error
View file "/home/mysite/public_html/testing/app/View/Pages/g.ctp" is missing.
Create a /View/Ajax/json.ctp view:
<?php
if(!empty($data)) echo json_encode($data);
Then in the action:
$this->set('data', array(0=>'Florida', 1=>'London'));
$this->layout = false;
$this->render('/Ajax/json');
You could also make it work following the Cake way.
First you have to add the following code to your routes file:
Router::parseExtensions('json');
Next, in the controller add the 'RequestHandler' to your components array and serialize your result in your getlocations function:
public $components = array('RequestHandler');
public function getlocations($string = ''){
$this->set('aResult', array(0=>'Florida', 1=>'London'));
$this->set('_serialize', 'aResult');
}
Finally, you can see the results in your browser mysite/app/pages/getlocations.json
Doing this way CakePHP will add the application/json headers automatically.
More info: http://book.cakephp.org/2.0/en/views/json-and-xml-views.html
In CakePHP each method of a Controller has its own View and the view template file is the name of the method.
class DataController extends AppController
{
public function one()
{
// will render one.ctp
}
public function two()
{
// will render two.ctp
}
}
Accourding to the API documentation there is a $view property of the Controller that specifies the view to render. So I should have the ability to specify a default view file, say all.ctp, for all methods of a controller
class DataController extends AppController
{
public $view = 'all';
public function one()
{
// should render all.ctp
}
public function two()
{
// should render all.ctp
}
}
However this does not work and CakePHP ignores the $view property and continues to look for the template file of the same name as the method.
Is there a way to have a default view without having to insert $this->render('all'); in each of the Controller's methods?
The value is going to be overridden in Controller::setRequest() which is being called in the controllers class constructor.
You could use your controllers beforeFilter() callback instead to set the value:
public function beforeFilter()
{
parent::beforeFilter();
$this->view = 'all';
}
I am facing a strange error in cakephp2.0. I have created two layouts - one for plugin and one for front end users. Whenever I take the front end and after that if I take the plugin in the url, the front end layout is getting applied to all pages coming under plugin and vice verse. After 8-10 refresh it will take the correct layout. How to avoid caching of layout variable in this case ?
VideosController under app/Controller folder
App::uses('AppController', 'Controller');
class VideosController extends AppController
{
public function index()
{
$this->layout = 'default';
$this->set('videos', $this->Video->find('list'));
}
}
My plugin Main controller
class AdminAppController extends AppController
{
var $layout = 'admin';
}
Another controller inside my plugin
App::uses('AdminAppController', 'Admin.Controller');
class VideosController extends AdminAppController
{
public function index()
{
$this->Video->recursive = 0;
$this->set('videos', $this->paginate());
}
}
You can set parts of your view to not be cached, or you could clear the cache every time the layout is changed. Check: http://book.cakephp.org/2.0/en/core-libraries/helpers/cache.html
I need to know in a helper in a CakePHP application if the device is mobile, I would love to use $this->RequestHandler->isMobile(), but the request handler component is not available in helpers. Any ideas?
Thanks!
You can import the class and use it anywhere in the framework like so:
App::import('Component', 'RequestHandler'); // import class
$requestHandler = new RequestHandlerComponent(); // instantiate class
$isMobile = $requestHandler->isMobile(); // call method
var_dump($isMobile); // output: bool(true) or bool(false)
(Tested from helper and gives correct results for Firefox and iPhone)
Also, any options you set in the Controller::helpers property will be passed to the helper:
class AppController extends Controller {
public $components = array(/*...*/, 'RequestHandler');
public $helpers = array(/*...*/, 'MyHelper');
public function beforeFilter() {
$this->helpers['MyHelper']['mobile'] = $this->RequestHandler->isMobile();
}
}
You can catch the options array in your helper's constructor:
class MyHelper extends AppHelper {
protected $_defaultOptions = array('mobile' => false);
public function __construct($options) {
$this->options = array_merge($this->_defaultOptions, $options);
}
}
The accepted answer suggests using a component inside a helper which should be avoided as components are for use solely in controllers and will result in errors as mentioned by Anupal.
The simple solution is to use the CakeRequest class that RequestHandlerComponent uses. So in your helper you can do:-
App::uses('CakeRequest', 'Utility');
$isMobile = (new CakeRequest())->is('mobile');
I cannot set title_for_layout in the PagesController that comes by default with CakePHP 1.3.
I am using the following code in the display function:
$this->set('title_for_layout','some title');
What am I doing wrong?
In your controller, the corresponding value is $this->pageTitle.
UPDATE
Oops, as noted in the comments, this is the 1.2 solution. 1.3 possibilities (after doing some research) include:
Ensuring that $title_for_layout is being echoed in the layout
Placing the $this->set() code in the view rather than in the controller
If you'd like to mimic the behavior of cake 1.2, you can do the following:
In your app_controller, create the following method:
in app/app_controller.php (you may need to create this file if you haven't already)
public $pageTitle;
public function beforeRender() {
$this->set('title_for_layout', $this->pageTitle);
}
Then in any of your action methods, you may then use the pageTitle as you would in 1.2.
public function index() {
$this->pageTitle = 'Some Title';
}
The beforeRender() method will be called after your controllers have finished processing, but prior to the layout being rendered, thus allowing you to set variables for the layout.
In the action method, try this:
function index()
{
$this->pageTitle= 'Your Title';
}
Just thought I'd add to any new people finding this solution, you can do $this->set('title', $title); in CakePHP 1.3 inside the controller and the title will be rendered automatically.
You can use :
$this->assign('title', 'Some title');
and in ctp :
<title><?= $this->fetch('title'); ?></title>
It work in CakePHP 3.0
For CakePHP 3.x,
you can follow the advice here
Essentially,
Inside UsersController.php:
$this->set('title', 'Login');
Inside src/Template/Layouts/default.ctp
above the $this->fetch('title');
write:
if (isset($title)) {
$this->assign('title', $title);
}
Use beforeRender() instead. Put the following in AppController:
class AppController extends Controller {
var $content;
function beforeRender() {
$this->set('content',$this->content);
}
}
And in the controller, you can just do:
function index() {
$this->content['title'] = '123'; }
That'll do the trick.