laravel 为什么当我使用主键而不是id时,数据会发生变化?

jyztefdp  于 2023-01-10  发布在  其他
关注(0)|答案(1)|浏览(152)

我正在Laravel 9.x中开发一个应用程序,我的应用程序目前包括7个表。每个表都有一个主键,这些主键中的NONE是标准的递增整数id。对于我的每个模型,我都在模型中添加了一行,指示实际主键是什么,并指示递增为false。我的迁移也正确定义了各自的主键。
我目前正在为我的7个控制器编写index()和show()方法,当我执行index()方法时,发生了一些非常奇怪的事情:主键列中的值与我在DatabaseSeeder中植入的值不同。在一个主键为字符串的表中,index()方法在表的每一行的主键列中显示0。在另一个主键为日期的表中,index()方法在表的每一行的主键列中只显示日期的年份部分。
我发现,使主键列中显示正确值的唯一方法是注解掉模型中的主键定义。
我对这种行为感到非常困惑。有人能告诉我为什么会发生这种情况以及如何解决吗?
这是我迁移的up()方法,其中定义了一个表:

public function up()
{
    Schema::create('non_driving_reasons', function (Blueprint $table) {
        $table->string('reason_for_not_driving', 50); 
        $table->primary('reason_for_not_driving', 'reason_for_not_driving_PK');
        $table->timestamps();
    });
}

以下是植入此表的值的示例:

\App\Models\NonDrivingReasons::factory()->create([
        'reason_for_not_driving' => 'Snow Day' 
    ]);
    \App\Models\NonDrivingReasons::factory()->create([
        'reason_for_not_driving' => 'Professional Development Day' 
    ]);
    \App\Models\NonDrivingReasons::factory()->create([
        'reason_for_not_driving' => 'School staff on strike' 
    ]);
    \App\Models\NonDrivingReasons::factory()->create([
        'reason_for_not_driving' => 'School Holiday - Christmas' 
    ]);

这是非驱动原因控制器的index()方法:

public function index() {
    return view('nonDrivingReasons.index', [
        'nonDrivingReasons' => NonDrivingReasons::paginate(6)
    ]);
}

这是NonDrivingReasons表的索引刀片:

<x-layout>
<div class="bg-gradient-to-b from-red-500 to-purple-100">
    <h1 class="text-3xl text-center text-white font-bold bg-indigo-700">Non-driving Reasons</h1>
    <h1 class="pb-5"></h1><!-- spacer beneath title -->

    <div class="flex justify-center h-screen" style="display: grid; grid-template-rows: auto auto auto auto; row-gap: 25px; padding: 10px">

        <div>
        {{-- If there are no non-driving reasons, indicate that to the user.  --}}
            @if (count($nonDrivingReasons) == 0)
                <p>No non-driving reasons found.</p>
            @endif
        </div>
        
        <div>
            <table><thead><tr><th><a href="/nonDrivingReasons/create"><img src="{{asset('icons/green-plus-circle-outline.svg')}}" width="50" alt="add icon"></a></th><th><a href="/nonDrivingReasons/create">Add new non-driving reason</a></th></tr></thead></table>
        </div>
    
        {{-- If there are non-driving reasons, display them.  --}}
        <div>
            <table class="border-black border-2 bg-white">
            <thead class="border-black border-2 text-white bg-gray-800">
                <tr class="content-center">
                    <th class="border-black border-2 p-2 text-left">Non-Driving Reason</th>
                    <th class="border-black border-2 p-2">View</th>
                    <th class="border-black border-2 p-2">Edit</th>
                    <th class="border-black border-2 p-2">Delete</th></tr>
                </thead>
            <tbody class="border-black border-2">
                @foreach($nonDrivingReasons as $nonDrivingReason)
                <tr class="border-black border-2">
                    <td class="border-black border-2 p-2">{{$nonDrivingReason->reason_for_not_driving}}</td>
                    <td class="border-black border-2 p-2"><a href="/nonDrivingReasons/show/{{$nonDrivingReason->reason_for_not_driving}}"><img src="{{asset('icons/magenta-details.svg')}}" width="25" alt="view logo"></a></td>
                    <td class="border-black border-2 p-2"><a href="/nonDrivingReasons/edit/{{$nonDrivingReason->reason_for_not_driving}}"><img src="{{asset('icons/yellow-lead-pencil.svg')}}" width="25" alt="update logo"></a></td>
                    <td class="border-black border-2 p-2"><a href="/nonDrivingReasons/destroy/{{$nonDrivingReason->reason_for_not_driving}}"><img src="{{asset('icons/red-delete.svg')}}" width="25" alt="delete logo"></a></td>
                </tr>
                @endforeach
            </tbody>
            </table>
        </div>

        <div>
            <p class="mt-6 p-4">{{$nonDrivingReasons->links()}}</p>
        </div>

    </div>

    <h1 class="pt-5">&nbsp;</h1><!-- spacer at bottom of page -->
</div>
</x-layout>

这是非驱动性原因的模型:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class NonDrivingReasons extends Model
{
    use HasFactory;

    protected $fillable = ['reason_for_not_driving'];
    protected $primaryKey = 'reason_for_not_driving';
    public $incrementing = 'false';

        /**
        * Set the keys for a save update query.
        *
        * @param  \Illuminate\Database\Eloquent\Builder  $query
        * @return \Illuminate\Database\Eloquent\Builder
        */
        protected function setKeysForSaveQuery($query)
    {
        $keys = $this->getKeyName();
        if(!is_array($keys)){
            return parent::setKeysForSaveQuery($query);
    
        }
    
        foreach($keys as $keyName){
            $query->where($keyName, '=', $this->getKeyForSaveQuery($keyName));
        }
    
        return $query;
        }
    
        /**
        * Get the primary key value for a save query.
        *
        * @param mixed $keyName
        * @return mixed
        */
        protected function getKeyForSaveQuery($keyName = null)
        {
        if(is_null($keyName)){
            $keyName = $this->getKeyName();
        }
    
        if (isset($this->original[$keyName])) {
            return $this->original[$keyName];
        }
    
        return $this->getAttribute($keyName);
        }
    
    }

同样,为了使正确的数据出现在表的Non-Driving Reason中,我需要做的就是在我的模型中注解掉$primaryKey = 'reason_for_not_driving';,但这不是一个好的解决方案,因为它会导致Controller中的表查询失败,因为Eloquent假设主键必须是id,而id在表中不存在。

jw5wzhpr

jw5wzhpr1#

如果定义的主键不是integer类型,则必须相应地定义$keyTpye

protected $keyType = 'string';

有关主键的更多信息,请参阅以下文档:https://laravel.com/docs/9.x/eloquent#primary-keys

相关问题