Laravel method not recieving post data on $request - php

On Laravel 5.1 a method is not recivieng the post data.
This is my method where $request does not store the data sent by post.
class ProjectCommentController extends Controller
{
public function store(Request $request,$projectId)
{
$this->validate($request, [
'description' => ['required'],
'status' => ['required'],
'profile_id' => ['required']
]);
$project = Project::findOrFail($projectId);
return $project->comments()->save(new Comment([
'description' => $request->input('description'),
'status' => $request->input('status'),
'profile_id' => $request->input('profile_id')
]));
}
}
This is how I call it from my test:
public function testProjectCommentCreation()
{
$category = factory(\App\Category::class)->create();
$project = factory(\App\Project::class)->create([
"category_id" => $category->id
]);
$profile = factory(\App\Profile::class)->create();
$comment = factory(\App\Comment::class)->make([
"profile_id"=>$profile->id
]);
$this->post(route('api.projects.comments.store', ['projects' => $project->id]), $comment->jsonSerialize(), $this->jsonHeaders)
->seeInDatabase('comments', ['project_id'=>$project->id,'description'=>$comment->description])
->assertResponseOk();
}
This is what $comment->jsonSerialize() stores:
array(3) {
'description' =>
string(10) "zFG8bW7EIz"
'status' =>
string(6) "active"
'profile_id' =>
int(629)
}
And this is my route:
Route::resource('projects.comments','ProjectCommentController',['only'=>['index','store']]);
My method recieves $projectId from the URL and that is working but the request comes empty, without the data I send from $comment->jsonSerialize()

This was solved by removing the header
Content-type: application/json
I'm still not sure why it is not working with that header but it was not an error on the method or the test.

Does this work?
$this->post(route('api.projects.comments.store', ['projects' => $project->id]), $comment->toArray())
->seeInDatabase('comments', ['project_id'=>$project->id,'description'=>$comment->description])
->assertResponseOk();
Does anything show if you put dd($request->all()); in your store method?

Related

Call to a member function store() on null Laravel 8

When I click on save to update the data on my edit page, I get the following error.
call to a member function store() on null
public function update(User $user)
{
$this->authorize('update', $user->profile);
$data = request()->validate([
'title' => 'required',
'description' => 'required',
'url' => 'url',
'image' => '',
]);
$imagePath = request('image')
->store('profile', 'public');
$image = Image::make(public_path("storage/{$imagePath}"))
->fit(1000, 1000);
$image->save();
dd($data);
auth()->user->profile->update(array_merge(
['image' => $imagePath]
));
return redirect("/profile/{$user->id}");
}
As a result of $request->file('file') is returning null, and you are trying to call a method on null, resulting in the exception.
Due to the way Laravel handles PUT and PATCH requests, you will need to send your request in a POST request, and supply _method with the value PUT in the header. This is what Laravel expects.
'image' => 'required'

Unable to obtain instance of HTTP request in Laravel 5.8

I am having trouble retrieving form values using the Illuminate\Http\Request class.
I have an endpoint that creates a product and another that updates it set up like this
Route::post('products', 'ProductController#store');
Route::put('products/{product}', 'ProductController#update');
The store and update methods in the ProductController are
public function store(Request $request)
{
// validate inputs
$validator = Validator::make($request->all(), [
'name' => 'required',
'category' => 'required',
'status' => 'required',
'price' => 'required',
'image' => 'required|image|mimes:jpeg',
'interest' => 'required'
]);
// return 401 response if validation fails
if ($validator->fails()) {
return response()->json([$validator->errors()], 401);
}
// create & store the product
if ($product = Product::create([
'name' => $request->name,
'category' => $request->category,
'status' => $request->status,
'price' => $request->price,
'interest' => $request->interest,
])) {
// store the product image
$file = $request->file('image');
$destinationPath = "public/images/products";
$filename = 'pramopro_' . $product->name . '_' . $product->id . '.' . $file->extension();
Storage::putFileAs($destinationPath, $file, $filename);
ProductImage::create([
'product_id' => $product->id,
'name' => $filename
]);
}
// return new product
return new ProductResource($product);
}
public function update(Request $request, Product $product)
{
// dd($request);
// validate inputs
$validator = Validator::make($request->all(), [
'name' => 'required',
'category' => 'required',
'status' => 'required',
'price' => 'required',
'image' => 'required|image|mimes:jpeg',
'interest' => 'required'
]);
// return 401 response if validation fails
if ($validator->fails()) {
return response()->json([$validator->errors()], 401);
}
// update this product
if ($product) {
$product->update($request->all());
return new ProductResource($product);
} else {
return response()->json(["error" => "Not found"], 404);
}
}
Now when I test the endpoints in postman, I can successfully create a new product record. But if I try to update a product, I get a 401 unauthorized error even though all the required fields are filled. dd($request)returns null but dd($product) returns the product as expected.
Maybe I have been looking at it so hard so I have missed something. What am I doing wrong?
This is the reasons I think why the $request return null
The store and update request is same name. Two input name or select name or textarea name can't be the same name in the same web page. If its same it will always get the first one that is the reason why it is returning null because the first one is empty.
The name you're calling is incorrect
Hope it helps!

Laravel phpunit test failing authorization

