2014年11月24日月曜日

Laravelでマイグレーション後にモデル作成してもデータが登録ができない

いままで、SQLiteを使ったことがなかったため、ちょっと試してみようということで、勉強を始めたlaravelで触ってみることにしました。

ですが、開始早々に躓いてしまいました。。

どんなことに躓いたかといいますと、マイグレーションからテーブルを作成し、テストデータを登録しようとしたら、追加できなかったのです。

ヘタレ具合を露呈させてしまいますが、まとめてみました。

まず、artisanコマンドでマイグレーションファイルを生成します。

$ php artisan migrate:make profile
Created Migration: 2014_11_23_230533_profile
Generating optimized class loader

上記のコマンドを実行すると「2014_11_23_230533_profile.php」というファイルがapp/databases/migrations配下に生成されます!

この生成したファイルにテーブルのカラム情報を記述していきます。記述するのは、マイグレーションファイルのupメソッドです。

$ vim app/database/migrations/2014_11_23_230533_profile.php
public function up()
{
// profileテーブル作成
       Schema::create('profile', function($table){
           $table->increments('id');
           $table->string('name');
           $table->timestamps();
       });
}

Schemeのcreateでテーブル名とカラム情報を設定します。最後のtimestamp()ではcreated_at、updated_atというカラムを作成できます!

記述が終わったら、artisanでmigrateします。

$ php artisan migrate

これでテーブルが作成できたので、モデルを作っていきます。

モデルでは、下記のようにテーブルや変更しないカラム、変更する可能性のあるカラムを指定しておきます。

 $ vim /app/models/Profile.php
 class Profile extends Eloquent {
     protected $table    = 'profile';
     protected $gurded   = array('id');
     protected $fillable = array('name');
 }

モデルを作成したら、今度はコントローラーでデータを追加してみます。

$ vim /app/controllers/ProfileController.php
public function index()
{
    $profile = new Profile;

    $profile->name = 'jack';
    $profile->save();
}

new Profileでインスタンスを生成して、save()で保存するように記述して、完了です。

これで、今回のテストデータ登録ができるはずだったのですが、エラーが出てしまいました。

Symfony\Component\Debug\Exception\FatalErrorException thrown with message "Call to undefined method Profile::save()"

Stacktrace:
#1 Symfony\Component\Debug\Exception\FatalErrorException in /app/controllers/ProfileController.php:15
#0 Illuminate\Exception\Handler:handleShutdown in <#unknown>:0

エラーを確認すると、saveメソッドが定義されていないというものでした。

save()が定義されていないということは、モデルを作ったけど、読み込まれていないのか!?と思い、dump-autoloadしてみることにしました。

$ composer dump-autoload
Generating autoload files

無事にコマンドが成功したので、再度登録を試みるも変わらずに同じエラーが出てしまいました。。

まだ、読み込めていないのかなんなのかよくわらないので、$profileをvar_dumpしてみました。var_dumpしていろいろ表示されてもよく分からないけど、とりあえずvar_dump‼︎

$profile = new ProfileTable;
var_dump($profile);

こんな感じでProfileの内容をvar_dumpしたところ•••
 
object(Profile)#131 (1) { ["connection":protected]=> NULL }

あ•••
NULLという文字が見える。。
これは、モデルがちゃんと生成できていないということなのか!?

なかなか混乱してきましたが、モデルがちゃんと読み込まれていない可能性があるということは、dump-autoloadでモデルがちゃんと入らなかったのか?ということで、dump-autoloadで更新されるautoload_classmap.phpを確認してみました。

ファイル内でprofileを検索したところ、モデルは読み込まれておらず、代わりにマイグレーションがProfileとして読み込まれていました。。

$ vim vendor/composer/autoload_classmap.php
'Profile' => $baseDir . '/app/database/migrations/2014_11_23_230533_Profile.php',

これは、マイグレーションとモデルが同じ名前で、すでにマイグレーションがあるからモデルが追加されていない?ということなのか?

もしそういうことなら、モデルの名前を変えればエラーじゃなくなるのか?

うーん、よく分からない。
考えても分からないので、とりあえずモデル名を変えてみます。。

$ vim /app/models/Profiles.php
<?php
class Profiles extends Eloquent {
    protected $table    = 'profile';
    protected $gurded   = array('id');
    protected $fillable = array('name');
}

モデルのもともとProfileだったものをProfilesに変更してみました。コントローラーで呼び出しているところも変更します。

$ vim /app/controllers/ProfileController.php
$profile s = new Profiles;

$profiles->name = 'jack';
$profiles->save();

ファイルの変更が終わったら、dump-autoloadで更新!

更新後にautoload_classmap.phpを確認したところ、Profilesが追加されているのが確認できました。

$ vim vendor/composer/autoload_classmap.php
'Profile' => $baseDir . '/app/database/migrations/2014_11_23_230533_Profile.php',
'Profiles' => $baseDir . '/app/models/Profiles.php',

モデルが読み込まれたので、実行してみるとエラーは解消され、無事に登録することができました。

+--+-------+----------------------------+----------------------------+
|id  |name  |created_at                     |updated_at                   |
+--+-------+----------------------------+----------------------------+
| 1  |jack    |2014-11-24 00:42:36|2014-11-24 00:42:36|
+--+-------+----------------------------+----------------------------+

今回の原因は、先に作成したマイグレーションがProfileとして読み込まれていたため、同じ名前で指定したProfileモデルが追加されなかったということみたいです。


0 件のコメント:

コメントを投稿

pythonの実行環境をDockerで構築してスクリプトを実行する方法

pythonの環境をローカルに構築するのに、pythonのバージョンを指定して入れるのもな と思って、dockerでやってみることにしました。 まずは、コンテナの準備をDockerfileで進めていきます。 今回は、pythonのイメージを使いたいので、 ドキュメント ...