我正在为我的应用程序开发一个消息传递系统,目前,我有两个表:
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
。这样我就可以用它来创建一个对话。
有什么办法可以列出所有用户并选择我想要发送消息的首选用户吗?或任何有消息传递技术帮助的人?
答案 0 :(得分:5)
你的问题有点含糊不清。无论如何,我假设您希望允许用户向系统中的其他现有用户发送消息。
在开始之前,请注意涉及很多设计决策。我只是采用最简单,最快捷的方法,因为它只是一个让你入门的演示。
为了使用户能够相互发送消息,您需要在数据库迁移中设置外键,设置雄辩的关系并创建在控制器类中使用的辅助方法。
非常不言自明;但如果您不知道我在说什么,请查看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]
。
首先,看看documentation on eloquent relationships。然后看看我们如何设置两个模型之间的关系; Message
和User
。
这是您的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
中使用它们来了解它的功能。
现在您已准备好迁移和模型。您需要利用它们来实现您的用户间消息传递系统。
这需要很多样板代码,例如路线,控制器和视图,我不会在这里写下来。但我相信你能找到自己的方法。我只是在这里添加一个示例用法示例。
我假设您需要一个控制器才能让用户向另一个发送消息。这是一个例子:
<?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
的用户发送消息。您的问题主要是关于收件人以及如何列出用户并从中进行选择。我们稍后会谈到这一点。
这样可行,但不是那么干净。让我们用模型方法包装逻辑:
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);
更好,对吧?
唯一剩下的问题是关于收件人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。