Is CakePhp adding timestamp to my javascript files requested by ajax? - cakephp-2.0

I am using Pjax to fetch pages on my cakePhp website. I am getting an error due to the javascript being fetch again because it see's it as a new file due the .js?_=timestamp being added to it.
main.min.js?_=1425763395728
If a page is being requested by ajax does cakePhp add this? I cant think of any other reason why it is getting returned with a timestamp.
I am using CakePhp 2.5
UPDATE:
The issue was jQuery and this helped to remove the timestamp.
$.ajaxPrefilter(function( options, originalOptions, jqXHR ) {
if ( options.dataType == 'script' || originalOptions.dataType == 'script' ) {
options.cache = true;
}
});

I assume your Asset.timestamp config var is set to 'force'or true. Setting this to false will remove the query string timestamp from your assets. This is documented in the book: http://book.cakephp.org/2.0/en/development/configuration.html
The only downside is that browsers may cache your JavaScript and CSS files and might use out-of-date assets if you update them.
Edit
Since this didn't help the OP it's likely that the timestamp is not being added by CakePHP. I would look at 3rd party libraries your are using, specifically in JavaScript but potentially in any CakePHP plugins or PHP libraries to see if they may be adding the query string.
End Edit

Although OP posted the solution, the final check-marked answer did not offer a solution - the issue is not related to Asset.timestamp in CakePHP, but rather the default jquery ajax behavior, which (as OP already stated) can be adjusted by placing following code snippet before the ajax requests are called:
//Cache Ajax request script files
$.ajaxPrefilter(function( options, originalOptions, jqXHR ) {
if ( options.dataType == 'script' || originalOptions.dataType == 'script' ) {
options.cache = true;
}
});
OR
//Cache all Ajax request related files
$.ajaxPrefilter(function( options, originalOptions, jqXHR ) {
options.cache = true;
});
Took me a while to figure this post, so hopefully this note helps others find the answer quicker. Thanks Keith!

Related

Filter cached REST-Data vs multiple REST-calls

I'm building an Angular Shop-Frontend which consumes a REST-API with Restangular.
To get the articles from the API, I use Restangular.all("articles") and I setup Restangular to cache this request.
When I want to get one article from the API, for example on the article-detail page by it's linkname and later somewhere else (on the cart-summary) by it's id, I would need 3 REST-calls:
/api/articles
/api/articles?linkname=some_article
/api/articles/5
But actually, the data from the two later calls is already available from the cached first call.
So instead I thought about using the cached articles and filter them to save the additional REST-calls.
I built these functions into my ArticleService and it works as expected:
function getOne(articleId) {
var article = $q.defer();
restangular.all("articles").getList().then(function(articles) {
var filtered = $filter('filter')(wines, {id: articleId}, true);
article.resolve((filtered.length == 1) ? filtered[0] : null);
});
return article.promise;
}
function getOneByLinkname(linkname) {
var article = $q.defer();
restangular.all("articles").getList().then(function(articles) {
var filtered = $filter('filter')(articles, {linkname: linkname}, true);
article.resolve((filtered.length == 1) ? filtered[0] : null);
});
return article.promise;
}
My questions concerning this approach:
Are there any downsides I don't see right now? What would be the correct way to go? Is my approach legitimate, to have as little REST-calls as possible?
Thanks for your help.
Are there any downsides I don't see right now?
Depends on how the functionality of your application. If it requires real time data, then having REST calls performed to obtain the latest data would be a requirement.
What would be the correct way to go? Is my approach legitimate, to have as little REST-calls as possible?
Depends still. If you want, you can explore push data notifications, such that when your data from the server is changed or modified, you could push those info to your client. That way, the REST operations happens based on conditions you would have defined.

How can I de-cache AngularJS templates when they change on the server?

