How to Get Data From Model in Function With Laravel - laravel

Is it possible to get data from the model in a function? I want to get the SupplierID data from the Product model.
public function productAjax($id)
{
$product = new Producttext();
$products = $product->productexts($id);
$hitung_products = $products->count();
$suplierproduct = Company::select('id', 'CompanyName')
->where(['id' => $products->SupplierID])
->first();
}
However, on execution, I get the following error.
Property [SupplierID] does not exist on this collection instance.

If you have producttext ID then
$product = Producttext::find($id)
OR
$product = Producttext::where('id',$id)->first();
//test and check that you have it $product->SupplierID
$suplierproduct = Company::select('id', 'CompanyName')->where('id',$product->SupplierID)
->first();

You should try this:
public function productajax($id)
{
$products = Producttext::where('id',$id)->first();
$suplierproduct = Company::select('id', 'CompanyName')
->where(['id' => $products->SupplierID])
->first();
}

Related

Laravel 9 hasMany relationship not working

I have a model with a relationship with another model, when calling the relationship in the controller it gives me
Exception: Property [products] does not exist on the Eloquent builder instance.
model:
public function products(): HasMany
{
return $this->hasMany(CartProduct::class,'cart_id','id');
}
controller
public function showCartOfAuth()
{
$id =auth()->guard('customers')->user()->id;
$cart = Cart::where('customer_id',$id)->get();
$products = Cart::where('customer_id',$id)->products->get();
$response = [
'cart' => $cart,
'items' => $products
];
return response($response,200);
}
Can you try this, please: Cart::with('products')->where('customer_id',$id)->get();
The way you have implemented requires atleast two database queries.
One: $cart = Cart::where('customer_id',$id)->get();
Two: Cart::where('customer_id',$id)->first()->products; //maybe a third query to fetch the products
For better performance you should
public function showCartOfAuth()
{
$id =auth()->guard('customers')->user()->id;
// Either Option 1
// Possibly 2 database queries, one to fetch the Cart and another to fetch Products for the Cart
$cart = Cart::where('customer_id',$id)->first();
$products = $cart->products;
$response = [
'cart' => $cart,
'items' => $products
];
// OR Option 2
// One database query using eager loading
$cart = Cart::with('products')->where('customer_id', $id)->first();
$response = ['cart' => $cart];
return response($response,200);
}
If you use option 2 from above then instead of $items you can use $cart->products

retrieving related field in controller index function gives error but ok in show function

