Eloquent Query With Custom Method - php

i am using laravel 7 eloquent. i am very new to laravel
this is basic method i am getting data from category table
public function category(){
$category = Category::orderBy('id', 'desc')->get();
$data['pageData'] = $category;
$data['pageTitle'] = "Category";
return view('admin.category.index')->with('data',$data);
}
But i want to do something like this
public function category(){
$category = Category::orderBy('id', 'desc')->get();
if(!empty($_REQUEST['parent_id']))
$category->where('parent_id',$_REQUEST['parent_id']);
$data['pageData'] = $category;
$data['pageTitle'] = "Category";
return view('admin.category.index')->with('data',$data);
}
So how can this is possible using eloquent.
Any help out of this question are helpful for me as i am beginner.

Try this
public function category(){
$query = Category::orderBy('id','desc');
$query = where('parent_id',$_REQUEST['parent_id']);
$category = $query->get();
$data['pageData'] = $category;
$data['pageTitle'] = 'Category';
return view('admin.category.index')->with('data',$data);
}

You can leverage the when() eloquent method to add conditional clause to query:
public function category()
{
$category = Category::when(request('parent_id'),function($parent_id,$query)
{
$query->where('parent_id',$parent_id);
})->orderBy('id', 'desc')->get();
$data['pageData'] = $category;
$data['pageTitle'] = "Category";
return view('admin.category.index')->with('data',$data);
}
when() doc reference https://laravel.com/docs/8.x/queries#conditional-clauses

You can use the when method to only apply the query if the request contains the parent_id.
From the docs:
Sometimes you may want certain query clauses to apply to a query based
on another condition. For instance, you may only want to apply a where
statement if a given input value is present on the incoming HTTP
request. You may accomplish this using the when method:
$role = $request->input('role');
$users = DB::table('users')
->when($role, function ($query, $role) {
return $query->where('role_id', $role);
})
->get();
The when method only executes the given closure when the first
argument is true. If the first argument is false, the closure will not
be executed. So, in the example above, the closure given to the when
method will only be invoked if the role field is present on the
incoming request and evaluates to true.
In your case it would be the following:
use Illuminate\Http\Request;
public function category(Request $request)
{
$categories = Category::query()
->when($request->input('parent_id'), function ($query, $parent_id) {
$query->where('parent_id', $parent_id);
})
->orderBy('id', 'desc')
->get();
$data['pageData'] = $categories;
$data['pageTitle'] = "Category";
return view('admin.category.index')->with('data', $data);
}

You can do as like below
public function category(){
$category = new Category();
if(!empty($_REQUEST['parent_id'])){
$category->where('parent_id',$_REQUEST['parent_id']);
}
$category = $category->orderBy('id', 'desc')->get()
$data['pageData'] = $category;
$data['pageTitle'] = "Category";
return view('admin.category.index')->with('data',$data);
}

Try using laravel when condition
https://laravel.com/docs/8.x/queries#conditional-clauses

Improve your question with proper details. as you mention in the question the second coding path won't work because it doesn't have $request query to functionally run the if statement. anyhow if you want to get only pageData & pageTitle in laravel Eloquent ORM you have to select both columns as follows.
class CategoryController extends Controller
{
public function category(){
$category = Category::select('pageData', 'pageTitle')->orderBy('id', 'desc')->get();
return view('admin.category.index')->with('data', $category);
}
}

Related

Laravel Eloquent Model with relationship

