Laravel用户间消息传递系统

时间:2017-01-09 12:12:03

标签: php laravel laravel-5 eloquent relationships

我正在为我的应用程序开发一个消息传递系统,目前,我有两个表:

1)messages表:

Schema::create('messages', function (Blueprint $table) {
    $table->increments('id');
    $table->text('subject');
    $table->integer('sender_id');
    $table->text('body');
    $table->timestamps('create_date');
    $table->integer('sent_to_id');
});

2)users表:

Schema::create('users', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->string('email')->unique();
    $table->string('password');
    $table->rememberToken();
    $table->timestamps();
});

目前,我可以将邮件及其主题存储到messages表中。现在,我想选择我发送邮件的用户id。这样我就可以用它来创建一个对话。

有什么办法可以列出所有用户并选择我想要发送消息的首选用户吗?或任何有消息传递技术帮助的人?

1 个答案:

答案 0 :(得分:5)

你的问题有点含糊不清。无论如何,我假设您希望允许用户向系统中的其他现有用户发送消息。

在开始之前,请注意涉及很多设计决策。我只是采用最简单,最快捷的方法,因为它只是一个让你入门的演示。

为了使用户能够相互发送消息,您需要在数据库迁移中设置外键,设置雄辩的关系并创建在控制器类中使用的辅助方法。

1。外键

非常不言自明;但如果您不知道我在说什么,请查看documentation on foreign key constraints

您的users表迁移现在不需要更改,因此我跳到messages表迁移:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateMessagesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('messages', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('sender_id');
            $table->integer('sent_to_id');
            $table->text('body');
            $table->text('subject');

            // It's better to work with default timestamp names:
            $table->timestamps(); 

            // `sender_id` field referenced the `id` field of `users` table:
            $table->foreign('sender_id')
                  ->references('id')
                  ->on('users');

            // Let's add another foreign key on the same table,
            // but this time fot the `sent_to_id` field:
            $table->foreign('sent_to_id')
                  ->references('id')
                  ->on('users');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('messages');
    }
}

这会在评论解释时在messages表上设置外键约束。不要忘记:php artisan migrate:refresh [-seed]

2。模型关系

首先,看看documentation on eloquent relationships。然后看看我们如何设置两个模型之间的关系; MessageUser

这是您的App\Message班级:

<?php

namespace App;

use App\User;
use Illuminate\Database\Eloquent\Model;

class Message extends Model
{
    protected $fillable = ['body', 'subject', 'sent_to_id', 'sender_id'];

    // A message belongs to a sender
    public function sender()
    {
        return $this->belongsTo(User::class, 'sender_id');
    }

    // A message also belongs to a receiver    
    public function receiver()
    {
        return $this->belongsTo(User::class, 'sent_to_id');
    }
}

您的App\User班级:

<?php

namespace App;

use App\Message;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;

    protected $fillable = ['name', 'email', 'password'];

    // A user can send a message
    public function sent()
    {
        return $this->hasMany(Message::class, 'sender_id');
    }

    // A user can also receive a message
    public function received()
    {
        return $this->hasMany(Message::class, 'sent_to_id');
    }
}

有了这些文件,您就可以随心所欲地使用扎实的API。看看这些例子:

$user->sent       // All messages sent by this user
$user->received   // All messages received by this user

App\User::has('sent')->get() // Retrieve all users that have at lest one sent message
App\User::has('sent', '>', 2)->get() 

$user->sent()->where('subject', 'Happy new year!')->first();

有关更多示例,请参阅文档或在php artisan tinker中使用它们来了解它的功能。

3。消息传递实施

现在您已准备好迁移和模型。您需要利用它们来实现您的用户间消息传递系统。

这需要很多样板代码,例如路线,控制器和视图,我不会在这里写下来。但我相信你能找到自己的方法。我只是在这里添加一个示例用法示例。

我假设您需要一个控制器才能让用户向另一个发送消息。这是一个例子:

<?php

namespace App\Http\Controllers;

use Auth;
use App\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class ConversationController extends Controller
{
    public function sendMessage(Request $request)
    {
        // Do the validation...

        // Send the message from the current user to the user with ID of 1,
        // You probably always want the current logged-in user as the sender.
        // We talk about the recipient later...
        //
        Auth::user()->sent()->create([
            'body'       => $request->body,
            'subject'    => $request->subject,
            'sent_to_id' => 1,
        ]);   

        // Set flash message, render view, etc...
    }
}

这将从登录用户向ID为1的用户发送消息。您的问题主要是关于收件人以及如何列出用户并从中进行选择。我们稍后会谈到这一点。

4。清理

这样可行,但不是那么干净。让我们用模型方法包装逻辑:

class User extends Authenticatable
{
    // ...

    public function sendMessageTo($recipient, $message, $subject)
    {
        return $this->sent()->create([
            'body'       => $message,
            'subject'    => $subject,
            'sent_to_id' => $recipient,
        ]);   
    }
}

将此方法添加到App\User模型中,并使控制器代码如下:

Auth::user()->sendMessageTo(1, $request->subject, $request->body);

更好,对吧?

4。收件人

唯一剩下的问题是关于收件人ID。您可能有一个用户用来撰写邮件的表单。它可能有一个名为body的textarea和名为subject的主题输入。您只需要另一个输入,以便用户也可以传递收件人用户的ID。然后你只要说:

Auth::user()->sendMessageTo($request->recipient, $request->subject, $request->body);

您可能希望使用列出用户名称的下拉列表(或自动完成窗口小部件)。渲染表单时,您可以添加将用户数据传递给视图,如下所示:

<?php

namespace App\Http\Controllers;

use Auth;
use App\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class ConversationController extends Controller
{
    public function composeMessage()
    {
        // ...

        // Get a collection of `[id => name]` probable recipients,
        // so that the logged-in user can choose from. Note that 
        // you probably want to exclude the current user herself
        // from the list.
        $users = User::where('id', '!=', Auth::id())->pluck('name', 'id');

        return view('view.name', compact('users'));
    }
}

然后,在您的视图中,您可以像这样呈现此数据:

{{ Form::select('recipient', $users) }}
// See: https://laravelcollective.com/docs/5.3/html

简单,对吗?它是未经测试的代码,但希望它可以为您提供这个想法。

毕竟,为什么不使用设计良好,经过良好测试的消息包呢?见Laravel Messenger