Property [id] does not exist on this collection instance? - php

I want to show from UserController how many products the User used and user information. I have created two Resources for it. SO I search him using $id Here is My UserController code
public function show($id)
{
//
$user = User::find($id);
if (is_null($user)) {
return response()->json([
'message' => 'User Not Found',
'status' => 404
], 404);
}
$products = Product::where('user_id', $user->id)->get();
return response()->json([
'data' => new UserProductResource($products),
'status' => 200
], 200);
}
And here is my UserProductResource
<?php
namespace App\Http\Resources;
use App\Http\Resources\ProductResource;
use Illuminate\Http\Resources\Json\JsonResource;
class UserProductResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'first_name' => $this->first_name,
'last_name' => $this->last_name,
'profile_img' => $this->profile_img,
'products' => ProductResource::make($this->products),
];
}
}
And The error is
My Route is:
Route::get('/show-product/{id}', [UserController::class, 'showProduct']);

Try this solution:
You have a error in this query
$products = Product::where('user_id', $user_id)->get();
because $user_id is an object of the User, not a single value.
Your Code:
public function show($id)
{
//
$user_id = User::find($id);
if (is_null($user_id)) {
return response()->json([
'message' => 'User Not Found',
'status' => 404
], 404);
}
$products = Product::where('user_id', $user_id)->get();
return response()->json([
'data' => new UserProductResource($products),
'status' => 200
], 200);
}
New Code:
public function show($id)
{
//
$user = User::find($id);
if (is_null($user)) {
return response()->json([
'message' => 'User Not Found',
'status' => 404
], 404);
}
$products = Product::where('user_id', $user->id)->get();
return response()->json([
'data' => new UserProductResource($products),
'status' => 200
], 200);
}

find($id) returns an object so you cant pass object in where(). Replace your below line
$products = Product::where('user_id', $user_id)->get();
with this line
$products = Product::where('user_id', $user_id->id)->get();
it will work.

new UserProductResource($products)
Here Object of Products is passed in resource file and if we check fields in UserProductResource they look like fields existing in User model.
Will $products have any field or relation like products ?
$products is a collection so UserProductResource::collection() should be used.
Ideally you should make relationship between User and Product and do this
$user = User::with('products')->find($id);
if (is_null($user_id)) {
return response()->json([
'message' => 'User Not Found',
'status' => 404
], 404);
}
return response()->json([
'data' => new UserProductResource($user),
'status' => 200
], 200);
and as there can be multiple products in UserProductResource you can do this
'products' => ProductResource::collection($this->products),

Related

How can I store barcode inside validate request in Laravel

I have a code on the store function where I save product details. However, the barcode always return empty. I don't know how to save it with Product::create($data);'. Can I ask some direction?
$data = new Product;
$data->name = $request->name;
Do I need to save one by one on an object such as the one above?
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Product;
use Picqer;
class ProductsController extends Controller
{
public function index() {
$products = Product::orderBy('id')->get();
return view('products.index', compact('products'));
}
public function show(Product $product) {
return view('products.show', ['product' => $product]);
}
public function create() {
$products = Product::all();
return view('products.create', compact('products'));
}
public function edit(Product $product) {
return view('products.edit', compact('product'));
}
public function update(Request $request, Product $product) {
$request->validate([
'code' => 'required',
'barcode' => 'required',
'name' => 'required',
'description' => 'required|string|max:250',
'unit' => 'required|int',
'cost' => 'required',
'srp' => 'required',
'supplier' => 'required|string|max:250',
'quantity_left' => 'required',
'category' => 'required|string|max:250',
'delivered_date' => 'required|date',
'expiration_date' => 'required|date'
]);
$product->code = $request->code;
$product->barcode = $request->barcode;
$product->name = $request->name;
$product->description = $request->description;
$product->unit = $request->unit;
$product->cost = $request->cost;
$product->srp = $request->srp;
$product->supplier = $request->supplier;
$product->quantity_left = $request->quantity_left;
$product->category = $request->category;
$product->delivered_date = $request->delivered_date;
$product->expiration_date = $request->expiration_date;
$product->save();
return redirect()->route('products.index');
}
public function store(Request $request) {
$code = $request->code;
$generator = new Picqer\Barcode\BarcodeGeneratorHTML();
$barcode = $generator->getBarcode($code, $generator::TYPE_CODE_128);
$data = $request->validate([
'code' => 'required',
'barcode' => 'max:15|nullable',
'name' => 'required',
'description' => 'required|string|max:250',
'unit' => 'required|int',
'cost' => 'required',
'srp' => 'required',
'supplier' => 'required|string|max:250',
'quantity_left' => 'required',
'category' => 'required|string|max:250',
'delivered_date' => 'required|date',
'expiration_date' => 'required|date'
]);
Product::create($data);
return redirect()->route('products.index')->with('success', 'Product has been added!');
}
public function destroy(Product $product) {
$product->delete();
return back();
}
}
I think I just missed something. I've used this framework: https://github.com/picqer/php-barcode-generator
You need to overwrite the barcode coming from request with the one you generated.
$product = new Product();
$product->name = 'some name';
...
$product->barcode = $barcode;
$product->save();
I made this work by merging the two arrays:
$data = array_merge($data, ['barcode' => $barcode]);
Product::create($data);

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,
];
}

Hi i get this "Error Call to a member function update() on boolean" when updating image in Laravel

