在聊天中查询用户的未读消息

时间:2019-11-05 08:43:03

标签: mysql laravel filter eloquent chat

我正在尝试建立越来越难的查询... 我正在使用Laravel开发具有简单结构的聊天应用程序:

  • 聊天有很多消息。
  • 每个消息都属于一个用户。
  • 在用户和邮件之间
  • n:m以保存已读邮件。

所以

Chat.php

pre=pre+al.get(i);
perm(pre,al,--k,real);

Message.php

public function messages() {
    return $this->hasMany(Message::class)
}

User.php

public function user() {
    return $this->belongsTo(User::class);
}

public function reads() {
    return $this->belongsToMany(User::class, 'reads');
}

好吧,现在我要下一个查询

  

将所有未读邮件的聊天记录给我(登录用户)

这意味着这样:

public function messages() {
    return $this->hasMany(Message::class);
}

public function reads() {
    return $this->belongsToMany(Message::class, 'reads');
}

但是那是行不通的,因为如果Chat读取了一条消息,它就会被忽略:(

也许我可以仅将聊天范围限定为 LAST 来实现此目的?或者也许我可以进行这样的操作:

  • 计算所有聊天消息
  • 计算我阅读的所有聊天消息
  • 进行减法运算,如果不为0,则考虑此Chat:D

但是我不知道如何与Eloquent进行这种“操作”。

请帮忙。 谢谢!

2 个答案:

答案 0 :(得分:0)

您阅读的所有聊天的第一个首选ID。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyForm extends StatefulWidget {
  @override
  State createState() {
    return _MyFormState();
  }
}

class _MyFormState extends State<MyForm> {
  static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  final Map<int, String> model = Map<int, String>();

  @override
  void initState() {
    print('initState()');
    for (int i = 0; i < 20; i++) {
      model[i] = null;
    }
    super.initState();
  }

  String validate(String value) {
    return value.isEmpty ? 'Cannot be blank!' : null;
  }

  void submitForm() {
    final FormState formState = _formKey.currentState;

    if (formState.validate()) {
      print('form is valid');
      formState.save();
    } else {
      print('form is invalid');
    }
  }

  @override
  Widget build(BuildContext context) {
    List<Widget> fields = [];

    for (int i = 0; i < 20; i++) {
      Widget widget = TextFormField(
        initialValue: model[i],
        decoration: InputDecoration(
          labelText: 'field $i',
        ),
        validator: validate,
        onFieldSubmitted: (String value) {
          print('field $i onFieldSubmitted()');
          setState(() {
            model[i] = value;
          });
        },
        onChanged: (String value) {
          print('field $i onChanged()');
          setState(() {
            model[i] = value;
          });
        },
        onSaved: (String value) {
          print('field $i onSaved()');
          setState(() {
            model[i] = value;
          });
        },
      );
      fields.add(widget);
    }

    fields.add(RaisedButton(
      child: Text('save'),
      onPressed: submitForm,
    ));

    return Form(
      key: _formKey,
      child: ListView(
        children: fields,
      ),
    );
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('form test'),
        ),
        body: MyForm(),
      ),
    );
  }
}

然后申请

$pluckedId=Chat::has('messages.reads', function (Builder $q) {
            return $q->where('user_id', auth()->id());
        })->pluck('id');

答案 1 :(得分:0)

好吧,我终于找到了一种方法,该方法仅提取聊天的最后一条消息,并使用查询生成器方法检查特定用户是否已阅读了该消息。

在这里,我使用子查询发布魔法范围;)

public function scopeUnreadBy(Builder $builder, int $userId)
{
    //First, look for Chats with Messages
    return $builder->whereHas('messages', function (Builder $q) use ($userId) { 
        $q->select(['last_message' => function(\Illuminate\Database\Query\Builder $sub) {
            // Then, take only last one Message
            $sub->select('id')
                ->from('messages')
                ->where('chat_id', 'chats.id')
                ->latest()
                ->limit(1);
        }])->whereDoesntHave('reads', function(Builder $q) use ($userId) {
            // Finally, check that last one has not been read :D
            return $q->where('user_id', $userId);
        });
    });
}

Ph,那很难。

我希望它对其他人有帮助!

请记住,所有这些都可以通过一个查询完成;)