We have an Angular project where the templates have changed numerous times thanks to our "Agile" environment. Browsers seem to strongly cache the templates because of the html file type. This means that when business goes to our dev site after an update, they occasionally see the old templates. How can we make sure that when changes are made to the templates, the user downloads the new template instead of loading from the cache?
We use Jade and to prevent caching, we have a variable based on the time that gets appended to the end of our JS/CSS includes (style.css?v=2012881). Since we already have an 'appVersion' via this variable, I chose to expose that variable using an angular module and constant:
script.
angular.module('appVersion',[]).constant('appVersion',#{curDate});
In my main Angular module I have:
.config(['$httpProvider','appVersion',function($httpProvider,appVersion){
$httpProvider.interceptors.push(function() {
return {
'request': function(config) {
if(!config.cached && config.url.indexOf('.html') > -1){
if(config.url.indexOf("?") > -1){
config.url = config.url.replace("?","?v="+appVersion+"&");
}
else{
config.url += "?v="+appVersion;
}
}
return config;
}
};
});
}])
Since the templates are loaded using $http.get, I added an interceptor that detects if a request is a request for a template and appends the appVersion to the request if it is. That way we have the same versioning for the CSS, JS, and HTML.
Use tools like grunt-filerev (https://github.com/yeoman/grunt-filerev) for static revisioning. They basically add a file content hash, so that caching becomes impossible.

Cakephp check if referer is from local url

I'm struggeling a litte with my Cakephp 2.1 application.
I want to render a different layout, if the referer is from an external url. Sadly this is not working :
if($this->referer(null, true))
{
$this->layout = 'lightview';
}
else
{
$this->layout = 'default';
}
Any ideas how I can fix this?
Thanks in advance
You got a logical error here:
$this->referer(null, true) // true as second param: only internal
will only return the lightview layout if
there is a referer (not always the case)
internal referrer
So this is probably not what you want.
You cannot do that this easily. Sometimes there is just no referrer.
And even if there is you might still don't know if this person came from somewhere else and just "hid" the referrer. Or then browsed your site (creating internal referrers from here on).
You would need to store the initial result on first visit in the session to check against later on.
But even so your approach is highly inconsistent and very likely breakable...

What's the proper way to serve JSONP with CakePHP?

I want to serve JSONP content with CakePHP and was wondering what's the proper way of doing it so.
Currently I'm able to serve JSON content automatically by following this CakePHP guide.
Ok, I found a solution on this site. Basically you override the afterFilter method with:
public function afterFilter() {
parent::afterFilter();
if (empty($this->request->query['callback']) || $this->response->type() != 'application/json') {
return;
}
// jsonp response
App::uses('Sanitize', 'Utility');
$callbackFuncName = Sanitize::clean($this->request->query['callback']);
$out = $this->response->body();
$out = sprintf("%s(%s)", $callbackFuncName, $out);
$this->response->body($out);
}
I hope it helps someone else as well.
I've as yet not found a complete example of how to correctly return JSONP using CakePHP 2, so I'm going to write it down. OP asks for the correct way, but his answer doesn't use the native options available now in 2.4. For 2.4+, this is the correct method, straight from their documentation:
Set up your views to accept/use JSON (documentation):
Add Router::parseExtensions('json'); to your routes.php config file. This tells Cake to accept .json URI extensions
Add RequestHandler to the list of components in the controller you're going to be using
Cake gets smart here, and now offers you different views for normal requests and JSON/XML etc. requests, allowing you flexibility in how to return those results, if needed. You should now be able to access an action in your controller by:
using the URI /controller/action (which would use the view in /view/controller/action.ctp), OR
using the URI /controller/action.json (which would use the view in /view/controller/json/action.ctp)
If you don't want to define those views i.e. you don't need to do any further processing, and the response is ready to go, you can tell CakePHP to ignore the views and return the data immediately using _serialize. Using _serialize will tell Cake to format your response in the correct format (XML, JSON etc.), set the headers and return it as needed without you needing to do anything else (documentation). To take advantage of this magic:
Set the variables you want to return as you would a view variable i.e. $this->set('post', $post);
Tell Cake to serialize it into XML, JSON etc. by calling $this->set('_serialize', array('posts'));, where the parameter is the view variable you just set in the previous line
And that's it. All headers and responses will be taken over by Cake. This just leaves the JSONP to get working (documentation):
Tell Cake to consider the request a JSONP request by setting $this->set('_jsonp', true);, and Cake will go find the callback function name parameter, and format the response to work with that callback function name. Literally, setting that one parameter does all the work for you.
So, assuming you've set up Cake to accept .json requests, this is what your typical action could look like to work with JSONP:
public function getTheFirstPost()
$post = $this->Post->find('first');
$this->set(array(
'post' => $post, <-- Set the post in the view
'_serialize' => array('post'), <-- Tell cake to use that post
'_jsonp' => true <-- And wrap it in the callback function
)
);
And the JS:
$.ajax({
url: "/controller/get-the-first-post.json",
context: document.body,
dataType: 'jsonp'
}).done(function (data) {
console.log(data);
});
For CakePHP 2.4 and above, you can do this instead.
http://book.cakephp.org/2.0/en/views/json-and-xml-views.html#jsonp-response
So you can simply write:
$this->set('_jsonp', true);
in the relevant action.
Or you can simply write:
/**
*
* beforeRender method
*
* #return void
*/
public function beforeRender() {
parent::beforeRender();
$this->set('_jsonp', true);
}

CakePHP how to display related information

My order table includes customer filed , When add new order, after choose the customer name from dropdown list, I want the same page to display the information of customer, for example, address, phone number from customer table
How to do?
Thanks in advance...
Could you give me an example or related links? I don't know anything about AJAX, have no idea where to start.
Maybe this link: http://www.w3schools.com/ajax/ajax_database.asp, but it uses php not cakephp...
the code in example is : xmlhttp.open("GET","getuser.php?q="+str,true);
I don't know how to pass customer_id(q=str) to orderscontroller/getuser function.need help
You can use JsHelper to achieve the same you mentioned. Kindly try at your end, and provide some raw code so that peers can help you to do that.
Your code should be like this
function showCustomer(str)
{
var xmlhttp;
if (str=="")
{
document.getElementById("divtoDisplayInfo").innerHTML="";
return;
}
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("divtoDisplayInfo").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","/yoursite/controllername/action/str,true); //if you use redirect and windows environment
xmlhttp.send();
}
you should expect the view of that action so do the normal cake processing, get data in the controller, render view, if there is an error set the actions autorender to false.
but i will just advice you to download Jquery add to your cakephp framework this simple line
$("divToDisplayInfo's_ID").load("Controllername/action")
solves your problem.

Resources