I have a working api only application.
I am required to write a test decided to use laravel's phpunit test. This simple app allows only authenticated users can store, update or delete a book. Everyone else (authenticated or not) can retrieve a list of all books or view details of one book.
For my books test, I have written a test that first creates a user then a random token for the user. Then the token is passed using withHeaders when posting a new book record
class BooksTest extends TestCase
{
public function test_onlyAuthenticatedUserCanAddBookSuccessfully()
{
$user = factory(User::class)->create();
$token = str_random(10);
$book = factory(Book::class)->create();
$response = $this->withHeaders(['Authorization' => "Bearer $token"])
->json('POST', '/api/books', [
'title' => 'book post',
'author' => 'post author'
]);
$response->assertStatus(201);
}
}
Here I am using the default Laravel 5.6 UserFactory and my own BookFactory
$factory->define(Book::class, function (Faker $faker) {
return [
'title' => $faker->sentence,
'author' => $faker->name,
'user_id' => 1
];
});
$factory->define(Rating::class, function (Faker $faker) {
return [
'user_id' => 1,
'book_id' => mt_rand(1, 2),
'rating' => mt_rand(1, 5)
];
});
When I run the test, it fails and I get 401 instead of 200 which means the user is unauthorized.
I have a feeling that I have probably not set the $user in my test properly to be used during POST but I am not sure and really need help to get it right.
you can send headers in the fourth params of json() method as
$response = $this->json('POST', '/api/books', [
'title' => 'book post',
'author' => 'post author'
],['Authorization' => "Bearer $token"]);
since json method itself has provision to pass headers
or you can use post() method as
$response = $this->post('/api/books', [
'title' => 'book post',
'author' => 'post author'
],['Authorization' => "Bearer $token"]);
Try this instead hope this solves your issues
Not sure how authentication is hooked on your application, but you could try this:
...
$this->actingAs($user)
->jsonPost('/api/books', [
// ...
]);
$response->assertStatus(201);

Laravel Put/Patch Request

Im trying to do a Put/Patch Request, I am using Postman, this is my current Code:
class CustomerController extends Controller
{
public function getAllCustomer()
{
return Customer::get();
}
public function addNewCustomer(Request $request)
{
$validatedData = $request->validate([
'Title' => 'required',
'Name' => 'required|max:255',
'Surname' => 'required|max:255',
'Email' => 'required',
'Phone' => 'required',
'Password' => 'required',
'dateofBirth' => 'required'
]);
return \app\model\Customer::create($request->all());
}
public function update (Request $request , Customer $id)
{
$id->update($request->all());
}
And this my route:
Route::put('Customer/{id}' , 'CustomerController#update');
Im trying to insert some Parameters into Postman, but I think the way I do it is not correct, right now I do it like this:
Im not getting any Errors, but nothing is happening, maybe somebody knows a solution.
I want to Change the Name of the customer.
Thanks!
Try to set x-www-form-urlencoded for body in postman.

How do I get ONLY the validated data from a laravel FormRequest?

Lets say I have the following Custom Request:
class PlanRequest extends FormRequest
{
// ...
public function rules()
{
return
[
'name' => 'required|string|min:3|max:191',
'monthly_fee' => 'required|numeric|min:0',
'transaction_fee' => 'required|numeric|min:0',
'processing_fee' => 'required|numeric|min:0|max:100',
'annual_fee' => 'required|numeric|min:0',
'setup_fee' => 'required|numeric|min:0',
'organization_id' => 'exists:organizations,id',
];
}
}
When I access it from the controller, if I do $request->all(), it gives me ALL the data, including extra garbage data that isn't meant to be passed.
public function store(PlanRequest $request)
{
dd($request->all());
// This returns
[
'name' => 'value',
'monthly_fee' => '1.23',
'transaction_fee' => '1.23',
'processing_fee' => '1.23',
'annual_fee' => '1.23',
'setup_fee' => '1.23',
'organization_id' => null,
'foo' => 'bar', // This is not supposed to show up
];
}
How do I get ONLY the validated data without manually doing $request->only('name','monthly_fee', etc...)?
$request->validated() will return only the validated data.
Example:
public function store(Request $request)
{
$request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
$validatedData = $request->validated();
}
Alternate Solution:
$request->validate([rules...]) returns the only validated data if the validation passes.
Example:
public function store(Request $request)
{
$validatedData = $request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
}
OK... After I spent the time to type this question out, I figured I'd check the laravel "API" documentation: https://laravel.com/api/5.5/Illuminate/Foundation/Http/FormRequest.html
Looks like I can use $request->validated(). Wish they would say this in the Validation documentation. It makes my controller actions look pretty slick:
public function store(PlanRequest $request)
{
return response()->json(['plan' => Plan::create($request->validated())]);
}
This may be an old thread and some people might have used the Validator class instead of using the validator() helper function for request.
To those who fell under the latter category, you can use the validated() function to retrieve the array of validated values from request.
$validator = Validator::make($req->all(), [
// VALIDATION RULES
], [
// VALIDATION MESSAGE
]);
dd($validator->validated());
This returns an array of all the values that passed the validation.
This only starts appearing in the docs since Laravel 5.6 but it might work up to Laravel 5.2

Categories