I am trying to do the following:
http://www.mydomain.com/Foo/json_bar
in my routing file, I want to say anything going to Foo/json_* it should go to the appropriate action in the action.class.php file
ex:
Foo/json_bar1 -> public function executeBar1
Foo/json_bar2 -> public function executeBar2
Thanks
In that case, you could probably write a routing rule like this (untested):
my_rule:
url: /Foo/json_:action/
params: { module: myModule, sf_method: json }
This, because the :action parameter is a "magic" parameter, which sets the action. (Normally you set the action parameter in the params block.
The sf_method is optional, by the way, but it sets the request format as json. That way, any exceptions will also render in JSON, and the correct headers are set for json.
The best practice to do this by the way, would be:
my_rule:
url: /Foo/:action.:sf_method
params: { module: myModule }
In that case you can write a bar1 action. Going to /Foo/bar1.html will render the HTML, and /Foo/bar1.json will render a json response. Of course you're free the replace the :sf_method with json, and set the sf_method param, like in my first example.
Related
I am facing a very weird case in my angularjs app. In a factory, the following code works properly:
$http.put(apiBase + 'delete?id='+orderId);
Which obviously connects to an api to perform a PUT operation (it is called "delete" here but it actually only updates a flag in the record).
But the same code, when written this way, does not work:
$http.put(apiBase + 'delete', {
params: {
id: orderId
}
}
);
Which is funny, because I am using the exact same syntax in some other factories to hit similar APIs and they work!
I believe this is because the second argument of $http.put() is a data object, not a config object. You are passing a config object as the second parameter.
You could try:
$http.put(apiBase + 'delete', null, {
params: {
id: orderId
}
}
);
https://docs.angularjs.org/api/ng/service/$http#put
When using $http.put, you don't need to wrap your data in the config object. You can pass the data object directly, and then omit the third parameter:
$http.put(apiBase + 'delete', { id: orderId });
Your other factories probably work with the syntax stated in your question because you are making $http.get or $http.delete requests.
I have found that this slightly-different API for the various "shortcut" methods to be confusing enough that I almost think it's better to avoid them altogether. You can see the differences from the documentation where get and delete have two parameters:
get(url, [config]);
delete(url, [config]);
and most of the other shortcut methods have three:
post(url, data, [config]);
put(url, data, [config]);
Note that the [config] object is defined further up on that documentation page, which is where it defines that "params" property:
params – {Object.} – Map of strings or objects which
will be serialized with the paramSerializer and appended as GET
parameters.
I have a GET endpoint with URI as /user/user-id . The 'user-id' is the path variable here.
How can I set the path variable while making the GET request?
This is what I tried:-
$http.get('/user/:id',{
params: {id:key}
});
Instead of replacing the path variable, the id get appended as query param.
i.e my debugger show the request URL as 'http://localhost:8080/user/:id?id=test'
My expected resolved URL should be like 'http://localhost:8080/user/test'
$http's params object is meant for query strings, so key-value pairs you pass into params are output as query string keys and values.
$http.get('/user', {
params: { id: "test" }
});
Becomes: http://localhost:8080/user?id=test
If you need http://localhost:8080/user/test, you can either:
Construct the url yourself,
$http.get('/user/' + id);
Or, use $resource (specifically $resource.get https://docs.angularjs.org/api/ngResource/service/$resource). This is a little cleaner.
Why not something like this?:
var path = 'test';
$http.get('/user/' + path, {});
The declaration of the User resource would be something like:
factory('User', function($resource) {
return $resource('/api/user/:userId.json', {}, {
put: {method:'PUT', params: {userId:'#id'}},
});
})
As you can see the -default- parameter for the PUT method is the id attribute within the resource.
if you would like to test:
httpBackend.expectPUT('api/user/1.json').respond(200);
userResource.put();
httpBackend.flush();
I keep getting a failure in the test cause the actual URL that it's being generated is: 'api/user/.json'. The id attribute is not being included in the URL.
It makes sense because I haven't specified the id attribute to the mock object, I didn't because I don't know how to do it.
Thanks in advance.
The path should start with '/', and you need to pass in an ID to make the path match with what is generated in your code. The URL match is string match, so you need to guarantee the URL you expect to hit is exactly same as what is generated.
httpBackend.expectPUT('/api/user/1.json').respond(200);
userResource.put({id:1});
httpBackend.flush();
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);
}
I need to use dynamically JSON with data.TreeStore.
With this component, there is proxy "config", it need a path to JSON file.
My problem is, i can't write Json file in my application.
I would know, if i can generated JSON dynamically and pass it to url config into proxy?
For example :
Var trStore = Ext.create('Ext.Data.TreeStore',{
... // config
proxy {
type : 'ajax',
url : { id : 'id0', task :'task0', value : 'val0', ..... }
}
});
My URL is not a file url but is JSON generated with my own method !
How to build JSON for use it with TreeStore and without make file !?
I hope you understand my problem :)
Thanks a lot to help !
Your example looks like you want to pass static "inline data" to the TreeStore.
As far as I can see this is not possible with a bare TreeStore, since it does not have a data config option as the "normal" Store has. However, it is possible with a Treepanel.
You can pass your inline data to the TreeStore using the root config option of the Treepanel (not the TreeStore). It works in a very similar manner as the data config option of a "normal" Store:
Ext.create('Ext.tree.Panel', {
root: { id : 'id0', task :'task0', value : 'val0', children: [...], ... }
// ...
});
There are two caveats related to this:
The beta3 docs say root is boolean, that's wrong.
Because of a bug in beta3 you cannot use this together with rootVisible: false.
Remember that a "json file" is really just a text string, so you can generate that with PHP or your preferred server software.
For the url in the proxy, simply put in the url you use to run that function. Eg in my web app I have http://example.org/controller/getTree?output=json
This runs the getTree() function on my controller, and the function knows to return json.