問題のない例
以下のようなmigrationとmodelの場合、特に問題は起こらない。
php artisan make:migration create_samples_table
php artisan make:model Sample
- create_samples_table.php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateSamplesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('samples', function (Blueprint $table) {
$table->increments('id');
$table->string('content');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('samples');
}
}
- Sample.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Sample extends Model
{
//
}
- 使用例
$sample = new Sample();
$sample->content = 'hoge';
$sample->save();
echo $sample->id; // 1
idがnullになる例
例えば、model
のkey
をstring
にしたいという場合。
migration
は以下のようになるだろう。
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateSamplesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('samples', function (Blueprint $table) {
$table->string('id')->unique(); //変更
$table->string('content');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('samples');
}
}
これをこのまま使用すると以下のようにidに0が格納されてしまう。
(データベースには正しくid
にa1234567
が格納されている)
$sample = new Sample();
$sample->id = 'a1234567';
$sample->content = 'hoge';
$sample->save();
echo $sample->id; // 0
解決策
おそらくだがsave時にint型で自動増分させる処理の際に、0が格納されてしまうのだろう。
なので、Modelのプロパティを以下のように設定してあげれば解決できる。
- Sample.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Sample extends Model
{
/**
* The "type" of the auto-incrementing ID.
*
* @var string
*/
protected $keyType = 'string';
/**
* モデルの主キーを自動増分させるか否か
*
* @var boolean
*/
public $incrementing = false;
}
- 使用例
$sample = new Sample();
$sample->id = 'a1234567';
$sample->content = 'hoge';
$sample->save();
echo $sample->id; // a1234567
原因?(追記)
$incrementing = true
となっていると、以下のprocessInsertGetId
が実行される。
public function processInsertGetId(Builder $query, $sql, $values, $sequence = null)
{
$query->getConnection()->insert($sql, $values);
$id = $query->getConnection()->getPdo()->lastInsertId($sequence);
return is_numeric($id) ? (int) $id : $id;
}
つまり、save時にインサートが行われ、その後最新のIdを取得してきている。
この処理の間に$idが0となってしまっているようだが、
具体的になぜ0になってしまうのか...ということまではわからなかった。