I have implemented eloquent relationship in my code but Laravel unable to read the function that I created to map the eloquent relationship in the model.
User Model
public function products(){
return $this->hasMany(Product::class,'userid');
}
Product Model
public function users(){
return $this->belongsTo(User::class);
}
Product Controller
$products = Product::with('Users')->Users()->where('users.isActive',1)->get();
return view('product',compact('products'));
I keep getting error from the product controller, I also attached the error that I current encountered as below.
How can I get all the product and user data with the where condition such as "Users.isActive = 1".
Thanks.
You can use whereHas to filter from a relationship.
$products = Product::with('users')
->whereHas('users', function ($query) {
$query->where('isActive', 1);
})
->get();
Also it is generally a good idea to use singular noun for belongsTo relationship because it returns an object, not a collection.
public function user() {
return $this->belongsTo(User::class);
}
$products = Product::with('user')
->whereHas('user', function ($query) {
$query->where('isActive', 1);
})
->get();
EDIT
If you want to retrieve users with products you should query with User model.
$users = User::with('products')
->where('isActive', 1)
->get();
Then you can retrieve both users and products by
foreach($users as $user) {
$user->products;
// or
foreach($users->products as $product) {
$product;
}
}
You can use whereHas() method for this purpose. Here is the doc
$products = Product::with('users')->whereHas('users', function (Illuminate\Database\Eloquent\Builder $query) {
$query->where('isActive', 1);
})->get();
$users = $products->pluck('users');
return view('product',compact('products'));
You have a typo after the with, is users instead of Users and you're redundant about the Query Builder, remove the ->Users():
Before:
$products = Product::with('Users')->Users()->where('users.isActive',1)->get();
return view('product',compact('products'));
After:
$products = Product::with('users')->where('users.isActive',1)->get();
return view('product',compact('products'));
Fix that and all should work.

How to get Billing Address from Eloquent model with where clause?

For example I can use:
$address = $user->address
which will return the addresses for the user.
// User.php (model)
public function address()
{
return $this->hasMany(Address::class, 'refer_id', 'id');
}
public function billingAddress()
{
return $this->address()
->where('type', '=', 1)
->where('refer_id', '=', $this->id)
->first();
}
However, I would like to return the BillingAddress for the user depending on this where clause. How do I do it?
EDIT:
If I use this inside... OrderController#index it returns correctly
$orders = Order::with('order_fulfillment', 'cart.product', 'user.address', 'payment')->get();
return new OrderResource($orders);
However, If I change it to:
$orders = Order::with('order_fulfillment', 'cart.product', 'user.billingAddress', 'payment')->get();
return new OrderResource($orders);
I get this error:
Symfony\Component\Debug\Exception\FatalThrowableError
Call to a member function addEagerConstraints() on null
One option is you can use whereHas in your query. For example,
$orders = Order::with('order_fulfillment', 'cart.product', 'user.address', 'payment')
->whereHas(
'address', function ($query) {
$query->where('type', '=', 1)
->first();
}
)->get();
return new OrderResource($orders);
This is one option. try to dd($orders) an find if its working.
You had an another option like this, in your model
public function address()
{
return $this->hasMany(Address::class, 'refer_id', 'id');
}
Add relations like
public function billingAddress()
{
return $this->hasOne(Address::class, 'refer_id', 'id')->where('type', 1);
}
And
public function shippingAddress()
{
return $this->hasOne(Address::class, 'refer_id', 'id')->where('type', 2);
}
Then in your query,
$orders = Order::with('order_fulfillment', 'cart.product', 'user.address','user.billingAddress', 'user.shippingAddress', 'payment')->get(); return new OrderResource($orders);

Having difficulties displaying all content on my wishlist table

I am trying to retrieve the data on my wishlist table, for a particular user, so far it only retrieves the first data on the table, just returning one array instead of the three in the table with same user id
public function getWishlistByUserId($id){
$wishlists = Wishlist::where('userId', $id)->get();
foreach($wishlists as $wishlist){
$products = Product::where('id', $wishlist->productId)->get();
return $products;
}
}
It happens because the foreach loop returns a value during the first iteration. Place your return statement outside the loop. Also you could improve your performence by making use of relationships.
An example could be:
// Product.php
public function wishlists()
{
return $this->hasMany(Wishlist::class);
}
// Your method
public function getWishlistByUserId($id)
{
return Product::whereHas('wishlists', function ($query) use ($id) {
$query->where('userId', $id);
});
}
Ideally this is n+1 situation
So i will suggest to use laravel relationship like:
in your whishlist model
public function product(){
return $this->hasMany(Product::class,'productId','id');
}
get data with relationship
public function getWishlistByUserId($id){
$wishlists = Wishlist::with('product')->where('userId', $id)->get();
}
I was finally able to get it working this way, i just pushed the result into an array, and then returned it outside the loop, thanks everyone for your help
public function getWishlistByUserId($id){
$wishlists = Wishlist::where('userId', $id)->get();
$wishlist = [];
foreach($wishlists as $wish){
$product = Product::where('id', $wish->productId)->get();
array_push($wishlist, $product);
}
return $wishlist;
}

