CakePHP: Reusable content blocks and MVC - cakephp

I'm trying to learn CakePHP by building a simple CMS app, it was going well but as I'm adding more, I'm getting a bit confused by the MVC structure.
In addition to my Posts, I have created a simple model for 'Content Blocks' (basically an admin editable title and content field) that I want to display as elements within other pages of my site.
To help explain:
My Posts controller has an index action that lists out all of the blog posts. In the view for that action I also want to pull a specific 'content block' from the database and display it at the top of the page.
Another example would be an admin-editable 'about' blurb that appears in the footer of every page.
Lastly, in a similar fashion to the Wordpress text widget or Magento static block, I'd like to prevent 'content blocks' being directly accessible (i.e. domain.com/content_blocks/view/id)
What is the ideal way to achieve this whilst staying true to CakePHP and MVC convention?
I've had several stabs at it (such as using requestAction in an element) but have only succeeded in getting more confused.

The way I would do it is as you suggested with a request action inside an element because that won't be directly accessible through the URL. So you would create a view inside the elements folder:
app/View/Elements/block.ctp:
<?php $sidebar = $this->requestAction(array(
'controller' => 'ContentBlocks',
'action'=> 'viewBlock',
'yourtitle'
));
// layout your block here
?>
app/Controller/ContentBlocksController.php
public function viewBlock($title) {
return $this->ContentBlock->findByTitle($title);
}
Then you can see this post for how to do caching with the element and requestAction: http://mark-story.com/posts/view/how-using-requestaction-increased-performance-on-my-site
Also, you might want to checkout Croogo, which has a lot of the functionality you are looking for and more already built in: http://croogo.org/

Related

CakePHP: Flexible redirection for views and controllers

I have views that are called from different views. The customers edit view can be called from the customers list, the customers search, from within an order and so on. Some of this views are simple views other contains forms to add, edit or delete data. After the user has done what he had to to on that form he should be redirected to the calling form or to another form.
Using $this->referer() wouldn't work as some navigations have to go like this:
list order --> edit order --> delete order --> list order.
I would be fine with defining the redirection for every call so I've tried to use query strings and add ?redirectTarget=<wherever> to every link or redirection. For that I've made a controller function
in AppController.php
public function getRedirectTarget() {
if ($this->request->query('redirectTarget')) {
return $this->request->query('redirectTarget');
} else {
return array(
'controller' => 'pages',
'action' => 'home'
);
}
}
This works for forms as I can use getRedirectTarget() in my controllers but I cannot access that function from within a view to build a link. (At leas I sholdn't do that Can you call a controller function from a view in CakePHP? ) In the example from the top I have to pass the information from the order list to the edit view to build a link and to the underlying controller for the form action.
Now I have different aproaches in my mind but with none of them I'm realy happy. I'm not shure which way to go.
Is there something in CakePhp I haven't found yet?
using $this->requestAction?
changing everything to forms and buttons and doing all redirections in the controllers?
Is there a way to create a variable for every view?
As this seems to me like a comon requirement and I'm pretty new to CakePHP I'm asking for your advice.
Using requestAction should be the best way.
In the views, you can have something like
$redirect = $this->requestAction('/mycontroller/requestAction');
$url = $this->Html->link('Continue', $redirect));

AngularJS set title and description in head when populating content from JSON

Before I go and do this in Jquery out of frustration I figured I would ask what the angular way is?
I'm building an AngularJS site using a model based of the Phonecat tutorial example on the AngularJS site.
I found this method to set the title of a page and can work out how to modify it to do description as well in the app config but this doesn't work when I'm populating pages with content via json. I tried doing it using a ngbind method as well but have yet to find a working solution as I think something to do with the order in which files are loaded is breaking.
For example
when('/faq', {
templateUrl: 'sub_pages/articles.html',
title: 'Landing page title goes here, not to big a deal'
}).
when('/things-to-do/:activityID', {
templateUrl: 'sub_pages/activity-detail.html',
controller: 'activityDetailCtrl',
title: 'If I put a title here it will be the same on all of these pieces of content'
}).
What method can I use in order to set title on both the landing pages and also the pages which draw their content from a JSON feed?
EDIT - ANSWER BELOW
After about 2 days of bashing my head against a wall trying to work this one out it's actually quite simple and works for both static pages and templates with dynamically loaded content.
Inside the view pages (html that loads inside of ng-view) add a couple of divs (you can put this anywhere really) and then inside them you need to load in ng-init.
ng-init="$root.title = path.to.title"
ng-init="$root.description = path.to.description"
This will set the title and description on the root scope. The "path.to." is just an example path to content in json, you can replace this with plain text as well which is how I deal with landing pages.
Then on the index.html or what ever page your app is based on inside the head you just need to load in.
Your Page Title
This will automatically set your page title and description meta tags and you can pretty much use this formula for any other meta data you need to create.
I haven't tested this yet with Prerender.io or any other cache service but will do some checks and post the results here.
Something like
$document[0].title = "xyz";

