Eloquent 具有非默认主键的关系(belongsTo、hasMany)

Eloquent relationships (belongsTo, hasMany) with non-default primaryKey

我是关系数据库的新手,目前我是 运行 一个本地 sqlite 数据库,只是想建立一个 pivot/relational 数据库,我可以在其中获取参与者的消息列表,方法是使用他们的 phone 号码作为主键。没有登录,登录基本上是由用户通过从他们的 phone 发送短信到应用程序来完成的,所以我不能在我的估计中使用典型的 'id' 列。在我的数据库中 participant_id 也可能是 phone 号。我不确定我做错了什么。

在我的控制器中,当我访问预定义的路线时,我只是尝试使用此代码对结果进行 DD:

public function showMessages()
{
    $participant_id = "+5555555";

    //$activeParticipant = Participant::where('participant_id', $participant_id);

    $activeParticipant = Participant::find($participant_id);
    $messages = $activeParticipant->messages;

    dd($messages);
    //$messages = Participant::find($participant_id)->messages;
}

我收到以下错误:

SQLSTATE[HY000]: General error: 1 no such column: participants.id (SQL: select * from "participants" where "participants"."id" = +5555555 limit 1)

尽管存在这个错误,但我很确定我有问题,我只是不明白在下面的代码中该做什么...如果有人能帮助我解释一下,我将不胜感激。

这是我的模型和数据库迁移: 参与者迁移:

class CreateParticipantsTable extends Migration
{

protected $primaryKey = 'participant_id';
protected $incrementing = false;

public function up()
{
    Schema::create('participants', function (Blueprint $table) {
        $table->string('participant_id')->unique()->primary();
        $table->date('appointment_date')->nullable();
        $table->boolean('subscribed');
        $table->timestamps();
    });
}

参与者模型:

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Participant extends Model
{
protected $table = 'participants';

protected $fillable = ['participant_id', 'appointment_date', 'subscribed'];

public function messages()
{
    return $this->hasMany(Message::class);
//      return $this->hasMany('App\Message', 'message_id', 'participant_id');
}
public function notifications()
{
    return $this->hasMany(Notification::class);
}
}

消息迁移:

class CreateMessagesTable extends Migration
{
/**
 * Run the migrations.
 *
 * @return void
 */
public function up()
{
    Schema::create('messages', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('message_id')->unsigned();
        $table->string('phoneNumber')->nullable();
        $table->string('message_content')->nullable();
        $table->string('mediaSID')->index()->nullable();
        $table->string('messageSID')->index()->nullable();
        $table->string('mediaURL')->index()->nullable();
        $table->binary('media')->nullable();
        $table->string('filename')->index()->nullable();
        $table->string('MIMEType')->nullable();
        $table->timestamps();
        $table->foreign('message_id')->references('participant_id')->on('participants')->onDelete('cascade');
    });
}

消息模型:

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Message extends Model
{
protected $table = 'messages';
protected $hidden = 'media';
protected $fillable = ['message_id', 'phoneNumber', 'message_content', 'mediaSID', 'messageSID', 'mediaURL', 'media', 'filename', 'MIMEType'];

public function participant()
{
    return $this->belongsTo(Participant::class);
}
}

Laravel 尝试从名称中猜测模型的主键。所以,调用时:

$activeParticipant = Participant::find($participant_id);

Laravel 正在调用 SELECT * FROM participants WHERE participants.id = ? ...,它返回 participants.id 的问题,因为该列不存在。

由于您使用的是自定义主键,因此需要对其进行定义。在您的 Participant 模型上,在 class 声明附近添加以下内容:

protected $primaryKey = "participant_id";

设置后,默认查询逻辑将调整为SELECT * FROM participants WHERE participants.participant_id = ? ...,一切都应该是金色的。

注意:您可能对 Participant 和其他模特之间的任何关系有类似的问题。 Laravel 再次尝试猜测用于 ->hasMany()->belongsTo() 等的列,因此仔细检查 Documentation for Relationships,特别是这些方法可用的附加参数。

编辑:

//$activeParticipant = Participant::where('participant_id', $participant_id);

如果您在其末尾添加 ->first() 以实际执行查询,将会有效。没有 Closure->first()->get()->paginate() 等),您有一个 Builder 实例,而不是实际的数据库结果(null , CollectionParticipant)