I have a question with laravel relationship OneToMany. My database have 2 table product and product_entry. Product will have infomation to choose same price... and product_entry will have infomation about infomation.
1 Product have have many product_entry will another language. But site only 1 language in the same time, so have anyway i only choose product_entry have product_entry_language same current language?
Ex: i have 1 product a with language "en" and "es". Normal, current language is "en". In blade, i must foreach product->product_entries and if(product_entry_language == "en") { ** get Info **} => I want don't need run foreach
Model
class Product extends Model
{
use TransformableTrait;
protected $table = 'product';
protected $fillable = ['product_code','product_id'];
public function entries()
{
return $this->hasMany('App\Entities\ProductEntry', 'product_entry_product_id', 'product_id');
}
}
class ProductEntry extends Model
{
use TransformableTrait;
protected $table = 'product_entry';
protected $fillable = ['product_entry_product_id','product_entry_name'];
}
You can do this by
Product::with(['entries' => function ($q) {
$q->where('product_entry_language', \App::getLocale());
}])->get();
\App::getLocale() is the current laravel locale
Use a constraint, for example:
Product::with(['product_entry' => function ($q) use($language) {
$q->where('language', $language);
}])->get();
Where product_entry is relationship name.
Related
Hello I have a question:
I have three things :
Top Category
Category
Product
I want to have this : Top Category -> Category -> Product
So I can get all nested information to one Top Category
My Models :
class Overcategory extends Model
{
use HasFactory;
protected $fillable = [
'name',
'img',
];
public function categories()
{
return $this->belongstoMany(Category::class);
}
}
class Category extends Model
{
use HasFactory;
protected $fillable = [
'category_title',
'category_description',
'category_preview_img',
'over_categories_id',
'order',
'price'
];
public function product()
{
return $this->belongstoMany(Product::class);
}
public function overcategories()
{
return $this->belongstoMany(Overcategory::class);
}
}
class Product extends Model
{
use HasFactory;
protected $fillable = [
'product_title',
'product_desc',
'product_preview_img',
'product_price',
];
public function category()
{
return $this->belongstoMany(Category::class);
}
}
And my code to get the Top Category with Category is this :
$relationsship = Overcategory::with('categories')->get();
How would I get the categories with their product too?
In order to get all Overcategory with their Category and their Product, you can use the dot notation when you eager load the relationships.
$relationsship = Overcategory::with('categories.product')->get();
// will get you all the Overcategories with a Categories relationshiop and inside each Category, the Products will be loaded.
This also works the exact same way when you are working on eloquent collections instead of a query builder, with the load method instead of with.
If you want to read more on this topic, here is the documentation https://laravel.com/docs/9.x/eloquent-relationships#querying-relationship-existence.
Quick note aside, if a relationship returns multiple items (which is the case with product) it should be plural (products).
I have a scenario where User has a belongsToMany relation with PortalBreakdown, PortalBreakdown has a belongsTo relation with Portal. Portal has order column in it. I have a method listing_quota($id) in UserController which returns all breakdowns of the user. I want to sort these breakdowns based on order column of the portal. Below are the code of classes and a method I have tried.
class User extends Model {
protected $table = 'user';
public function listing_quota() {
return $this->belongsToMany('App\PortalBreakdown', 'user_listing_quota')->withPivot(['quota']);
}
}
class PortalBreakdown extends Model {
protected $table = 'portal_breakdown';
public function portal() {
return $this->belongsTo('App\Portal');
}
}
class Portal extends Model {
protected $table = "portal";
protected $fillable = ['name', 'description', 'order'];
}
Below is the method where I am trying to return sorted by order. I tried few things some of which can be seen in commented code but not working.
class UserController extends Controller {
public function listing_quota($id)
{
$user = User::with(['listing_quota' => function ($query) use ($id) {
// $query->sortBy(function ($query) {
// return $query->portal->order;
// });
}, 'listing_quota.portal:id,name,order'])->findOrFail($id);
// $user = User::with(['listing_quota.portal' => function ($q) {
// $q->select(['id', 'name',order']);
// $q->orderBy('order');
// }])->findOrFail($id);
return $this->success($user->listing_quota);
}
}
I also tried chaining orderBy directly after relation in Model class but that's also not working from me. Thank you in advance.
NOTE: I am using Laravel Framework Lumen (5.7.8) (Laravel Components 5.7.*)
I have two models Song and Album.
Song is Taggable(using eloquent-taggable).
1)Song belongs_to Album.
Album has columns name and language.
I want to get all tags of Song for a particular Album language.
I tried
Song::join('albums','albums.id','=','songs.album_id')
->where('albums.language', 'hindi')
->allTags()->orderBy('count', 'DESC')->get();
But not working.
allTags is a static method that should be called on the model directly. When you start to add constraints or chain on relationship method to an Eloquent model an instance of Builder will be returned.
I would suggest, if you haven't already done so, to create a Tag model that extends \Cviebrock\EloquentTaggable\Models\Tag and then define a relationship for the songs. Your model will then look something like:
namespace App;
class Tag extends \Cviebrock\EloquentTaggable\Models\Tag
{
/**
* Songs Relationship.
*
* #return \Illuminate\Database\Eloquent\Relations\MorphToMany
*/
public function songs()
{
return $this->morphedByMany(Song::class, 'taggable', 'taggable_taggables', 'tag_id', 'taggable_id');
}
}
If you already have the model but don't have the relationship then simply add the above relationship to that model.
Then you should be able to get all of the Tags with:
$tags = Tag::whereHas('songs.artist', function ($query) {
$query->where('language', 'hindi');
})->orderBy('count', 'DESC')->get();
If you don't want to create a new model that you could do something like:
Song::with('tags')
->whereHas('artist', function ($query) {
$query->where('language', 'hindi');
})
->get()
->flatMap(function ($song) {
return $song->tags;
})
->unique()
->sortByDesc('count');
For more information on collection please have a look at the documentation
At first create relation on song and album as :
namespace App;
use Illuminate\Database\Eloquent\Model;
use Cviebrock\EloquentTaggable\Taggable;
class Song extends Model
{
use Taggable;
protected $fillable = ['name','title','album_id'];
public $timestamps = false;
public function album() {
return $this->belongsTo(Album::class, 'album_id');
}
}
and then make query as :
$songs = Song::with(['album','tags'])->whereHas('album', function($q) {
$q->where('language', '=', 'hindi');
})->get();
This will returns you all songs which belongs to albums which has "hindi" language with their tags.
here is an example
Table Structure
Game
--id
--game
Posts
--id
--game_id
--post_text
class Posts extends Eloquent {
protected $primaryKey = 'id';
protected $table = 'posts';
public function games() {
return $this->hasOne('games','id');
}
}
class Games extends Eloquent {
protected $primaryKey = 'id';
protected $table = 'games';
public function posts() {
return $this->belongsTo('posts','game_id');
}
}
I need to get the game name of a certain post. How can I get it using eloquent?
here is my initial code
echo $post->games['game'];
but I get the wrong data.
The way it queries is this.
'query' => string 'select * from `games` where `games`.`id` = ? limit 1' (length=52)
'bindings' =>
array (size=1)
0 => int 5
Firstly Eloquent model names are not plural, so by default they should be Game and Post.
Secondly relationship return values must be changed. In hasOne and belongsTo you will need to use model class names like below. I also left out some optional code which is not required for the code to work.
class Post extends Eloquent {
public function game() {
return $this->hasOne('Game');
}
}
class Game extends Eloquent {
public function post() {
return $this->belongsTo('Post');
}
}
Now you can get the game name by $post->game->name
Hi there i'm trying to sort a collection by attribute of the relation.
This is my model
class Song extends \Eloquent {
protected $fillable = ['title', 'year'];
public function artist(){
return $this->hasOne('Artist','id', 'artist_id');
}
}
class SongDance extends \Eloquent {
protected $table = 'song_dances';
protected $fillable = ['rating'];
public function dance(){
return $this->belongsTo('Dance', 'dance_id');
}
public function song(){
return $this->belongsTo('Song', 'song_id');
}
}
class Dance extends \Eloquent {
protected $fillable = ['name'];
public function song_dances(){
return $this->hasMany('SongDance','dance_id','id');
}
public function songs(){
return $this->belongsToMany('Song', 'song_dances', 'dance_id', 'song_id');
}
}
this is how far i'm by now:
$dance = Dance::find(1);
$songs = $dance->songs()
->with('artist')->whereHas('artist', function ($query) {
$query->where('urlName','LIKE','%robbie%');})
->where('song_dances.rating', '=', $rating)
->orderBy('songs.title','asc')
->where('songs.year', '=', 2012)
->get();
Yeah i just could add a ->sortBy('artist.name'); to the query, but he result-collection can be quite big (about 6000 items) therefore i would prefer a databased sorting.
is there a possibility to do this?
Since Eloquent's relations are all queried separately (not with JOINs), there's no way to achieve what you want in the database layer. The only thing you can do is sort the collection in your app code, which you've already dismissed.
If you feel you must sort it in the database then you should write your own join queries instead of relying on Eloquent's relations.