Sir*_*rge 3 php relationships laravel eloquent laravel-5
我正在为我的应用程序开发一个消息传递系统,目前,我有两个表:
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');
});
Run Code Online (Sandbox Code Playgroud)
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();
});
Run Code Online (Sandbox Code Playgroud)
目前,我可以将消息及其主题存储到messages表中.现在,我想选择id我正在发送消息的用户.这样我就可以用它来创建一个对话.
有什么办法可以列出所有用户并选择我想要发送消息的首选用户吗?或任何有消息传递技术的人可以帮忙吗?
你的问题有点模糊,太宽泛.无论如何,我假设您希望允许用户向系统中的其他现有用户发送消息.
在我们开始之前,请注意涉及很多设计决策.我将简单地采用最简单,最快捷的方法,因为它只是一个让你入门的演示.
为了使用户能够相互发送消息,您需要在数据库迁移中设置外键,设置雄辩的关系并创建在控制器类中使用的辅助方法.
非常不言自明; 但如果您不知道我在说什么,请查看有关外键约束的文档.
您的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');
}
}
Run Code Online (Sandbox Code Playgroud)
这会messages在注释中解释为您的表设置外键约束.别忘了:php artisan migrate:refresh [-seed].
首先,看看有关雄辩关系的文档.然后看看我们如何设置两个模型之间的关系; 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');
}
}
Run Code Online (Sandbox Code Playgroud)
而你的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');
}
}
Run Code Online (Sandbox Code Playgroud)
有了这些文件,您就可以拥有一个可靠的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();
Run Code Online (Sandbox Code Playgroud)
有关更多示例,请参阅文档或与其一起使用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...
}
}
Run Code Online (Sandbox Code Playgroud)
这将从登录用户向ID为的用户发送消息1.您的问题主要是关于收件人以及如何列出用户并从中进行选择.我们稍后会谈到.
这有效,但它不是那么干净.让我们用模型方法包装逻辑:
class User extends Authenticatable
{
// ...
public function sendMessageTo($recipient, $message, $subject)
{
return $this->sent()->create([
'body' => $message,
'subject' => $subject,
'sent_to_id' => $recipient,
]);
}
}
Run Code Online (Sandbox Code Playgroud)
将此方法添加到App\User模型中,并使控制器代码如下所示:
Auth::user()->sendMessageTo(1, $request->subject, $request->body);
Run Code Online (Sandbox Code Playgroud)
好吧,对吗?
唯一剩下的问题是关于收件人ID.您可能有一个用户用来撰写邮件的表单.它可能有一个名为textarea的命名body和主题输入subject.您只需要另一个输入,以便用户也可以传递收件人用户的ID.那你就说:
Auth::user()->sendMessageTo($request->recipient, $request->subject, $request->body);
Run Code Online (Sandbox Code Playgroud)
您可能希望使用列出用户名称的下拉列表(或自动完成窗口小部件).渲染表单时,您可以添加将用户数据传递给视图,如下所示:
<?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'));
}
}
Run Code Online (Sandbox Code Playgroud)
然后,在您的视图中,您可以像这样呈现此数据:
{{ Form::select('recipient', $users) }}
// See: https://laravelcollective.com/docs/5.3/html
Run Code Online (Sandbox Code Playgroud)
容易,对吗?这是未经测试的代码,但希望它能给你提供这个想法.
在这之后,为什么不使用设计良好,经过良好测试的消息包呢?认识Laravel Messenger.