Can someone help me with this Laravel problem?
I get Error Call to a member function update() on boolean, when I edit and update Image for an ad.
So when I create a new Ad the image will store but when updating the Ad with a new image the old image stays and I get this error for this line in storeImage.
private function storeImage($ad){
if (request()->has('image')) {
$ad->update([
'image' => request()->image->store('uploads', 'public'),
]);
$image = Image::make(public_path('storage/' . $ad->image))->fit(300, 300, null, 'top-left');
$image->save();
}
}
This is my AdsController
public function edit($id)
{
$ad = Ad::find($id);
return view('ads.edit_ad', compact('ad', 'id'));
}
public function update(Request $request, $id)
{
$ad = Ad::find($id);
$user_id = Auth::user()->id;
$rules = [
'ad_title' => 'required',
'ad_description' => 'required',
'purpose' => 'required',
'image' => 'sometimes|file|image|max:5000',
];
$this->validate($request, $rules);
$title = $request->ad_title;
$is_negotialble = $request->negotiable ? $request->negotiable : 0;
$data = [
'title' => $request->ad_title,
'description' => $request->ad_description,
'type' => $request->type,
'price' => $request->price,
'purpose' => $request->purpose,
'address' => $request->address,
'user_id' => $user_id,
];
$updated_ad = $ad->update($data);
if ($updated_ad){
$this->storeImage($updated_ad);
}
return redirect()->back()->with('success','Ad Updated');
}
public function destroy(Ad $ad)
{
$ad->delete();
return redirect()->back()->with('success','Ad Deleted');
}
/**
* Listing
*/
public function listing(Request $request){
$ads = Ad::all();
$roles = Role::all();
return view('listing', compact('ads'));
}
public function myAds(){
$user = Auth::user();
$ads = $user->ads()->orderBy('id', 'desc')->paginate(20);
return view('ads.my_ads', compact('ads'));
}
private function storeImage($ad){
if (request()->has('image')) {
$ad->update([
'image' => request()->image->store('uploads', 'public'),
]);
$image = Image::make(public_path('storage/' . $ad->image))->fit(300, 300, null, 'top-left');
$image->save();
}
}
At the bottom of your update() function, try to change this:
if ($updated_ad){
$this->storeImage($updated_ad);
}
to this:
if ($updated_ad){
$this->storeImage($ad);
}
The Eloquent models update() function returns a boolean of whether the update completed successfully. After running the update() function on the $ad variable, it is mutated and contains the updated data, and you can use it as an argument in your storeImage() function.

How to select field name using with relation in laravel

I am trying to get field name using with relation:
My Code:
public function getAllUsers()
{
$users = User::with('userBasicInfo','roles:name')->get();
return response([
'status' => true,
'message' => "All Users",
'total' => count($users),
'data' => $users
], 200);
}
when i simply use $users = User::with('userBasicInfo','roles)->get();
it returns my record accurately and when I used $users = User::with('userBasicInfo','roles:name')->get();
It returns my null array of roles I also want to display name using roles: name but it returns nothing.
You should try this:
public function getAllUsers()
{
$users = DB::table('users')
->select('users.name','roles.name')
->join('userBasicInfo', 'users.userbasicinfo_id', '=', 'userBasicInfo.id')
->join('roles', 'users.roles_id', '=', 'roles.id')
->get();
OR
$users = User::with(['userBasicInfo','roles:name'])->get();
return response([
'status' => true,
'message' => "All Users",
'total' => count($users),
'data' => $users
], 200);
}

Create new record using 2amigos SelectizeDropDownList in Yii2

I am trying to implement the 2amigos SelectizeDropDownList widget in a form to add new values to a table directly within the dropdown.
I am using the model Book and the Model Author so basically want to be able to add a new author in the book form.
This is the book controller at the update function:
public function actionUpdate($id) {
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['index']);
} else {
return $this->render('update', [
'model' => $model,
'categories' => BookCategory::find()->active()->all(),
'publishers' => Publisher::find()->all(),
'copirights' => Copiright::find()->all(),
'authors' => Author::find()->all(),
]);
}
}
This is the form:
<?=
$form->field($model, 'author_id')->widget(SelectizeDropDownList::className(), [
// calls an action that returns a JSON object with matched
// tags
'loadUrl' => ['author/list'],
'value' => $authors,
'items' => \yii\helpers\ArrayHelper::map(\common\models\author::find()->orderBy('name')->asArray()->all(), 'id', 'name'),
'options' => [
'class' => 'form-control',
'id' => 'id'
],
'clientOptions' => [
'valueField' => 'id',
'labelField' => 'name',
'searchField' => ['name'],
'autosearch' => ['on'],
'create' => true,
'maxItems' => 1,
],
])
?>
And this is the function author controller:
public function actionList($query) {
$models = Author::findAllByName($query);
$items = [];
foreach ($models as $model) {
$items[] = ['id' => $model->id, 'name' => $model->name];
}
Yii::$app->response->format = \Yii::$app->response->format = 'json';
return $items;
}
The form works fine to load, filter, search and add new items.
But it is not inserting the new typed attribute in the author table.
Do I need to add something in the book controller?
How can I check if it is a new value or a change of an existing author?
Thanks a lot
I made it work with the following code, not sure the most elegant because i am checking the if the author_id is a number or a string.
In my case the author won't be a number anyway.
public function actionUpdate($id) {
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post())) {
$x = Yii::$app->request->post('Book');
$new_author = $x['author_id'];
if (!is_numeric($new_author)) {
$author = new Author();
$author->name = $new_author;
$author->save();
$model->author_id = $author->id;
}
if ($model->save()) {
return $this->redirect(['index']);
}
} else {
return $this->render('update', [
'model' => $model,
'categories' => BookCategory::find()->active()->all(),
'publishers' => Publisher::find()->all(),
'copirights' => Copiright::find()->all(),
'authors' => Author::find()->all(),
]);
}
}

Categories