Laravel 10: Online/Offline

dakata__92

Super Moderator
Нещо тотално забих как да направя качествено прихващането на статус онлайн или не на потребител, спрямо таблица записваща активностите. Искам бързо да мога да взимам статуса на потребителя и информацията от последната активност.
Не ми се вижда коректно да го правя така.
PHP:
dd(User::with('online', 'offline')->first()->toArray());
Примерен отговор.
Код:
array:12 [
  "id" => 1
  "name" => "Test"
  "email" => "test@abv.bg"
  "email_verified_at" => null
  "created_at" => "2023-05-13T08:27:23.000000Z"
  "updated_at" => "2023-05-14T12:33:46.000000Z"
  "currency" => "BGN"
  "deleted_at" => null
  "online" => null
  "offline" => array:11 [
    "id" => 1149733
    "level" => 1
    "user_id" => 1
    "method" => "POST"
    "ip" => "127.0.0.1"
    "created_at" => "2023-05-15T14:37:25.000000Z"
    "updated_at" => "2023-05-15T14:21:36.000000Z"
  ]
]

Модел.
PHP:
<?php

namespace App\Models;

class User
{

    /**
     * @return HasMany
     */
    public function activities(): HasMany
    {
        return $this->hasMany(
            Activity::class,
            'user_id',
            'id'
        );
    }

    /**
     * @return HasOne
     */
    public function online(): HasOne
    {
        return $this->hasOne(
            Activity::class,
            'user_id',
            'id'
        )
            ->latest()
            ->where('created_at', '>=', now()->subMinutes(10));
    }

    /**
     * @return HasOne
     */
    public function offline(): HasOne
    {
        return $this->hasOne(
            Activity::class,
            'user_id',
            'id'
        )
            ->latest()
            ->where('created_at', '<', now()->subMinutes(10));
    }
}
 
Какво те притеснява така?

Защо не си направиш само една релация status и тя да ти показва дали е on/off спрямо тия 10 минути?
 
Какво те притеснява така?

Защо не си направиш само една релация status и тя да ти показва дали е on/off спрямо тия 10 минути?
То с online е лесно в рамките на 10 минутки ако има активност да мачва, обаче искам и последната активност. Нещо ми се омешаха логически нещата. Искам да имам последната активност и дали е онлайн или не клиента.
 
Както казаха по-горе. Имай си едно поле статус, което си има едни и същи данни + това ли е он или офф. Не е нужно да ги разделяш отделно.
Другия вариант е поле статус дали е online/offline и едно last_activity с информацията от последната активност, когато е вече offline.
 
Както казаха по-горе. Имай си едно поле статус, което си има едни и същи данни + това ли е он или офф. Не е нужно да ги разделяш отделно.
Другия вариант е поле статус дали е online/offline и едно last_activity с информацията от последната активност, когато е вече offline.
защо ти е статус ако имаш последна активност.
Аз поне на база активността бих смятал дали е на линия. При логоут сетваш като нулл
 
Аз имам лог на активностите на потребителите. Въпроса е как по културен начин да си направя релацията да взема последният запис на клиента и заедно с това да маркирам статус на линия или не. Не ми се иска всеки път да пиша на 100 места проверка дали са изтекли 10 минутки от последният активен момент. Смятам че има по-добри варианти за това.

PHP:
$item = User::with([
    'activities' => function($query) {
        return $query->latest()->limit(1);
    }
])->where('id', 1)->first();
dump($item->toArray(), current($item->activities->toArray()));
if ($item->activities[0]->created_at >= now()->subMinutes(10)) {
    dd('online');
}
dd('offline');
 
Виж какво е Accessor и си направи такъв за status-a спрямо последното activity, където да ти прави логиката дали е online или offline.
 
Разглеждал ли си варианта, в който имаш нова колона "last_activity_at" и при всяка промяна на активити модела (може би с някакъв observer) му тапваш "last_activity_at" колоната и я ъпдейтваш и така няма нужда от релации после като правиш справка може на самия модел да си сложиш условието директно:
PHP:
User::where('last_activity_at', '<', now()->addMunites(2))->get()

иили един скоуп, който да ти връща created_at на последната активност, и спрямо нея да си направиш проверката, така правиш "виртуална"/"временна" колона

PHP:
// User.php
public function scopeWithLastestActivity($q)
{
    $q->join('activities', 'users.id', '=', 'activities.user_id')
        ->select('users.*', 'activities.created_at as last_activity_at')
        ->latest('last_activity_at');
}
(join-а е примерен, не знам дали така са ти колоните, защото не си споделил)

PHP:
User::WithLastestActivity()->where('last_activity_at', '<', now()->addMunites(2))->get()
 
Последно редактирано:
Виж какво е Accessor и си направи такъв за status-a спрямо последното activity, където да ти прави логиката дали е online или offline.
Това е доста добър вариант и ще го пробвам днес или утре.

Разглеждал ли си варианта, в който имаш нова колона "last_activity_at" и при всяка промяна на активити модела (може би с някакъв observer) му тапваш "last_activity_at" колоната и я ъпдейтваш и така няма нужда от релации после като правиш справка може на самия модел да си сложиш условието директно:
PHP:
User::where('last_activity_at', '<', now()->addMunites(2))->get()

иили един скоуп, който да ти връща created_at на последната активност, и спрямо нея да си направиш проверката, така правиш "виртуална"/"временна" колона

PHP:
// User.php
public function scopeWithLastestActivity($q)
{
    $q->join('activities', 'users.id', '=', 'activities.user_id')
        ->select('users.*', 'activities.created_at as last_activity_at')
        ->latest('last_activity_at');
}
(join-а е примерен, не знам дали така са ти колоните, защото не си споделил)

PHP:
User::WithLastestActivity()->where('last_activity_at', '<', now()->addMunites(2))->get()
Имам цяла таблица с пълната активности на потребителя, което на практика обезсмисля да правя такова поле. Мисля, че с примера на @deam0n ще се случат нещата, но в момента съм претоварен с други казуси и нямам време да пиша по този.
 
защо ти е статус ако имаш последна активност.
Аз поне на база активността бих смятал дали е на линия. При логоут сетваш като нулл
На мен не ми трябва :D
 

Back
Горе