I'm trying to setup some simple favoriting for my app using Laravel/Jenssegers MongoDB
I have two models:
class Item {
public function favorites()
{
return $this->hasMany('App\Models\User', 'favorites');
}
}
class User {
public function favorites()
{
return $this->hasMany('App\Models\Item', 'favorites');
}
}
So an item can have many users and a user can have many items or "favorites".
When I try to run a simple query like:
Item::with('favorites')->get();
The relationship for favorites is there but an empty array.
The favorites table is simple and just has three columns:
_id, item_id, user_id
I've also tried using embedsMany with no luck:
return $this->embedsMany('App\Models\User', 'favorites');
I've also tried every combination of parameters.
return $this->embedsMany('App\Models\User', 'favorites', 'building_id', 'user_id');
return $this->embedsMany('App\Models\User', 'favorites', 'user_id', 'building_id');
return $this->hasMany('App\Models\User', 'favorites', 'building_id', 'user_id');
return $this->hasMany('App\Models\User', 'favorites', 'user_id', 'building_id');
Strange results when using:
return $this->hasMany('App\Models\User', 'favorites', 'building_id', 'user_id');
Only in this situation it returns ALL users, even though favorites has only one record.
Also trying to debug using getQueryLog just gives me an empty array at all times.
print_r(\DB::connection('mongodb')->getQueryLog());
I've done this using mysql and have never had issues. So not really sure where the issues are coming from.
Can you try these instead, I know its the same thing but might do the trick :
use App\User;
use App\Item;
class Item {
public function favorites()
{
return $this->hasMany('User');
}
}
class User {
public function favorites()
{
return $this->hasMany('Item');
}
}
class Favourite {
public function users()
{
return $this->belongsTo('User');
}
public function items()
{
return $this->belongsTo('Item');
}
}
Also add inverse of the above relations like: belongsTo.
and try this query then :
//Just for testing purpose, if raw query returns right result
$items = DB::table('items')
->join('favorites','items.id','=','favorites.id')
->get();
Related
In laravel 7 app I app/Forum.php model with method:
public function forumThreads()
{
return $this->hasMany('App\ForumThread', 'forum_id', 'id');
}
app/ForumThread.php has field forum_id and:
public function forum()
{
return $this->belongsTo('App\Forum', 'id');
}
public function forumPosts()
{
return $this->hasMany('App\ForumPost');
}
and in app/ForumPost.php there are field forum_thread_id and:
public function forumThread()
{
return $this->belongsTo('App\ForumThread'/*, 'user_id'*/);
}
can I in app/Forum.php make method referring post:
public function forumPosts()
{
return $this->hasMany('App\ForumPost');
}
and if yes, how?
Thanks!
Though your eloquent looks confusing, but i will say guess what might need is using the "has many through" and "has one through" relationship.
I have a Member model in my Laravel application, and in the model:
public function active_memberships() {
return $this->hasMany(MemberMembership::class, 'member_id', 'id')->where(function($query) {
$query->where('ends_at', '>', Carbon::now());
});
}
public function promo_code() {
return $this->hasMany(MemberPromoCode::class, 'member_id', 'id');
}
Both the member_memberships and member_promo_codes tables have member_id as a foreign key. However, if I do this:
$member = Member::with(['active_memberships','promo_code'])->find($id);
I get the active_memberships array in $member, but not promo_code.
So, $member['active_memberships'] prints out an array., but $member['promo_code'] gives an error:
Undefined index: promo_code
What am I missing here?
Try changing your relationship methods to these:
public function active_memberships() {
return $this->hasMany('\App\MemberMembership', 'member_id')->where(function($query) {
$query->where('ends_at', '>', Carbon::now());
});
}
public function promo_code() {
return $this->hasMany('\App\MemberPromoCode', 'member_id');
}
You don't need to pass the third parameter as id because that is by default and try to give the relation using the namespace as that is the most basic way to define relations.
See if Controller query works then?
I have a project with main table 'Qsos' and bunch of relations. Now when I try to create advanced search I don't really know how to query all relations at the same time. Qso model has following:
public function band()
{
return $this->belongsTo('Band');
}
public function mode()
{
return $this->belongsTo('Mode');
}
public function prefixes()
{
return $this->belongsToMany('Prefix');
}
public function user()
{
return $this->belongsTo('User');
}
public function customization() {
return $this->hasOne('Customization');
}
Then I have SearchController with following code that has to return collection of all Qsos following required conditions:
$qsos = Qso::withUser($currentUser->id)
->join('prefix_qso','qsos.id','=','prefix_qso.qso_id')
->join('prefixes','prefixes.id','=','prefix_qso.prefix_id')
->where('prefixes.territory','like',$qTerritory)
->withBand($qBand)
->withMode($qMode)
->where('call','like','%'.$input['qCall'].'%')
->orderBy('qsos.id','DESC')
->paginate('20');
And then in view I need to call $qso->prefixes->first() and $qso->prefixes->last() (Qso and Prefix has manyToMany relation) but both return null. What is wrong?
Here is the eloquent code that I found working but taking VERY long time to process:
$qsos = Qso::withUser($currentUser->id)
->with('prefixes')
->withBand($qBand)
->withMode($qMode)
->where('call','like','%'.$input['qCall'].'%')
->whereHas('prefixes', function($q) use ($qTerritory) {
$q->where('territory','like',$qTerritory);
})
->orderBy('qsos.id','DESC')
->paginate('20');
So i'm a bit confused with this situation, I have the current relations:
User hasmany Favourite
favourites references to a Recipe model
favourites is a pivot table but when I retrieve the favourites for a given user like:
$user->favourites
i get the favourite with the pivot data, but I want to get the fields of the recipe
Recipe.php:
public function favourites()
{
return $this->hasMany('App\Favourite');
}
User.php:
public function favourites()
{
return $this->hasMany('App\Favourite');
}
Favourite.php:
public function user()
{
return $this->belongsTo('App\User','user_id');
}
public function recipes()
{
return $this->belongsTo('App\Recipe','recipe_id');
}
EDIT : there was no problem at all, just needed to call:
#foreach($user->favourites as $favourite)
{{ $favourite->recipe->name }}
#endforeach
You need to set your relation to Has Many Through instead of just has Many.
https://laravel.com/docs/5.2/eloquent-relationships#has-many-through
Recipe.php:
public function favourites()
{
return $this->hasManyThrough('App\Favourite', 'App\User');
}
User.php:
public function favourites()
{
return $this->hasManyThrough('App\Favourite', 'App\Receipe');
}
Favourite.php:
public function user()
{
return $this->hasManyThrough('App\User','App\Receipe');
}
I want to return the customer adress if there is no deliveretadress on the order.
This what I have been trying:
public function deliveryAddress()
{
if ( $this->delivery_address )
{
return $this->belongsTo("DeliveryAddress",'delivery_address');
}
return $this->belongsTo("Customer", 'customer_id');
}
This does not work if I want to use Order::with('deliveryAddress')->get(), only If I have a model and not a collection.
Is this possible?
When you use a relation you still don't have a row available, relations are queries in the process of built, this way, you still dont havedelivery_address` available here:
if ( $this->delivery_address )
Because at this point your model is still not up. It (or they) will be up after a get() or a first() and then you'll have access to them. So you can
public function deliveryAddress()
{
return $this->belongsTo("DeliveryAddress",'delivery_address');
}
public function customerAddress()
{
return $this->belongsTo("Customer", 'customer_id');
}
class Order extends Eloquent {
public function getAddress()
{
if ($this->delivery_address)
{
return $this->deliveryAddress;
}
else
{
return $this->customerAddress;
}
}
}
$order = Order::with('deliveryAddress', 'customerAddress')->first();
echo $order->getAddress()->street_name;
This is untested code, so it might not work at first, but this is the idea of what you can do.