JSON view in Recess Framework - php

I am trying to create an api with Recess and I have a question about its JsonView. Currently, if I do a GET request on, for example, /users/1 (which routes to a function that gets all the details for the user with id 1 and responds with Json), I get the following:
{"users":{"id":"1","username":null,"password":null,"datejoined":false}}
How can I make it so that I get the following instead:
{"id":"1","username":null,"password":null,"datejoined":false}
That is, I don't want all the details wrapped inside "users":{}.

By default, Recess's JsonView responds with the properties of your controller. So your $users property is getting directly encoded into JSON.
You can override this by returning a custom response object:
return new OkResponse($this->request, (array)$this->users);

Not sure about recess specifically, but if you are using JsonView method/function with an input parameter (array) $result, then changing $result to $result['users'] may give you the answer you are looking for.
For example using plain PHP:
first object: echo json_encode($result);
second object: echo json_encode($result['users']);

Related

Do all API responses need to explicitly be returned with a json function?

I'm getting into api controllers and am wondering if this index function:
public function index()
{
$data = DB::table('galleries')->get();
return response()->json($data);
}
inside my api controller has to be returned with response()->json() or if it is OK to just return the variable:
public function index()
{
$data = DB::table('galleries')->get();
return $data;
}
Both seem to work. Are there reasons to use the former one?
the return $data will just convert the $data into a json response. no header will be set and your frontend will not recognize it as a json object.
return response() will return a full Response instance. from the doc
Returning a full Response instance allows you to customize the response's HTTP status code and headers. A Response instance inherits from the Symfony\Component\HttpFoundation\Response class, which provides a variety of methods for building HTTP responses
for return response()->json() method
The json method will automatically set the Content-Type header to application/json, as well as convert the given array to JSON using the json_encode PHP function
so this will be recognised as json object in your frontend. Read more at laravel doc.
When you send something as a response which is not already an instance of a Response then Laravel will create a new instance of a Response with that as the content. When the response is sent and that object is an array (or arrayable) or something that is convertible to JSON then it is sent as a JSON response. At that point all relevant headers will be correct.
There are two parts of the source code to consider if you are curious on how this works:
The part that checks whether the response is already an instance of Response and constructs one if not
The part that decides whether a response content should be JSON
If you want my opinion then you should be doing response()->json(...) which creates a JsonResponse instance that has no chance to be ambiguous because otherwise you are relying on undocumented behavior which is subject to change.
Both seem , both are correct but if you send as json it will be formal and in the fornt-end site they can use easily

filters are not being executed

I'm writing a PHP 5.6 application using apigility 1.0.4 and zend framework 2.3.3
with apigility I created a new reset service called drink
and created a filed called "drink_flavor".
I used the following filters:
Zend\Filter\StringToLower
Zend\Filter\StringTrim
now I use postman to test it.
so i configured the url to http://url/drink
I'm sending post data with raw json with the following text:
{"drink_flavor" : " AAA"}
as you can see i have a space at the beginning and the letters are capital.
now if my controller code i have the following:
public function create($data)
{
die(var_export($data,1));
}
so i'm just printing the data.
if I understood everything correctly instead of getting ' AAA' i should have gotten 'aaa'
because of my filters but I still got the unmodified data which is " AAA".
any ideas what's missing?
You have to pull the data from you InputFilter to get the filtered data.
So inside your listener:
// Get filtered data
$inputFilter = $this->getInputFilter();
$data = $inputFilter->getValues();
And continue to use that $data array instead.
The $data param in your create method is the raw/unfiltered POST data.
You should be careful using that $data as a source for your methods since anything sent by the client will be in there.
I think this is not so clearly explained in the Apigility documentation and I think that a lot of users make this mistake. I wrote about this in an issue on GitHub.

Need to access associative array data created inside a class by json_decode from outside the class

I've been using procedural php for a long time but am still learning OOP. I was able to find a bit of code online that is in the form of a class and I am able to call a new instance of the class and use var_dump on a string to have it print JSON data to a web page. I can look at the results of the var_dump and see that it's returning exactly what I want. I'm then able to use json_decode on the same string to turn it into and associative array and then I can echo the values from within the class. The problem is, I need to use the array values in more code - it's great that I can confirm it by printing it to a web page but I need to use it... but I'm getting errors that state the array is undefined once I try to access it outside of the class.
I'm using this line to convert the data into an array:
$response_array = json_decode($body, true);
I've already confirmed that this works within the class by using this code to print some of the data:
echo $response_array['amount'];
and it works - I see it on the web page.
I've been using this code to create the new instance of the class:
$fdata = new FData();
$fdata->request($order_total, $cc_exp, $cc_number, $cc_name, $order_id, $customer_id);
(the function named 'request' is defined as a public function inside the class)
After that, I want to grab the $response_array so that I can store the returned data into a transactions table, i.e something like this:
$r = mysqli_query($dbc, "CALL add_transaction($order_id, $response_array['transaction_type'], $response_array['amount'], $response_array['exact_resp_code'], $response_array['exact_message'], $response_array['bank_resp_code'], $response_array['bank_message'], $response_array['sequence_no'], $response_array['retrieval_ref_no'], $response_array['transaction_tag'], $response_array['authorization_num'])");
but I keep getting an error saying that the array values are undefined.
Things I have already tried (and which failed) include:
Defining the variables as public inside the class, setting their value in the class, and then calling them outside the class...
public $amount = $response_array['amount'];
then using $amount in my procedure CALL --- I still get the error saying that $amount is undefined.
Using 'return', as in
return $response_array;
and still the error saying the values are undefined.
I tried embedding the entire rest of my code within the class, just copy/paste it in right after the json_decode... but for some reason it can't seem to then make the database calls and other things it needs to do.
I've been reading about __construct but I'm not sure if it applies or how to use it in this case...
I want to stress that I AM able to see the results I want when I use var_dump and echo from within the class.. I need to access the array created by json_decode OUTSIDE of the instance of the class.
Any advice would be greatly appreciated. Thanks.
Assuming your FData::request method ends with something like this...
$response_array = json_decode($body, true);
return $response_array;
and you call it like this...
$response_array = $fdata->request(...);
You should then be able to use $response_array in the calling scope.
Extra note; you should be using prepared statements with parameter binding instead of injecting values directly into your SQL statements.

