I try to create a messenger where users are able to join threads and therefore I have four tables:
users
id - integer
name - string
threads
id - integer
name - string
created_at - dateTime
updated_at - dateTime
participants
user_id - integer
threads_id - integer
created_at - dateTime
updated_at - dateTime
deleted_at - dateTime
messages
id - integer
user_id - integer
thread_id - integer
text - string
created_at - dateTime
updated_at - dateTime
deleted_at - dateTime
The User has:
threads(){
return $this->belongsToMany(
Thread::class,
'participants',
'user_id',
'thread_id'
)
->withTimestamps()
->withPivot('thread_id', 'user_id', 'deleted_at')
->orderBy('created_at', 'desc');
}
Now I try to get a relationship to the messages, only the messages which are after joining the thread should be visible:
public function messagesThroughThreads()
{
$relation = $this->hasManyThrough(
Message::class,
$this->threads(),
'user_id',
'thread_id',
'id',
'id'
)
->orderBy('updated_at', 'desc');
return $relation;
}
actually, this is not working like that and I get the Models via:
public function messagesThroughThreads(bool $show_deleted = false)
{
$messages = collect([]);
foreach ($this->threads as $thread){
if($thread->pivot->deleted_at){
$m = $thread->messages_model()->whereBetween('messages.created_at', [$thread->pivot->deleted_at, $thread->pivot->created_at])->get();
}else{
$m = $thread->messages_model()->where('messages.created_at', '>=', $thread->pivot->created_at)->get();
}
$messages = $messages->merge($m->toArray());
}
return $messages->unique();
}
Any Idea how I could get a relationship instance with the same conditions?
There's no (native) relationship to access the messages directly.
Depending on your data it might be faster to get all messages and then remove some of them:
class Thread
{
public function messages()
{
return $this->hasMany(Message::class);
}
}
public function messagesThroughThreads(bool $show_deleted = false)
{
$this->load('threads.messages');
foreach ($this->threads as $thread) {
$m = $thread->messages->where('created_at', '<=', $thread->pivot->deleted_at)
->where('created_at', '>=', $thread->pivot->created_at);
}
You would be working on collections, so methods like whereBetween()
aren't available.
I created a HasManyThrough
relationship with unlimited levels: Repository on GitHub
After the installation, you can use it like this:
class User extends Model {
use \Staudenmeir\EloquentHasManyDeep\HasRelationships;
public function messagesThroughThreads() {
return $this->hasManyDeep(Message::class, ['participants', Thread::class])
->whereColumn('messages.created_at', '>=', 'participants.created_at')
->where(function($query) {
$query->whereNull('participants.deleted_at')
->orWhereColumn('messages.created_at', '<=', 'participants.deleted_at');
})->orderByDesc('messages.updated_at');
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.