I define the relation in Company table (where I added the plural):
protected $table = 'companies';
public function country() {
return $this->belongsTo(Country::class, "country_id")->withDefault(['country' => 'unknown']);
}
I also did the same in the Country model.
When I use the following code in the controller show function it works:
public function show (Company $company) {
$company->country = $company->country()->pluck('country');
But if I use the same code in the index function in a loop, I get an error "Call to undefined method stdClass::country()":
public function index (Company $company) {
if (request('tag')) {
$companies = Tag::where('name',request('tag'))->firstOrFail()->companies;
$companies->page_title = "Businesses matching tag '".request('tag')."'";
} else {
$companies = DB::table('companies')
->where([['is_active', '=', '1']])
->orderBy('company')
->get();
}
foreach($companies as $key => $thisCompany) {
...
$thisCompany->country = $company->country()->pluck('country');
}
I guess it is due to the fact that $company is created in the loop and not passed through the function like in show(Company $company)... but I could not find how to solve this issue... so help will be appreciated.
I have added the model in the argument of the function and change the name of the $company variable in the loop by $thisCompany to avoid confusion with the $company model.
No error but the field $country->country does not contain the name of the country but "Illuminate\Support\Collection {#443 …1}"
Why is it so complicated? Please help...
Paul, sorry, I think I didn't explain myself well in the comments.
What I meant by "What about if you change DB::table('companies') by Company?", is to stop using DB Query Builder to use the Eloquent Company model.
Specifically in this segment of code:
$companies = DB::table('companies')
->where([['is_active', '=', '1']])
->orderBy('company')
->get();
So, it could be:
$companies = Company::where([['is_active', '=', '1']])
->orderBy('company')
->get();
The explanation is that in the first way (with DB Query Builder), the query will return a collection of generic objects (the PHP stdClass object) that do not know anything about the Company and its relationships.
On the other hand, if you use the Eloquent model Company, it will return a collection of Company objects, which do know about relationships, and specifically the relationship that you have defined as country.
Then, when you loop over the collection, you will be able to access the country relation of each Company object:
foreach($companies as $key => $company) {
//...
$company->country = $company->country()->pluck('country');
}
Finally, your code could looks like:
public function index () {
if (request('tag')) {
$companies = Tag::where('name',request('tag'))->firstOrFail()->companies;
$companies->page_title = "Businesses matching tag '".request('tag')."'";
} else {
$companies = Company::where([['is_active', '=', '1']])
->orderBy('company')
->get();
}
foreach($companies as $key => $company) {
//...
$company->country = $company->country()->pluck('country');
}
//...
}

Laravel filter of multiple variables from multiple models

Goodmorning
I'm trying to make a filter with multiple variables for example I want to filter my products on category (for example 'fruit') and then I want to filter on tag (for example 'sale') so as a result I get all my fruits that are on sale. I managed to write seperate filters in laravel for both category and tag, but if I leave them both active in my productsController they go against eachother. I think I have to write one function with if/else-statement but I don't know where to start. Can somebody help me with this please?
These are my functions in my productsController:
public function productsPerTag($id){
$tags = Tag::all();
$products = Product::with(['category','tag','photo'])->where(['tag_id','category_id'] ,'=', $id)->get();
return view('admin.products.index',compact('products','tags'));
}
public function productsPerCategory($id){
$categories = Category::all(); //om het speciefieke id op te vangen heb ik alle categories nodig
$products = Product::with(['category','tag','photo'])->where('category_id', '=', $id)->get();
return view('admin.products.index',compact('products','categories'));
}
These are my routes in web.php. I guess this will also have to change:
Route::get('admin/products/tag/{id}','AdminProductsController#productsPerTag')->name('admin.productsPerTag');
Route::get('admin/products/category/{id}','AdminProductsController#productsPerCategory')->name('admin.productsPerCategory');
For filter both
change your URL like
Route::get('admin/products/tag/{tag_id?}/{category_id?}','AdminProductsController#productsPerTag')->name('admin.productsPerTag');
Make your function into the controller like
public function productsPerTag($tagId = null, $categoryId = null){
$tags = Tag::all();
$categories = Category::all();
$query = Product::with(['category','tag','photo']);
if ($tagId) {
$query->where(['tag_id'] ,'=', $tagId);
}
if ($tagId) {
$query->where(['category_id'] ,'=', $categoryId);
}
$products = $query->get();
return view('admin.products.index',compact('products','tags', 'categories'));
}
You are trying to filter in your query but you pass only 1 parameter to your controller, which is not working.
1) You need to add your filters as query params in the URL, so your url will look like:
admin/products/tag/1?category_id=2
Query parameters are NOT to be put in the web.php. You use them like above when you use the URL and are optional.
2) Change your controller to accept filters:
public function productsPerTag(Request $request)
{
$categoryId = $request->input('category_id', '');
$tags = Tag::all();
$products = Product::with(['category', 'tag', 'photo'])
->where('tag_id', '=', $request->route()->parameter('id'))
->when((! empty($categoryId)), function (Builder $q) use ($categoryId) {
return $q->where('category_id', '=', $categoryId);
})
->get();
return view('admin.products.index', compact('products', 'tags'));
}
Keep in mind that while {id} is a $request->route()->parameter('id')
the query parameters are handled as $request->input('category_id') to retrieve them in controller.
Hope It will give you all you expected outcome if any modification needed let me know:
public function productList($tag_id = null , $category_id = null){
$tags = Tag::all();
$categories = Category::all();
if($tag_id && $category_id) {
$products = Product::with(['category','tag','photo'])
->where('tag_id' , $tag_id)
->where('category_id' , $category_id)
->get();
} elseif($tag_id && !$category_id) {
$products = Product::with(['category','tag','photo'])
->where('tag_id' , $tag_id)
->get();
} elseif($category_id && !$tag_id) {
$products = Product::with(['category','tag','photo'])
->where('category_id' , $category_id)
->get();
} elseif(!$category_id && !$tag_id) {
$products = Product::with(['category','tag','photo'])
->get();
}
return view('admin.products.index',compact(['products','tags','products']));
}
Route:
Route::get('admin/products/tag/{tag_id?}/{category_id?}','AdminProductsController#productsPerTag')->name('admin.productsPerTag');

