Unable to obtain instance of HTTP request in Laravel 5.8 - php

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!

Related

Illuminate\Validation\Factory::make(): Argument #1 ($data) must be of type array, App\Models\Product given

This is my controller function to store a product, i have the error in the $validator, i'm using this in the api route, i have the error of the title, i've try so many things and nothing works, please helpme, if i send in $validator the $req->all() it works, but i need to send a picture and thats why i'm using the $productReq, i'm using laravel 8
public function store(Request $req)
{
$productReq = new Product($req->all());
if ($req->file('file') == null) {
$req->file = "";
} else {
$image = $req->file('file')->store('public/images');
$url = Storage::url($image);
$productReq->file = $url;
}
$rules = array(
'name' => 'required',
'price' => 'required',
'file' => 'required|image'
);
$validator = Validator::make($productReq, $rules);
if ($validator->fails()) {
return response()->json([
'error' => true,
'response' => $validator->errors()
], 401);
} else {
$product = Product::create($productReq);
return response()->json([
'error' => false,
'response' => $product,
], 200);
}
}
Validator::make() expects an array of data to be provided to it. You've provided an instance of a Product, which Laravel doesn't know what to do with. What you want to do is validate your data before creating an instance of Product.
public function store(Request $req)
{
$rules = array(
'name' => 'required',
'price' => 'required',
'file' => 'required|image'
);
$validator = Validator::make($req->input(), $rules);
if ($validator->fails()) {
return response()->json([
'error' => true,
'response' => $validator->errors()
], 401);
}
$product = new Product($req->input());
if ($req->file('file') == null) {
$req->file = "";
} else {
$image = $req->file('file')->store('public/images');
$url = Storage::url($image);
$product->file = $url;
}
$product->save();
return response()->json([
'error' => false,
'response' => $product,
], 200);
}
You can also simplify the controller's logic by making use of some of Laravel's conveniences. However, it may produce responses that do not match what the front end expects (i.e. JSON message when a validation error is encountered).
public function store(Request $req)
{
// Laravel's `validate()` method on a Request will validate against the
// current request data and return the valid input. It will throw an Exception
// if validation fails, which Laravel will handle and reply with the validation errors.
$validatedInput = $req->validate([
'name' => 'required',
'price' => 'required',
'file' => 'required|image'
])
$product = new Product($validatedInput);
// ... file logic
$product->save();
// In Laravel, you can return an array from a controller. Laravel
// will assume it's supposed to be JSON, and encode it automatically for you
return [
'error' => false,
'response' => $product,
];
}

i am trying to save the image using the `Intervention \ Image library`. and I found an error Image source is not readable

public function store(Request $request)
{
$this->validate($request, [
'judul' => 'required',
'category_id' => 'required',
'konten' => 'required',
'gambar' => 'required',
]);
$gambar = $request->gambar;
$new_gambar = time().$gambar->getClientOriginalName();
$post = Posts::create([
'judul' => $request->judul,
'category_id' => $request->category_id,
'konten' => $request->konten,
'gambar' => 'public/uploads/posts/'.$new_gambar,
'slug' => Str::slug($request->judul),
'users_id' => Auth::id()
]);
$img = Image::make('public/uploads/',$gambar->getRealPath())->resize(300,
300)->save('public/uploads/', $gambar->getClientOriginalName());
$gambar->move('uploads', $new_gambar);
$post->tags()->attach($request->tags);
return redirect('post');
}
Add enctype in your html form
enctype="multipart/form-data"
And change for this in your controller:
$img = Image::make($request->file('gambar')->getRealPath());
Also check permissions of the directory in which you are uploading the file
make sure form has enctype:
<form class="form" ... enctype="multipart/form-data">
change controller
use Intervention\Image\ImageManagerStatic as Image;
public function store(Request $request)
{
$this->validate($request, [
// 'judul' => 'required',
//if judul column type is varchar need to set max varchar value or less
//varchar max 255, if higer than 255 strings, extra string will be truncated
'judul' => 'required|string|max:200',
// 'category_id' => 'required',
//category should exist
'category_id' => 'required|exists:categories,id',
'konten' => 'required',
// 'gambar' => 'required',
//validating image is successfully uploaded and is image format
'gambar' => 'required|file|image|mimes:jpg,jpeg,png',
//validation for tags, assuming 1 input <select name="tags[]" multiple="multiple"/>
'tags' => 'array',
'tags.*' => 'exists:tags,id'//each value of input select exists in tags table
]);
// $gambar = $request->gambar;
//get the file from <input type="file" name="gambar"/>
$gambar = $request->file('gambar');
$new_gambar = time().$gambar->getClientOriginalName();
//make path to save image: sample public path
$file_path = public_path("uploads/post/{$new_gambar}");
$img = Image::make($gambar)
->resize(300,300)
->save($file_path);
$post = Posts::create([
'judul' => $request->judul,
'category_id' => $request->category_id,
'konten' => $request->konten,
// 'gambar' => 'public/uploads/posts/'.$new_gambar,
//should maake the image first
'gambar' => $file_path,
'slug' => Str::slug($request->judul),
'users_id' => Auth::id() // <- if it is to get current logged in user, use Auth::user()->id
]);
// $gambar->move('uploads', $new_gambar); //let Intervention do this for you
// $post->tags()->attach($request->tags);
//if tags exists (get values frominput select)
$post->tags()->sync($request->input('tags', []));
//$request->input('tags', []) <- if input tags is not null get value, else use empty array
//if route have name e.g Route::get('post', 'PostController#post')->name('post');
//return redirect()->route('post');
return redirect('post');
}

