Select column from relations relation in laravel - laravel

I'm trying to do eager loading using with() method, I only want to get selected column from relations relation, how can I do that ? . I'm using polymorphic relation.
Draft::with(["user:id,username","article:id,locale","article.articleable:title"])->where([
["user_id",$user_id],
["is_suspended",1]
])->get();
Draft Model
public function article()
{
return $this->belongsTo("App\Models\Article");
}
Article Model
public function drafts()
{
return $this->hasMany("App\Models\Draft", "article_id", "id");
}
public function articleable()
{
return $this->morphTo();
}
other models which has polymorphic relation with Article model
public function articles()
{
return $this->morphMany("App\Models\Article", "articleable");
}

This has been fixed in Laravel 5.7.6: https://github.com/laravel/framework/pull/25662
In order for this to work, you also have to select the id column:
Draft::with('user:id,username', 'article:id,locale', 'article.articleable:id,title')
^^
->where([
['user_id', $user_id],
['is_suspended', 1]
])->get();

Related

Restricting hasMany relationship where child.field != parent.field without joins

I'm looking for a way to qualify a hasMany relationship to exclude/include children where the value a specific child field does/not match that of a specific parent field without using joins.
The issue with joins is that the ->select() filters out many descendant relationships (unless they are each added to the join, which is too much to manage). The descendant relationships for example would be order_item.options which is a belongsToMany of OrderItem.
Case in point:
class Order extends Model
{
public function items()
{
return $this->hasMany(OrderItem::class, 'order_id', 'id');
}
public function items_removed_by_store()
{
return $this->hasMany(OrderItem::class, 'order_id', 'id')
//->join('order', 'order_item.order_id', 'order.id')
//->where('order_item.deleted_by', '!=', 'order.customer_id')
//->select('order_item.*', 'order.customer_id')
->onlyTrashed();
}
public function items_removed_by_customer()
{
return $this->hasMany(OrderItem::class, 'order_id', 'id')
//->join('order', 'order_item.order_id', 'order.id')
//->where('order_item.deleted_by', '=', 'order.customer_id')
//->select('order_item.*', 'order.customer_id')
->onlyTrashed();
}
}
and I'm looking to query it like:
Location::has('orders.items_removed_by_customer')->get()
Get me locations where customers have removed items from their orders.
It seems like you are currently joining the relationship on its parent. Note you already have the parent data
Maybe try something like this
class Order extends Model
{
public function items()
{
// Note: it is not required to pass 'order_id', 'id' to this method as thats the default value
return $this->hasMany(OrderItem::class);
}
public function items_removed_by_store()
{
return $this->items()
->where('order_items.deleted_by', '!=', $this->customer_id)
->onlyTrashed();
}
public function items_removed_by_customer()
{
return $this->items()
->where('order_item.deleted_by', '=', $this->customer_id)
->onlyTrashed();
}
}

How to write this same code and get same data in eloquent relationship ... laravel

How to write this same code and get same data in eloquent relationship
public function index(){
$data = DB::table('categories')
->join('subcategories', 'categories.id', 'subcategories.cat_id')
->select('categories.*', 'subcategories.*')->paginate(5);
return view ('admin.subcategory.index', compact('data'));
}
You need to create hasMany relationship between Category and Subcategory.
Category model
class Category extends Model
{
public function subcategories()
{
return $this->hasMany('App\Subcategory','cat_id','id');
}
}
Now you can call with('subcategories')
Category::with('subcategories')->paginate(5)

Laravel how to get only relation data

this is my User.php relation code
public function activities()
{
return $this->hasMany(Activities::class, 'builder');
}
and this is my query to get only relation data
return User::whereHas('activities', fn($query) => $query->where('user_id', 1))
->paginate();
but it returns only user data without appling any relation, and its pagination not get to use pluck
i have also tried this
User::where('username', request()->username)->has('activities')->paginate();
but i need only get relation data not user with relation, and i prefer do it with whereHas
You need to create reverse relation for Activities model:
class Activities extends Model
{
// ...
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
}
And get all the activities using Activities builder:
$paginated = Acitivities::query()
->whereHas('user', static function(Builder $userQuery) {
$userQuery->where('name', request()->username); // Think about security!
})
->paginate();
Note: All the models must be named in singular (e.g. Activity, User, Product and etc.).

