Laravel API patch method - php

I am developing a laravel api and sucessfully made gets, posts, deletes and i am now trying to do the update method using PATCH.
Here is my first try:
public function update($id, Request $request)
{
$taxes = taxes::find($id);
$taxes ->fill($request->only(['$request']));
$taxes->save();
}
And testing it with the follow url on postman
****.local/api/taxes/1?description=test
This obviously doesnt work, i tought i would be able to see the error but i am currently on a different machine but hopefully someone can guide me to correct path to make this update method.
Dont forget its an api, no views/forms.
Thank you.

You have to specify the body of the query (so the variables you want to change) in the x-www-form-urlencoded tab of the Body tab for your request in Postman.
You can find a screenshot here: http://img11.hostingpics.net/pics/987644Sanstitre1.jpg (waiting for imgur to be back online)
You also have an issue in your method, your code should be the following:
public function update($id, Request $request)
{
$taxes = taxes::find($id);
$taxes ->fill($request->only(['description', 'anyotherfield', '...']));
$taxes->save();
}

Could be to do with this line: $request->only(['$request']), as your request is unlikely to have a parameter called $request. You might've been meaning to use $request->all() (all input) or $request->only('description', 'etc.') which will whitelist given paramters.
Probably should give your model a singular name, and capitalize it.
Tax::findOrFail($id)->update($request->only('description'))

Related

Authorization returns false in Form Request

In a form request, I need to check whether a user can update or not a Vehicle. I have the following method:
public function authorize()
{
$vehicle = Vehicle::find($this->route('vehicle'));
return $vehicle and $this->user()->can('update', $vehicle);
}
I checked with dd and $this->user()->can('update', $vehicle) returns false even if I put the return value of the update policy to true. I tried the policy in a controller and I had no issue. It's like the can method can't find the update policy while it is registered.
Why does not it work?
This looks like an issue I saw a long time ago when using route() in the pull for the class - it seems to pull an array. As you said this is not what is reflected in the documentation.
Take a look at the Laravel bug report here.
There are potential work-arounds if this is indeed your issue. Quoted from the issue page (insert vehicle for user, or whatever):
$route = $request->route();
$user_id = is_array($route) ? $route[2]['user_id'] : $route->parameter('user_id');
Pretty ugly, I know. But you could also change your architecture slightly and pull the id in like you would in a normal controller method if you wanted, sort of like:
public function myNewPreAuthThing(Request $request, $id){}
And then send the correct id through to the auth. Either way it's not clean, I know. But... I think you have hit on a know bug.

Laravel - check request method

I'm an iOS lead on an app and trying to fix some API bugs whilst our dev is 'unavailable'. I'm almost completely new to Laravel and trying to check what the request method is. I have followed some guidance from another question but have been unable to get it working:
public function defaults(Request $request, User $user){
$follow_ids = explode(',', env('FOLLOW_DEFAULTS'));
if ($request->isMethod('post')) {
return ['user' => $user];
}
$user->follows()->syncWithoutDetaching($follow_ids);
return ['user.follows' => $user->follows->toArray()];
}
Do you know where I might be going wrong here? Thanks in advance.
When the request is returned it always just seems to skip over and return ['user.follows' => $user->follows->toArray()]
$request should be an instance of Illuminate\Http\Request. This class extends Symfony's request (Symfony\Component\HttpFoundation\Request), which is actually where the isMethod() method is defined.
Basically, given the function definition as posted, it reads "if this is a POST request, just return the user data. if this is not a POST request (e.g. GET), update and return the relationship data."
So, if you send a POST request, you'll get the ['user' => $user] response. If you send any other request method (e.g. GET), you'll modify the follows relationship and get the ['user.follows' => $user->follows->toArray()] response.
To me, this seems backwards. I would think you'd want the POST request to update the data, and any other request (e.g. GET) to just return data.
If this is correct, you need to negate your isMethod check:
if (! $request->isMethod('post')) {
return ['user' => $user];
}
More appropriately you should define separate controller actions to handle POST vs GET requests, but that is outside the scope of this question, and probably more than you want to get into as a temporary maintainer.
It seems that the request is not a POST so the if check is never true. You could echo the method name like this:
$method = $request->method();
echo $method;
// or var_dump($method);

How to handle eager loading on REST API

Imagine you have the following resources for example: Users, Posts and Comments (With typical relationship setup in laravel).
When fetching a single Post, you will have the following endpoint
GET /api/posts/1
// With route model binding
public function show(Post $post)
{
return $post;
}
This is fine if I only want the Post object, but in some pages in my application, I also need to load the User and the Comments associated with the Post.
How do you guys handle that kind of scenario?
1. Should I load everything in that endpoint like:
return $post->load(['user', 'comments.user']);
and call it a day? (nope)
2. Should I accept an additional parameter that will tell my controller to load the relationship based on that value?
// With route model binding
public function show(Request $request, Post $post)
{
// rel for "relationship"
if ($request->has('rel')) {
$post->load($request->input('rel'));
}
return $post;
}
with this approach I could do something like this:
GET /api/posts/1?rel=user
returns Post with User
or I could build an array of parameter with jquery's $.param(['user', 'comments.user'])
GET /api/posts/1?rel%5B%5D=user&rel%5B%5D=comments.user
returns Post with User + Comments.User
but anyone can easily mess with the 'rel' parameter so I also need to check that
¯\(°_o)/¯
3. Just create a new endpoint for every specific requirements. (what should your endpoint look like for the example above?).
I'm building a SPA with Angular + Laravel (just a self-consumed API) for my Internal Project when I encounter this pitfall. The second approach is what I currently using for basic fetching and I use the third approach for more complex requirements.
Any inputs are appreciated.