SQL default value error when uploading files using laravel

i'm trying to upload multiple images using laravel and so far i've succeded, but the problem is that when i try to save text AND the files i get an error.
So far i've received so many errors that i can't remember all of then, but the latest is:
SQLSTATE[HY000]: General error: 1364 Field 'title' doesn't have a default value (SQL: insert into posts (image, updated_at, created_at) values (["italian.jpg"], 2019-05-23 18:48:22, 2019-05-23 18:48:22))
i've set the sql properly, and as i said, if i remove the image upload it works, and if i remove the text fields it also work, but if i try both i doesnt.
if i remember correctly when i remove the required fields it also works.
public function store(Request $request)
{
//dd($request);
$this->validate($request, [
'title' => 'required|min:3|max:120',
'text' => 'required',
'image' => 'required',
'image.*' => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048'
]);
if($request->hasfile('image')){
foreach($request->file('image') as $image)
{
$name=$image->getClientOriginalName();
$image->move(public_path().'/images/', $name);
$data[] = $name;
}
} else{
redirect('/posts')->with('Error', 'no image');
}
$post->image=json_encode($data);
$post = Post::create($validatedData);
return redirect('/posts')->with('success', 'yay');
}
i also tried this, but it returns
Creating default object from empty value
public function store(Request $request)
{
$validatedData = $request->validate([
'title' => 'required|min:3|max:120',
'category' => 'required|min:3|max:120',
'text' => 'required',
'image' => 'required',
'image.*' => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048',
]);
if($request->hasfile('image'))
{
foreach($request->file('image') as $image)
{
$name=$image->getClientOriginalName();
$image->move(public_path().'/images/', $name);
$data[] = $name;
}
}
$post = new Post();
$post->image=json_encode($data);
$post->save();
return back()->with('success', 'Yay');
}
i figured it out, hehe. just had to remove these lines:
'image' => 'required',
'image.*' => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048'
Thanks anyways.

Laravel request validation image required in create but not required in update

