Laravel 4.2 HasMany Relationship using Like - laravel

I'm wondering if its possible to set the operator when using a HasMany relationship in Laravel 4.2.
I'm working with a users table and an email log table. The log table has a userID stored in serialised format (as there may be more than one userID stored within the log).
Users table
+---------+
| user_ID |
+---------+
| 1 |
| 2 |
+---------+
emailLog Table
+----+--------------------+
| ID | user_ID |
+----+--------------------+
| 1 | a:1:{i:0;s:1:"2";} |
| 2 | a:1:{i:0;s:1:"1";} |
+----+--------------------+
Am I able to use a hasMany relation with a 'Like' operator rather than an equals operator to return the correct email log ID? Would the statement be written something like the below?
return $this->hasMany('emailLog', 'user_ID', '%user_ID%', 'LIKE');

The proper way to return join table with a where clause would be:
return $this->hasMany('emailLog','user_id')->where('user_id', 'LIKE', '%user_id%');

I found a way to do something similar
class User extends Model
{
public function emailLogs()
{
// old code
// return $this->hasMany(EmailLogs::class, 'user_ID');
// Replace HasMany by like query
return EmailLogs::where('user_ID', 'LIKE', "%{$this->user_ID}%");
}
}

Related

laravel eloquent nested relationship count

i have 4 database tables :
Broadcasters
| id | public_name | .... |
Articles
| id | title| .... |
Comments
| id | user_id| article_id | .... |
users
| id | login| .... |
i would like to list all broadcasters with number of article of each one (broadcaster) and the totale comments of all article ( of the broadcaster ). below my code that i make but it miss samething
Broadcaster::withCount(['articles'])
->withCount(['articles'=> function($query){
return $query->withCount("comments");
}])
->get();
i checked in stackoverflow forum but didnot get any answer of my question , please help and thx
You can declare a relation hasManyThrough in Broadcasters class:
function comments()
{
return $this->hasManyThrough('App\Comment', 'App\Articles');
}
So you can
Broadcaster::withCount(['articles','comments'])
Laravel Doc

Eloquent model relationship for final table

I've the following tables
Cities (City model)
+----+-------+
| id | name |
+----+-------+
| 1 | tokyo |
+----+-------+
events (Event model)
+----+--------------------+---------+
| id | title | city_id |
+----+--------------------+---------+
| 1 | Biggest event ever | 1 |
+----+--------------------+---------+
event_user_applications (EventUserApplication model)
+----+----------+---------+
| id | event_id | user_id |
+----+----------+---------+
| 1 | 1 | 1 |
+----+----------+---------+
How do I get the city on EventUserApplication model.
I tried both of this in the EventUserApplication
public function city()
{
// return $this->belongsTo('App\Model\City', 'city_id')->using('App\Model\Event', 'event_id');
// return $this->hasOneThrough('App\Model\City', 'App\Model\Event', 'city_id', 'id');
}
Can't get any of this to work. Already spent hours. Please help. Thank you in advance.
I solved it with the help of my friend. This is what I did to get the city.
$applications = EventUserApplication::with(
'user:id,name,phone,email,date_of_birth',
'event:id,title,area_id,area_city_id',
'event.city' // nester eager loading
)->latest()->get();
In the Event model, I already had this
public function city()
{
return $this->belongsTo('App\Model\City', 'area_city_id');
}
It's the Nester Eager Loading which was needed.
In that case you can use hasOnThrough relationship EventUserApplication has One city Through Event.
Edit:The 5th parameter should be event_id and there should be another parameter which is id (foreign key of event table)

Self referencing "ownerless" many_many relationships?

