CakePHP: How to use the same controller function to render 2 pages - cakephp

I wish to have a page called "index" with a corresponding url "domain/controller/index" and another
page called "admin_index" with a corresponding url "domain/admin/controller/index".
The trick is that i want both pages to use the same view to render and the same function for the logic while on of the page's parameters are a flag indicating to the view from which url the view is rendered.
I need it because currently in my "index" page I have table with data.
The page also has a smart filter for that page which requires a respectful amount of logic in the controller side.
My problem is that currently there is an "Edit" button in each line which I don't want to share to all the users.
Currently I'm using the admin prefix to handle this kind of pages by protecting them by limiting the access from the web-server (Apache in my case).
Any ideas of how to implement this without duplicating the controller function?

Try this (I've tested it on my CakePHP 2.0.x app, but there's nothing in this code that should be 2.0 specific):
//controller
public function index($admin = false) {
$this->set(compact('admin'));
}
public function admin_index() {
$this->index(true); //calls the index function to do all that stuff
$this->render('index'); //tells it to render the 'index' view
}
When you hit the /index page, all should be as normal. When you hit the admin_index, it runs the logic from the index function, then specifies to use the index view.

Related

google analytics page views are being incremented incorrectly for each page change (angularjs)

I'm using Google analytics for my website (built using AngularJS) to track page views. For some reason though, the page views are incremented incorrectly. For example, when I'm on home page and I switch to the about page, about page gets 1 view, which is correct, but when I switch to another page, that page gets 2 views when it should just get 1. When I switch to another page, that page gets 3 views and so on until I reload the website. Reloading the website will reset the incrementation back to 1, and it'll start counting up again, which means there appears to be a count that is incremented with each state change.
I have this code in all the controllers for each page:
$rootScope.$on('$stateChangeSuccess', function(event) {
if (!$window.ga)
return;
$window.ga('send', 'pageview', { page: $location.path() });
});
What is the cause of the tracking error and how can I resolve it?
$stateChangeSuccess is a global event, which means that if you include the above code in every controller, every time a new controller is instantiated, you are creating a new listener for the event. When a state change occurs, every listener you have registered gets fired, thus the increasing number of calls that are happening.
You actually only need to do this once, probably in your main module run() method, rather than in all of your controllers.

How to make a search with separate views in Angularjs?

How can I have an index page accept search input and then return the result in different page (view) with angularjs?
All the tutorials I have gone through on the internet shows search box that accepts the query and instantly prints results beneath it on the same page (or say "view" in MVC language?). I want a separate page to just hold the search box, let user type what it wants and then hit go button which then return results on a separate page (which does not have the search box).
You need to store the search box value somewhere before going to the second page. You can do this in several ways.
One way would be to use a service to store the value, then the result page can retrieve it from there.
The service:
.service('CommonService', function(){
this.value = '';
});
The search controller:
.controller('search', function(CommonService){
$scope.goToResult = function(searchBoxValue){
CommonService.value = searchBoxValue;
// Redirect to result view
};
});
This function could be on the ng-submit of the search form.
The result controller:
.controller('result', function(CommonService){
// Receive value of search box
$scope.receivedValue = CommonService.value;
});
Another way would be to send the value along the URL, like GET params:
http://google.com/q?SearchBoxValue=something-i-wrote-before
are you implementing single page application (SPA)? you can do this multiple way with partial view and override partial view on search page with result page.
search page (partial) hit send request to get data.
receive data from service
redirect to result (partial view).
you done.
hope this help you.

Whats the Advantage of Marionette AppRouter+Controller over Backbone.Router?

From my understanding, the differences is the callback functions to events on an AppRouter should exist in the Controller, instead of the same Router object. Also there is a one-to-one relationship between such AppRouter & Controllers, all my code from Router now moves to Controller, I don't see too much point of that? So why use them? I must be missing something?
The way I see it is to separate concerns:
the controller actually does the work (assembling the data, instanciating the view, displaying them in regions, etc.), and can update the URL to reflect the application's state (e.g. displayed content)
the router simply triggers the controller action based on the URL that has been entered in the address bar
So basically, if you're on your app's starting page, it should work fine without needing any routers: your actions (e.g. clicking on a menu entry) simply fire the various controller actions.
Then, you add on a router saying "if this URL is called, execute this controller action". And within your controller you update the displayed URL with navigate("my_url_goes_here"). Notice you do NOT pass trigger: true.
For more info, check out Derick's blog post http://lostechies.com/derickbailey/2011/08/28/dont-execute-a-backbone-js-route-handler-from-your-code/ (paragraph "The “AHA!” Moment Regarding Router.Navigate’s Second Argument")
I've also covered the topic in more length in the free preview of my book on Marionette. See pages 32-46 here: http://samples.leanpub.com/marionette-gentle-introduction-sample.pdf
I made some override for the router. And currently use it in this way (like Chaplin):
https://gist.github.com/vermilion1/5525972
appRoutes : {
// route : controller#method
'search' : 'search#search'
'*any' : 'common#notFound'
},
initialize : function () {
this.common = new Common();
this.search = new Search();
}

Single Page website with CakePHP

I'm currently working on a single-page scrollable website (5 pages displaying as a single page) using CakePHP. I have worked on each controller action and everything runs well. I have one layout for the entire app and a view for each action. My challenge is finding a way to load the view of each action without reloading the page inside the layout. Should I just put all the view content inside the layout (without echoing $content_for_layout) or could there be a better way to do it?
Considering the div you want to update has the id #content:
$.ajax({
url:"http://yourdomain.com/controller/action",
context:document.body,
dataType:"html",
data:{id:123}, // in case you need to pass some params
success:function(data){
$("#content").html(data);
}
})
The action must return the HTML you want to display inside that div. If you want to have each pags loaded in different div's, you will have to create one div for each page and call AJAX for each one.
When the page is loaded for the first time, you can just pull the data for whatever default action you defined. Then, when you want to change the content, just call AJAX.

CakePHP dynamic element

I am trying to create a message-board type element in a CakePHP app. This element will be displayed on all pages and views that use a particular layout. I want it to display all the messages in the model, then show the add form when a link is clicked, then return to the updated message list when submitted. All this without affecting the current view/page.
I have my message model/controller/index set up, with a message board element that requests the index action. This works fine. However I am perplexed about how to return back to the original page/action from which the link was clicked. I can't use $this->referer() because that will link back to the add() action; what I want rather is to link to the page/view before that.
Any general pointers on how to achieve something like this?
I would approach this using Ajax, and use an ajax layout.
$this->layout('ajax')
Then you would be able to setup a full stack for processing this, and pass various things in as parameters into the controller actions.
By using Ajax you will not need to worry about passing in the referrer controller / action pair. You can also use the return from this to update the list by calling out to the MessagesController. The added bonus of this is that you can just switch the layout in your actual controllers, thus not having to write any extra code at all.
In your controller, you can check for Ajax
if($this->params['requested']){
$this->layout('ajax');
return $data;
}else{
$this->set('data',$data);
}

Resources