質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.92%

Laravel 5.3でhasManyがundefinedとなる

受付中

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 3,321

TakahiroDeto

score 2

前提・実現したいこと

laravelで口コミ付きのランキングサイトを作っています。
ranking modelの各項目が複数のreputation modelを持つ仕様です
** ranking:1 reputation:N のhasMany

発生している問題・エラーメッセージ

外部キー制約をつけた上で、seedデータを投入した際に、
rankingモデルが持つはずのreputations()メソッドがundefinedとなりseedに失敗します

Seeding: RankingsTableSeeder
Seeding: ReputationsTableSeeder


  [BadMethodCallException]                                                  
  Call to undefined method Illuminate\Database\Query\Builder::reputations()

下記に、各モデルとmigrationデータ、seedファイルを記載しましたが
個人的にはしっかりメソッドを定義してる認識なのですが、どこか間違いがありますでしょうか・・・?
ご教示いただけると助かります。

該当のソースコード

Reputationモデル

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;

class Reputation extends Model
{
    protected $guarded = [];
    public function ranking()
    {
        return $this->belongsTo('App\Ranking');
    }
}

Rankingモデル

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;

class Ranking extends Model
{
    protected $guarded = [];
    public function reputations()
    {
        return $this->hasMany('App\Reputation');
    }
}


migration (一部カラムのみ抜粋)

class CreateRankingsTable extends Migration
{    
    public function up()
    {
        Schema::create('rankings', function (Blueprint $table) {
            $table->increments('id');
            $table->string('service_id',255)->unique();
            $table->string('service_type',255);            
            $table->integer('rank');
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('rankings');
    }
}

class CreateReputationsTable extends Migration
{
    public function up()
    {
        Schema::create('reputations', function (Blueprint $table) {
            $table->increments('id');                                    
            $table->integer('age');
            $table->string('gender',50);            
            $table->integer('rating');
            $table->text('comment');            
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('reputations');
    }
}


// 外部キー制約追加用マイグレーション
class AddColumnToReputationsTable extends Migration
{    
    public function up()
    {
        Schema::table('reputations', function (Blueprint $table) {
            $table->integer('rankings_id')->unsigned();
            $table->foreign('rankings_id')->references('id')->on('rankings')->onDelete('cascade');
        });
    }

    public function down()
    {
        Schema::table('reputations', function (Blueprint $table) {
            $table->dropForeign('reputations_rankings_id_foreign');
            $table->dropColumn('rankings_id');
        });
    }
}


シードデータ

class RankingsTableSeeder extends Seeder
{
    public function run()
    {
        DB::table('rankings')->delete();

        $data = [
          [            
            'service_id' => 'hoge1',
            'service_type' => 'fuga1',
            'rank' => 1,            
          ],
          [
            'service_id' => 'hoge2',
            'service_type' => 'fuga2',
            'rank' => 2,
          ],
          [
            'service_id' => 'hoge3',
            'service_type' => 'fuga3',
            'rank' => 3,
          ],
          [          
            'service_id' => 'hoge4',
            'service_type' => 'fuga4',
            'rank' => 4,          
          ],
        ];

        for($i = 0; $i < count($data); $i++){
          Ranking::create([
            'service_id'      => $data[$i]['service_id'],
            'service_type'    => $data[$i]['service_type'],          
            'rank'            => $data[$i]['rank'],            
          ]);
        }
    }
}

class ReputationsTableSeeder extends Seeder
{
    public function run()
    {
        DB::table('reputations')->delete();

        $count = App\Ranking::all()->count();

        for($i = 0; $i < $count; $i++){

          for($k = 0; $k < 10; $k++){
            $rep = new App\Reputation([              
              'age'                   => $ages[mt_rand(0,count($ages) - 1)],
              'gender'                => $genders[$i % count($genders)],
              'rating'                => mt_rand(0,5),
              'comment'               => $comments[mt_rand(0,count($comments) - 1)],              
            ]);

          }
          // ここでreputationsがundefinedとなるようです
          $ranking = App\Ranking::all()->orderBy('rank','asc')->take(1)->skip($i)->reputations()->save($rep);
        }

    }
}

試したこと

スペルミスも、単数複数もすべて試しましたがダメでした。
また補足情報として、mariadbのtableのprefixとして"tj_"というstringがつくのですが
このprefixがもしや悪さをしているかと思い、

Reputationモデル

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;

class Reputation extends Model
{
    protected $guarded = [];
    public function ranking()
    {
        return $this->belongsTo('App\Ranking','tj_rankings_id');
    }
}

Rankingモデル

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;

class Ranking extends Model
{
    protected $guarded = [];
    public function reputations()
    {
        return $this->hasMany('App\Reputation','tj_rankings_id','id);
    }
}

のように試しましたがそれでも同様のエラーでした。

補足情報(言語/FW/ツール等のバージョンなど)

FW:laravel5.3
DB:mysql  Ver 15.1 Distrib 5.5.52-MariaDB, for Linux (x86_64) using readline 5.1
Centos7.3

お手数おかけしますが、どなたかご教示ください。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

-1

投稿してやっと気付きましたが、seedデータのfor(k)が明らかにおかしいですね。なぜ気づかなかったんだろう。。再度自己トライします。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

-2

外側のループに記述してことに気づいた(初歩的。。。)ので、内側のループに戻しましたが、それでも動きませんでした。。

 for($i = 0; $i < $count; $i++){

   for($k = 0; $k < 10; $k++){
     $rep = new App\Reputation([              
              'age'                   => $ages[mt_rand(0,count($ages) - 1)],
              'gender'                => $genders[$i % count($genders)],
              'rating'                => mt_rand(0,5),
              'comment'               => $comments[mt_rand(0,count($comments) - 1)],              
      ]);
// ここでreputationsがundefinedとなるようです
          $ranking = App\Ranking::all()->orderBy('rank','asc')->take(1)->skip($i)->reputations()->save($rep);
   }

}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/18 01:38

    reputationsメソッドを持ってるのは誰でしょう?

    skipメソッドの返り値は何のオブジェクトでしょう?

    そこが分かれば、もう原因はわかるよね?

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.92%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る