I have a many many relationship where I don't care who created the relationship, if the querying models ID is in either side of the relationship I need the other side.
--
Let's say I have this model
class Ingredient extends Model
{
public function complements()
{
return $this->belongsToMany(
self::class, 'ingredient_complements',
'ingredient_id', 'complement_id'
);
}
}
And I've created a few different instances as below
$ing1 = new Ingredient();
$ing2 = new Ingredient();
$ing3 = new Ingredient();
$ing4 = new Ingredient();
$ing5 = new Ingredient();
$ing6 = new Ingredient();
$ing1->save(); //2,3,4,5,6...
Next I go through and relate a few of them
$ing1->complements()->attach($ing2);
$ing2->complements()->attach($ing3);
$ing3->complements()->attach($ing4);
$ing4->complements()->attach($ing6);
$ing5->complements()->attach($ing6);
$ing6->complements()->attach($ing1);
So now we have a pivot table that looks like
| ing_id | cmp_id |
| 1 | 2 |
| 2 | 3 |
| 3 | 4 |
| 4 | 5 |
| 5 | 6 |
| 6 | 1 |
So..
if I call $ing1->complements I'll get back ing2
if I call $ing2->complements I'll get back ing3
But..
if I call $ing2->complements I won't get back ing1
if I call $ing3->complements I won't get back ing2
I need to fix that.
I've got a second method that I'm using at the moment that I can call using $ing3->complementaryIngredients; which ends up executing something like
select * from `ingredients`
inner join `ingredient_complements` on `ingredient_id` = '3'
or `complement_id` = '3' and `ingredient_id` = `id`
or `complement_id` = `id` where `id` <> '3'
Which works, but I don't feel this is something that I should have to break out of the ORM for?
public function getComplementaryIngredientsAttribute()
{
return self::join('ingredient_complements', function(JoinClause $join){
$join->where('ingredient_id', $this->id);
$join->orWhere('complement_id', $this->id);
$join->on('ingredient_id', '=', 'id');
$join->orOn('complement_id', '=', 'id');
})->where('id', '<>', $this->id)->get();
}
You actually need to define bi-directional relationship, so your model should have 1 more method which will define the opposite direction.
public function ingredients()
{
return $this->belongsToMany(
self::class, 'ingredient_complements',
'complement_id', 'ingredient_id'
);
}
Then you will get the other side of your relation in this way $ing2->ingredients() and it will return what you are looking for.
Another approach is to create model for your pivot table so you can query that model to get both sides of your relationship

Laravel Categories Map Relationship

I have the following three tables but I don't know how to build a relation between the category and the other data type, in this case 'Page':
posts:
post_id | title | slug
1 | Test | test
2 | Another test | another test
catgory_map:
id | category_id | referrer_id | category_map_type
1 | 2 | 1 | Post
2 | 3 | 2 | Post
3 | 2 | 9 | Page
category
id | name
1 | Laravel
2 | Zend2
3 | Phalcon
So whenever I read a Category I like to be able to do something like this
foreach($category->destinations) ...
I have tried until now with hasManyThrough but it didn't work.
What you have is a many-to-many relation with some additional filtering on the relationship (for the category_map_type). Try this:
Post model
public function categories(){
return $this->belongsToMany('Category', 'category_map', 'referrer_id')
->where('category_map_type', 'Post');
}
Category model
public function posts(){
return $this->belongsToMany('Post', 'category_map', 'category_id', 'referrer_id')
->where('category_map_type', 'Post');
}
Usage
$category = Category::find(1);
foreach($category->posts as $post){
// ...
}
(And the same goes for Post)
You might also want to look into polymorphic many-to-many relations

Laravel multiple whereHas criteria for relationship

I have two tables - contacts and visits:
Contacts Table
id | name
----- | -------
1 | Joe
2 | Sally
Visits Table
id | contact_id | pathname | referrer
----- | ------- | ------- | -------
1 | 1 | about | google
2 | 1 | pricing | null
3 | 1 | signup | null
4 | 2 | about | null
5 | 2 | signup | null
Using eloquent, I would like to retrieve all contacts that have a both a pathname = 'signup' AND a referrer = 'google'.
What I've got so far is:
Contact::whereHas('visits', function($query) {
$query->where('pathname','=','signup');
})
->orWhereHas('visits', function($query) {
$query->where('referrer','=','google');
})
->get();
Which properly retrieves all contacts that have visited either the pricing OR signup page.
However, this example would also retrieve Sally (from the example table above), since she visited signup, but was not referred by google. I need a way to only retrieve Joe, who was both referred by google and visited pricing.
Any ideas? Thanks in advance!
You can use:
Contact::whereHas('visits', function($query) {
$query->where('pathname','=','signup');
})
->whereHas('visits', function($query) {
$query->where('referrer','=','google');
})
->get();
A refined version of the code above:
Contact::whereHas('visits', function($query) {
$query->where('pathname','signup')->where('referrer','google');
})->get();
Several noteworthy points:
You can chain where() clauses within a closure.
The default operator for a where clause is =, so you can omit it.
Use multiple whereHas() clauses, when accessing multiple related models.

Resources