get object data in mvc structure

I'm working with a PHP MVC Framework. Works really well. I like the separation of the business layer (model) with the business logic (controller). But i just stumbled upon a problem. Here's the thing:
Suppose i navigate to the following url:
http://localhost/user/showall/
In this case the userController.php is called and within that file there is a method showallAction() which gets executed.
In the showallAction() method i simply do a request to a model which gets all the users for me. Something like this:
public function showallAction()
{
// create userModel object
$users = new userModel();
// get all users and assign the data to a variable which can be accessed in the view
$this->view->users = $users->getAllUsers();
// render views
$this->view->render();
}
So this method gets all the users, assigns the data returned from the userModel to a variable and i can easily work with the returned data in my view. Just a typical MVC thing.
Now here comes the problem.
I also need to create a native iphone variant. Ofcourse the looks will be totally different. So all i actually want to do is to request this url:
http://localhost/user/showall/
And that it just gives me the array (in json format) back. So i can use that for the mobile development.
But this obviously can't be done right now because the showallAction() method assumes that it is for web browser display. It doesn't echo JSON formatted, instead it simply assings the array of users to a variable.
So that means i have to create another method "showallMobileAction()" in order to get the data, but specifically for the mobile device. But this is not an elegant solution. I'm sure that are better ways...
Anyone any idea how can i solve this problem??
In your situation i would modify the routing mechanism.
It would be useful, if you could add extension at the end of URL, which represents the format you expect, like :
http://foo.bar/news/latest >> HTML document
http://foo.bar/news/latest.html >> HTML document
http://foo.bar/news/latest.rss >> you RSS feed
http://foo.bar/news/latest.json >> data in JSON format
It's a simple pattern to recognize. And you can later expand this to add .. dunno .. pdf output, or Atom feeds.
Additionally , two comments :
Model is not a type of objects. Instead it is a layer, containing objects responsible for business logic, and objects responsible for data storage/retrieval.
View should be a full blown object, to which you bind the domain objects (objects responsible for business logic).
You could pass parameters to your url:
/user/showall/json
and get the third URL segment with a custom function or a built-in one. For instance, with CodeIgniter: $this->uri->segment(3).
Some frameworks will pass the additional parameters to your method. Just try this with the URL I wrote above:
public function showallAction()
{
print_r(func_get_args());
}
I'm not familiar with PHP MVC but in general terms I'd use the "accepts" HTML header field to request the response in either "text/html" or "text/json", the controller would check for the accepts type and return the response accordingly.

Zend Framework - need to access a GET parameter from a view

I am using the Zend framework and what I need is to construct a url in my view. Normally in regular php code I'd just grab the GET Variable by using the global $_GET. However with Zend I'm setting it to clean URIs so :
?ac=list&filter=works&page=2
Looks like
index/ac/list/filter/works/page/2
In my view I'm setting a links cs such that if the GET variable filter equals works then the color of that link would be different and it would point to the same page only linked as so:
index/ac/list/filter/extra/page/2
And like wise I have a number of other links all which just one GET value - how do I set this up - I am using the Zend framework.
To access a request variable direct in the view you could do:
Zend_Controller_Front::getInstance()->getRequest()->getParam('key');
But as others have said, this is not a good idea. It may be easier, but consider other options:
set the view variable in the controller
write a view helper that pulls the variable from the request object
If you need to access a GET parameter from a view, i think you're doing it the wrong way.
I suggest that you set up a route with all your parameters, and then use $this->url from your view to render a valid and correct url.
Fore som more info, check out the following blog post (no, i'm not the author):
http://naneau.nl/2007/07/08/use-the-url-view-helper-please/
Edit:
If you want to be 'lazy', you can set a view parameter from your controller by doing $this->view->param = $this->_getParam('param'). You can then access param from your view by doing echo $this->param;. However, i do not recommend this.
To access the Request Object one way that is common is to save it in the Registry.
http://osdir.com/ml/php.zend.framework.mvc/2007-08/msg00158.html
http://www.zfforums.com/zend-framework-components-13/model-view-controller-mvc-21/how-access-request-object-customizing-layout-view-3349.html
You can pass it in from a controller: $this->view->page = $this->_getParam('page');.
Footnote: I agree with #alexn.
i am using Zend Framework v1.11 and i am doing like this
In Controller
$this->view->request = $this->_request;
then in View you can access any Request param like this
<h3><?= $this->request->fullname ?></h3>

Categories