CakePHP Routing & HTML Helper Link Ambiguity

I have a site that uses CakePHP 2.x. There's a backend interface where actions use the standard Cake layouts and views, but several of the actions are also exposed to front end users as "dialogs" (same functionality, just a layout that can be put in iframe).
In app/Config/router.php I have added the following:
Router::connect('/dialog/:controller', array('action' => 'index'));
Router::connect('/dialog/:controller/:action');
Router::connect('/dialog/:controller/:action/**');
This works appropriately, but the problem starts when trying to use the HTML helper's link() method. If I try to create a link like:
$this->Html->link('edit account', array('controller' => 'users', 'action' => 'edit'));
I get the following:
edit account
When the link is within a dialog, this works great, but I don't want the non-dialog pages to link to the dialog.
How can I control which of the two URLs is used in a particular page?
Is there something I can call from within AppController once I know whether the page being rendered is a dialog or not, or even something in the call to link() that would allow me to override it.
I know there's the "prefix" option which would allow for URLs like /user/dialog_edit but I would like to maintain the /dialog/users/edit format if possible. I also know I can hard code the URL vs. passing controller/action/id/etc in an array, and I don't anticipate pathing/model names changing, but I'd like to do this the idiomatic way for CakePHP, if possible.

cakephp display data from another controller in pages

I need to display latest article on my apps home page. After reading a lot of questions on stackoverflow, I've tried importing the ArticlesController and using requestAction with no success. Maybe there's a catch that I'm missing, since PagesController doesn't use a model.
What would be the best way to do this?
////////////// edit:
I've got the requestAction working, using following code
home.ctp view:
$lastarticle = $this->requestAction('/Articles/getarticle');
ArticlesController controller:
public function getarticle() {
$lastarticle = $this->Article->find('first', array('order' => array('Article.id DESC')));
return $lastarticle;
}
Now, I'd like to know if requestAction is an appropriate way of solving this problem because I've read that it's a waste of resources.
If your home page just displays articles, why not make your articles/index your home page (it doesn't have to be pages/display/home)? Look into cake routing.
Edit: You can use loadModel or requestAction (post your code for requestAction). Either way, you should cache it for better perfomance http://book.cakephp.org/view/1380/Caching-in-the-Controller

cakephp back button issue

i am working on social network website where user can navigate to the album view page in many ways.
for example.
myprofile>> Gallery index page >> Album view page.
myprofile>> Gallery details page >> Album view page.
In first case back button should go to gallery index page and In second case it should go to Gallery details page.
Is there any way to add link to back button path dynamically in cakephp?
You could try using a breadcrumb-like session array. With every view you can pop a path onto the stack, and access the stack in the view (via the Session Helper) and construct the back button that way.
The stack could be as simple as a single parameter, or an array of controller, action and parameter variables to construct the path, depending on how much detail you need.
Edit: You could also use Neil Crookes' History Component: https://github.com/neilcrookes/cakephp-bits/blob/master/history_component/controllers/components/history.php
Use the breadcrump methods in the Html helper.
In your layout:
echo $this->Html->getCrumbs(' > ','Home');
In your view:
$this->Html->addCrumb('Users', '/users');
$this->Html->addCrumb('Add User', '/users/add');
In each of your views, you can add in a new crumb, or the chain of crumbs to be able to see a history of your actions.
More here: http://book.cakephp.org/view/1653/Creating-breadcrumb-trails-with-HtmlHelper

Resources