Merge two hasOne relation in laravel - Eloquent

I have two table one is product and secound is RelatedProduct
where related product is connected with products.id and sometime with product.parent_id
public function relationWithId()
{
return $this->hasOne('App\RelatedProduct', 'product_id', 'id');
}
public function relationWithParent()
{
return $this->hasOne('App\RelatedProduct', 'product_id', 'parent_id');
}
so need a third relation where I can merge above both like this
public function relationProduct()
{
/*****/
}
Product::where('status', '=', 'active')->with('relationProduct')->get();
thanks in advance
Try creating the accessor which merges the two relationship and returns the collections.
public function getRelatedProductAttribute($value){
$withId = $this->relationWithId;
$withParentId = $this->relationWithParent;
return $withId->push($withParentId);
}

Laravel: One to Many to Many, retrieve distinct() values

Laravel 4 Project, using Eloquent ORM.
I have three tables: customers, orders and products (+ 1 pivot table order_product). Customers are linked one-to-many to Orders. Orders are linked many-to-many to Products.
Customers 1-->N Orders N<-->N Products
I would like to have a method on Customer model that retrieves a list of products that customer is buying.
To better understand this, assume products are consumable.
For example Customer #1 can place:
Order #1 for Products A, B and C;
Order #2 for Products A, C and D;
Order #3 for Products C and E;
...and the result I want to retrieve is a Collection with Products A, B, C, D and E.
Models are (pseudo-coded on the fly):
class Product extends Eloquent {
public function orders()
{
return $this->belongsToMany('Order');
}
}
class Orders extends Eloquent {
public function customer()
{
return $this->belongsTo('Customer', 'customer_id');
}
public function products()
{
return $this->belongsToMany('Product');
}
}
class Customers extends Eloquent {
public function orders()
{
return $this->hasMany('Orders', 'customer_id');
}
public function products()
{
// What to put here ???
}
}
Thanks to #deczo's answer, I was able to put up a single query method to retrieve items:
public function items()
{
$query = DB::table('items')->select('items.*')
->join('item_order', 'item_order.component_id', '=', 'items.id')
->leftJoin('orders', 'item_order.order_id', '=', 'orders.id')
->leftJoin('customers', 'customers.id' , '=', 'orders.customer_id')
->where('customers.id', $this->id)
->distinct()
->orderBy('items.id');
$eloquent = new Illuminate\Database\Eloquent\Builder( $query );
$eloquent->setModel( new Item );
return $eloquent->get();
}
This is a Many-to-Many relationship, but with the Orders table as the pivot table.
class Customers extends Eloquent {
public function orders()
{
return $this->hasMany('Orders', 'customer_id');
}
public function products()
{
return $this->belongsToMany('Products', 'orders', 'customer_id', 'product_id');
}
}
I've included the last two parameters, but if you follow the singular_id pattern they can be left out.
It's possible to receive distinct Product models like this:
public function products()
{
return $this->belongsToMany('Products', 'orders', 'customer_id', 'product_id')
->distinct();
}
#deczo's answer probably works fine, and is probably a lot more performant as all the data reduction is done in the database itself, but here's a 'pure Laravel' way that's undoubtedly more readable:
use Illuminate\Database\Eloquent\Collection;
class Customer extends Eloquent
{
...
public function products()
{
$products = new Collection;
foreach ($this->orders as $order) {
$products = $products->merge($order->products);
}
return $products;
}
}
Note that this method will not act like normal relationship methods - to get the resulting collection you call the method (i.e. $products = $customer->products();) and you can't access it as a property like you can with relationships (i.e. you can't do $products = $customer->products;).
Also, I'm kinda going on my understanding of the Illuminate\Database\Eloquent\Collection#merge() method here that it automatically does a DISTINCT-like thing. If not, you'll have to do a $collection->unique() kinda thing.
I can't think of easy relation method for this one, but here's a workaround:
$productsIds = DB::table('customers')
->leftJoin('orders', 'orders.customer_id', '=', 'customers.id')
->join('order_item', 'order_item.order_id', '=', 'orders.id')
->leftJoin('items', 'order_item.item_id' , '=', 'items.id')
->distinct()
->get(['items.id']);
$productsIds = array_fetch($productsIds, 'id');
$productsCollection = Product::whereIn('id', $productsIds);

Resources