How can i decode json data if i saved in array laravel?

I have 2 two tables: one is an admission and the other is a class table. I am saving class id in admission class field of admission table by json_encode method.
My controller
public function store(Request $request)
{
$inputs = $request->all();
$admission = new Admission;
$admission->school_id = Auth::User()->id;
$admission->admission_classes=json_encode($inputs['admission_classes']);
$admission->save();
}
My index function
public function index(Request $request) {
$school_id= Auth::user()->id;
$admissions= Admission::where('school_id',$school_id)->orderBy('id','desc')->paginate(10);
return view('frontend.index',compact('admissions','active_class'));
}
My view
#foreach($admissions as $i => $admission)
{{ $admission->admission_classes }}
#endforeach
I am getting data in this way:-
["1","2","4","5","6","7","8","9"]
But I want to get in this format:
Nursery,Class 1, Class2, Class3 etc
My class controller
class Classes extends Authenticatable
{
use EntrustUserTrait;
use Billable;
use Messagable;
protected $fillable = [
'name','status'
];
}
You need to save integer value in as json array and do the following code
$integerIDs = array_map('intval', $inputs['admission_classes']);
$admission->admission_classes= json_encode($integerIDs);
public function index(Request $request){
$admissions = DB::select('SELECT a.*, GROUP_CONCAT(c.name) as classes FROM academy as a LEFT JOIN class c ON JSON_CONTAINS(a.classes, CAST(c.id as JSON), '$') WHERE a.school_id =2 GROUP BY a.id');
$admissions = $this->arrayPaginator($admissions, $request);
return view('frontend.index',compact('admissions','active_class'));
}
public function arrayPaginator($array, $request)
{
$page = Input::get('page', 1);
$perPage = 10;
$offset = ($page * $perPage) - $perPage;
return new LengthAwarePaginator(array_slice($array, $offset,
$perPage, true), count($array), $perPage, $page,
['path' => $request->url(), 'query' => $request->query()]);
}
I have not checked the code hope this will help u to continue.......
The best way to achieve this would be to have a one-to-many relationship with App\Classes.
However, since you already have something up and running, I would probably do it like this.
First, I would cast admission_classes to an array. This makes sure that admission_classes will always be casted to an array whenever it is fetched. It makes it easier for us to work with it.
protected $casts = [
'admission_classes' => 'array'
];
Finally, while fetching your admission records, you would also need to map over it and hydrate the Classes from its ids. This is how I'd try to achieve it.
$admissions = Admission::where('school_id',$school_id)
->orderBy('id','desc')
->paginate(10)
->map(function($admission) {
return array_map(function($class) {
$class = Classes::find($class);
return isset($class) ? $class->name : '';
}, $admission->admission_classes);
});
You will notice that I wrapped the Classes::find() method into the optional() helper. This is because, in case, a record is not found, it will not fail.
Finally, to print your class names in your blade, you would do something like this:
implode(',', $admission->admission_classes);

Laravel 5 eloquent conditional chaining query

Need help on this simple code, what code should I replace at
$users = User::all(); so I can conditional chaining the scope method and paginate it at the end?
I tried initiate the User object with $users = new User(); and there is error, Trying to get property of non-object error when using at VIEW.
public function index()
{
// user search
$name = $this->request->name;
$email = $this->request->email;
$users = User::all();
if (!empty($name)) {
$users->name($name);
}
if (!empty($email)) {
$users->email($email);
}
$users->paginate(5);
return view('admin.users.index',compact('users'));
}
Thanks in advance
$users = DB::table('users');
$users = empty($email) ? $users->paginate(5) : $users->whereEmail($email)->paginate(5);
You do not need to check for a name if all users have an email, because email is always unique. That way to do the task is faster and more convinient.
In case, if you need to check name or anything else, you can use this:
$users = DB::table('users');
$users = empty($email) ? $users : $users->whereEmail($email);
$users = empty($name) ? $users : $users->whereName($name);
$users = $users->paginate(5);
Try this:
$users = new User;
if( !empty($name) )
$users->whereName($name);
if( !empty($email) )
$users->whereEmail($email);
$users =$users->paginate(5);
I found the answer from the following link
https://stackoverflow.com/a/21739314/417899
Eg code:
$users = new User;
if (!empty($name)) {
$users = $users->name($name);
}
$users = $users ->paginate(5);

Resources