ProductsRequest.php code:
public function rules()
{
return [
'name' => 'required
|min:'.trans('validation_standards.names.min').'
|max:'.trans('validation_standards.names.max').'
|unique:products,name,'.$this -> product_id,
'barcode' => 'size:'.trans('validation_standards.barcode.size').'
|unique:products,barcode,'.$this -> product_id,
'category_id' => 'required
|exists:categories,id',
'seasons_id' => 'required
|exists:seasons,id',
// REQUIRED IMAGE ONLY IN STORE
'image' => 'required
|image|mimes:'.trans('validation_standards.images.extensions').'
|max:'.trans('validation_standards.images.file_size'),
'description' => 'nullable
|min:'.trans('validation_standards.descriptions.min').'
|max:'.trans('validation_standards.descriptions.max'),
];
}
These rules apply for both store and update methods.
Problem is:
I want the image to be required only on store and not required in update, since user can just update the product basic info without choosing a new image for the product every time he update the product.
What I have tried:
I have tried to create two different ProductsRequest one for store and other for update but I know that this achievement is not the best achievement because my code must be DRY.
Use required_without rules
If primary key and element with name is id exist in your array
'image' => 'required_without:id`
If primary key and element with name is product_id exist in your array
'image' => 'required_without:product_id`
You can get more detail from laravel validation
You can do this in your ProductsRequest file;
public function rules()
{
if(request()->isMethod('put')) // could be patch as well
{
// Update rules here - Don't require image here
return [
'name' => 'required
|min:'.trans('validation_standards.names.min').'
|max:'.trans('validation_standards.names.max').'
|unique:products,name,'.$this->product_id,
'barcode' => 'size:'.trans('validation_standards.barcode.size').'
|unique:products,barcode,'.$this->product_id,
'category_id' => 'required|exists:categories,id',
'seasons_id' => 'required|exists:seasons,id',
// REQUIRED IMAGE ONLY IN STORE
'image' => 'required|image|mimes:'.
trans('validation_standards.images.extensions').'
|max:'.trans('validation_standards.images.file_size'),
'description' => 'nullable
|min:'.trans('validation_standards.descriptions.min').'
|max:'.trans('validation_standards.descriptions.max'),
];
}else{
// store rules here - require image here
return [
'name' => 'required
|min:'.trans('validation_standards.names.min').'
|max:'.trans('validation_standards.names.max').'
|unique:products,name,'.$this->product_id,
'barcode' => 'size:'.trans('validation_standards.barcode.size').'
|unique:products,barcode,'.$this->product_id,
'category_id' => 'required|exists:categories,id',
'seasons_id' => 'required|exists:seasons,id',
// REQUIRED IMAGE ONLY IN STORE
'image' => 'image|mimes:'.
trans('validation_standards.images.extensions').'
|max:'.trans('validation_standards.images.file_size'),
'description' => 'nullable
|min:'.trans('validation_standards.descriptions.min').'
|max:'.trans('validation_standards.descriptions.max'),
];
}
}
}
public function rules()
{
$image = request()->isMethod('put') ? 'nullable|mimes:jpeg,jpg,png,gif,svg|max:8000' : 'required|mimes:jpeg,jpg,png,gif,svg|max:8000';
return [
'image' => $image,
];
}
If your route is something like this one (which should be)
Route::post('products/{id}/update', 'ProductController#updateProduct')->name('products.update');
And you will call this route as
route('products.update', $product->id);
$product->id will be available in your form request and you can validate your form request for both create and update like this.
public function rules() {
return [
// All other rules
'image' => $this->id == null ? 'required|image|mimes:'.
trans('validation_standards.images.extensions').'
|max:'.trans('validation_standards.images.file_size') :
'image|mimes:'.trans('validation_standards.images.extensions').'
|max:'.trans('validation_standards.images.file_size')
];
}
Just this few lines can solve your problems...
You have to check there image have or not, like this.
Rules in a private or protected function
private function validateRequest($request)
{
//This is for Update without required image, this will check that In DB image have or not
$product = Product::find($request->product_id);
$rules = [];
if ($product) :
if ($product->product_image == null):
$rules['product_image'] = 'required|image|max:1999';
endif;
//This is for regular validation
else :
$rules = [
'category_id' => 'required|integer|not_in:-- Select Category --',
'product_image' => 'required|image|max:1999',
];
endif;
return $rules;
}

Laravel image being posted to database as "/private/var/tmp/"

I'm trying to store an image in my Laravel project, but I'm having an issue. The image is sucessfuly being added to the /public/images folder as its filename, but when the request hits the database, its added as /private/var/tmp/XXXXX. I've tried to set $request->file as the name, but it still posts as the var/temp.
Controller
public function store(Request $request)
{
$rules = [
// 'address' => 'required',
// 'city' => 'required',
// 'postcode' => 'required',
// 'restDesc' => 'required',
// 'telNumb' => 'required',
// 'resWebsite' => 'required',
// 'restDesc' => 'required',
// 'business_id' => 'unique:busprofiles,business_id',
];
$customMessages = ["Message"];
if ($request->hasFile('file')) {
$request->file->store('public/uploads');
$filename = $request->file->getClientOriginalName();
$filesize = $request->file->getClientSize();
$request->file = $request->file->storeAs('public/uploads', $filename);
}
$this->validate($request, $rules, $customMessages);
Busprofile::create($request->all());
return redirect()->route('business.dashboard')
->with('success', 'Profile created successfully');
}
If it helps: return $request->file returns the correct URL.
The problem is in Busprofile::create($request->all());. You do indeed get the original filename with $filename = $request->file->getClientOriginalName(); but your request stays the same.
Create the array for the database entries manually, according to your database needs.
$data = ['filename' => $request->file->getClientOriginalName(),
...,
];
and
Busprofile::create($data);

Categories