how to pass data from one application to another in Laravel?

I want to pass data from one application to another in Laravel..
Suppose I want to take user data from one application and I want to send this data to another application form.
I wanted to send it this way..But I'm getting Error..
So if anyone could suggest any solution for this..would be appreciated ..
public function store(Request $request)
{
$payment = new Payment();
$payment->username = $request->Input(['username']);
$payment->price = $request->Input(['price']);
$payment->purchase_id = $request->Input(['purchase_id']);
$payment->save();
$store_id =\Hash::make($payment->id);
$price = $payment->price;
return \Redirect::to('http://localhost/blog/public/getPayment');
}
And I get the following Error:
InvalidArgumentException in Response.php line 462:
The HTTP status code "0" is not valid.
If you just want your user to be redirected to another app so they can fill whatever forms you can use
return Redirect::away('http://localhost/blog/public/getPayment');
See the method here.
BUT
If you want to send data to another app without redirecting the user, the best solution I can give is to make an API on this other app so you can make requests (with Guzzle or something else) to this API, allowing you to pass some data.

Best Practices and how to find get POST data from iOS AFNetworking in Symfony2 and return JSON in GET?

I am building a mobile app (iOS) and Symfony2 REST backend. On Symfony2, my routes are working correctly and I have tested them with AJAX and httpie, all CRUD operations, etc are fine. Now, I am trying to access the routes from the app. So far, I can access the routes and when I look into the Symfony2 Profiler, I can see entries in last 10 entries to verify that I am hitting the server with my POST and GET requests. Now, I have 2 questions and I would be glad if people can point me in the direction for ** Best Practices ** on how to proceed.
Problem 1: Although I am posting data which I can see coming in under "Request", when I try to create a record, it creates only NULL records, meaning the data is being lost. This is my controller for creating users for example:
public function postUserAction(Request $request)
{
$content = $this->get('request')->getContent();
$serializer = $this->get('jms_serializer');
$entity = $serializer->deserialize($content, 'Name\BundleName\Entity\User', 'json');
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return array(
'entity' => $entity,
);
}
When I look into the log, the only things that stand out are: Request Cookies (No cookies), Request Content: "Request content not available (it was retrieved as a resource)." This tells me the data was missing, how can I get this data and use it? Or what else could it be?
Problem 2: GET returns an empty JSON response with no data just the keys when I NSlog (echo it). My code looks like:
public function getUsersAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('NameBundle:User')->findAll();
return array(
'entities' => $entities,
);
}
From the log, it has the Request Cookies set: PHPSESSID => "1udududjjs83883jdlb4ho0j4" but again the Request Content says: "Request content not available (it was retrieved as a resource)." How can I make it return the data with the JSON? This works well in the browser AJAX and httpie tests.
Problem 3: Using AFNetworking, I have a symbolic constant which I set as the APIHost (IP Address) and APIPath was the folder. Now in my earlier version using native PHP, I constructed the actual code to be executed in index.php by sending the parameter in JSON so if I wanted a login, I sent something like todo:login but with Symfony2, I am not sure or know even the best practices for this case. Ideally, I would like to specify the server-side request in the JSON request and then find the correct route in Symfony2 but is this how to do it and if yes, can you please provide an example? The workaround is to specify hard coded paths in AFNetworking each time I need to make a request which I think tightly couples the code and I need to make changes in a lot of places anytime something changes on the server side. Thanks and sorry for the long question!
You expect the jmsserializer to do magic for you. But it won't, you have to configure it first. From you code I can see that you are using jmsserializer wrong.
In getUsersAction() you have to return a serialized response, but you are returning an array of objects. This would be the right way:
public function getUsersAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('NameBundle:User')->findAll();
$serializer = $container->get('jms_serializer');
return array(
'users' => $jsonContent = $serializer->serialize($entities, 'json');,
);
}
Your post action basically looks ok, however when the json does not contain every field of entity USER the deserialization will fail. You can configure the entity for serialization/deserialization using annotations.
http://jmsyst.com/libs/serializer/master/reference/annotations
I am not sure if I understood your last problem, but I think you have to hardcode the path in your app.
Symfony2 is great and absolutely useful when writing an API. But if you don't want to deal with serialization/deserialization you can give http://laravel.com/ a try. It is build on symfony and you can generate an api on the fly.

Categories