Relationship not working. Foreach. Laravel

So I have defined relationship between OrderProduct.php and 'Product.php' models like this:
OrderProduct.php:
public function product()
{
return $this->belongsTo('App\Product');
}
Product.php
public function order()
{
return $this->belongsTo('App\OrderProduct');
}
OrderController function
public function orderShow($id)
{
//$order = Order::where('id', $id)->first();
$products = OrderProduct::where('id', 32)->first();
return view('admin.orders.show', compact('order', 'products'));
}
When I do this foreach:
#foreach($products as $product)
<?php dd($product) ?>
#endforeach
I get Invalid argument supplied for foreach() How to fix this ?
You've got only first record from set.
Try
public function orderShow($id)
{
//$order = Order::where('id', $id)->get();
$products = OrderProduct::where('id', 32)->get();
return view('admin.orders.show', compact('order', 'products'));
}
EDIT
If you need to retrieve particular record by id, use find() or even findOrFail() method (difference you can find in docs);
public function orderShow($id)
{
// this will retrieve record with id=32 from db if it exists,
// and throw Illuminate\Database\Eloquent\ModelNotFoundExceptio otherw
$product = OrderProduct::findOrFail(32);
return view( 'admin.orders.show', compact('product') );
}
then in your blade template you can access your $product info as an object, like so
{{ $product->name }}
{{ $product->otherProductProperty }}
You are giving
$products = OrderProduct::where('id', 32)->first();
which will fetch you only one record the result will not be a collection so you cannot do foreach for this
You can change it as
$products = OrderProduct::where('id', 32)->get();
to make it work
You need to even check the Relationship used. One will be belongs to and the other will be hasmany
you should try like this..
public function orderShow($id)
{
//$order = Order::where('id', $id)->get();
$products = OrderProduct::where('id', 32)->with('product')->get();
return view('admin.orders.show', compact('order', 'products'));
}

Unable to assign variable value in model constructor

I am playing with Laravel models and I need one to return a value that is not in the db table but it comes by running a model method. This method runs a query that groups and count grouped results.
The model method works just fine but I don't seem to be able to pre-fill the $quantity variable within the constructor with something different than 0.
So this is an excerpt of the model:
public $quantity;
function __construct($attributes = array(), $exists = false) {
parent::__construct($attributes, $exists);
$this->quantity = $this->quantity();
}
public function quantity()
{
$query = DB::table('carts_shopping')
->select('cart_id', DB::raw('COUNT(*) AS quantity'))
->where('cart_id',$this->cart_id)
->groupBy('cart_id')
->first();
return ($query) ? $query->quantity : 0;
}
While this is how I am trying to retrieve the results from controller:
$cartitems = Auth::user()->cartshopping;
foreach ($cartitems as $cartitem)
{
echo $cartitem->name;
echo $cartitem->quantity;
}
As you may guess 'cartshopping' comes from the user model being related with the model excerpt I pasted.
I also noticed that quantity() method gets called and it returns 0 all the time as if $this->cart_id was empty and, changing $this-cart_id with a real value the query itself doesn't even get executed.
Thanks a lot for any suggestion you guys can share.
Have you tried accessing the properties using $this->attributes?
public $quantity;
function __construct($attributes = array(), $exists = false) {
parent::__construct($attributes, $exists);
$this->quantity = $this->quantity();
}
public function quantity() {
$query = DB::table('carts_shopping')
->select('cart_id', DB::raw('COUNT(*) AS quantity'))
->where('cart_id', $this->attributes['cart_id'])
->groupBy('cart_id')
->first();
return ($query) ? $query->quantity : 0;
}
Failing that, you could try using the Eloquent accessors, which would be the best way to do it. This would make it dynamic as well, which could be useful.
class YourModel {
// Normal model data here
public function getQuantityAttribute() {
$query = DB::table('carts_shopping')
->select('cart_id', DB::raw('COUNT(*) AS quantity'))
->where('cart_id', $this->attributes['cart_id'])
->groupBy('cart_id')
->first();
return ($query) ? $query->quantity : 0;
}
}

Categories