0
0

More than 1 year has passed since last update.

【Laravel】ViewでのErrorException count()への対処

Posted at

ErrorException count(): Parameter must be an array or an object that implements Countable

某アカデミーでTwitterクローンを作っている際に発生しました。

結論:count()の引数にカウントできないものを入れている。

結論から言うと、私の場合はcount()の引数にBelongsToMany, HasMany等のクラスのオブジェクトを入れていたことが原因でした。
それらをget(),first(),pagenate()などでCollectionクラスにしてやることでcount()できるようになりました。

Controller

app/Http/Controllers/UsersController.php
class UsersController extends Controller
{
    /**
     * ユーザのお気に入り一覧ページを表示するアクション。
     *
     * @param  $id  ユーザのid
     * @return \Illuminate\Http\Response
     */ 
    public function favorites($id)
    {   
        $user = \Auth::user();
-       $microposts = $user->favorites();
+       $microposts = $user->favorites()->get();
        $data = ['user' => $user,'microposts' => $microposts,];

        // favoritesビューでそれらを表示
        return view('users.favorites', $data);
    }
}

再現と解決までの過程

私はControllerからViewに渡す際にうまくいっていませんでした。

Model

app/User.php
class User extends Authenticatable
{
    /**
     * このユーザのお気に入り
     */ 
    public function favorites()
    {
        return $this->belongsToMany(Micropost::class, 'user_favorite', 'user_id', 'favorite_id')->withTimestamps();
    }
}

Controller

app/Http/Controllers/UsersController.php
// 略
class UsersController extends Controller
{
    public function favorites($id)
    {   
        $user = \Auth::user();
        $microposts = $user->favorites();
        $data = ['user' => $user, 'microposts' => $microposts,];
        // favoritesビューでそれらを表示
        return view('users.favorites', $data);
    }
}

Router

routes/web.php
Route::group(['middleware' => ['auth']], function () {
    Route::group(['prefix' => 'users/{id}'], function () {
        Route::get('favorites', 'UsersController@favorites')->name('users.favorites');
    });
});

View

resources/views/users/favorites.blade.php
@if (count($microposts) > 0)
    @foreach ($microposts as $micropost)
    @endforeach
@endif


さて、/users/{id}/favosで動作確認してみると…

ErrorException
count(): Parameter must be an array or an object that implements Countable
(View: /home/ubuntu/environment/microposts/resources/views/users/favorites.blade.php)

Viewの1行目のcountでエラーです。
「パラメーターは配列かカウントできるオブジェクトじゃないとアカンで!」と怒られてるようです。
Controllerで\$microposts = $user->favorites();で配列やCollectionが取れていると思い込んでいました。

tinkerで確認してみます。

$ php artisan tinker
>>> $user = User::find(1)
>>> get_class($user->favorites());
=> "Illuminate\Database\Eloquent\Relations\BelongsToMany"

>>> count($user->favorites());
PHP Warning:  count(): Parameter must be an array or an
object that implements Countable in Psy Shell code on line 1
=> 1

なるほど、BelongsToManyクラスはカウントできるけど警告が出ますね。

1時間近くあれこれやってみたのですがカウンタブルなクラスに変えられず、メンターに質問しました。

「paginate() や get() や first() などを実行することでデータの取得が行われ、countなどを実行できる形式のデータを取得できます」とのこと。

さっそくget()で試してみる。

>>> get_class($user->favorites()->get());                          
=> "Illuminate\Database\Eloquent\Collection"

>>> count($user->favorites()->get());
=> 4

Collectionクラスになりました!カウントもできます。

その結果、Controllerを書き換えて出来上がったのが冒頭と同様の↓

app/Http/Controllers/UsersController.php
class UsersController extends Controller
{
    /**
     * ユーザのお気に入り一覧ページを表示するアクション。
     *
     * @param  $id  ユーザのid
     * @return \Illuminate\Http\Response
     */ 
    public function favorites($id)
    {   
        $user = \Auth::user();
-       $microposts = $user->favorites();
+       $microposts = $user->favorites()->get();
        $data = ['user' => $user,'microposts' => $microposts,];

        // favoritesビューでそれらを表示
        return view('users.favorites', $data);
    }
}

Viewを少し書き換えて

resources/views/users/favorites.blade.php
@if (count($microposts) > 0)
    @foreach ($microposts as $micropost)
        {{-- 投稿内容 --}}
        <p class="mb-0">{!! nl2br(e($micropost->content)) !!}</p>
    @endforeach
@endif

qiitaErrorExceptioncount().gif

無事に内容が取得できました!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0