Search code examples
phplaravelcaching

Laravel cache error: Too few arguments to function {closure}(), 0 passed in .../Illuminate/Cache/Repository.php on line 426 and exactly 2 expected


So I have a table called styles which has classes and styles for various places in blade templates. The table has a unique column the name and a column for class and a column for style. These values i do not expect to change much so I wish to cache them. The functions I have added to a helper class are listed below.

What I'm trying to do is cache a string so it can be called back later without the database query. So in my blade file I have a line like this <table class="{{ getStyles('table', 'class') "> and my helper file has the following functions

function getStyles( $name, $type )
{
    if ( $type === 'class' ) {
        $key = $name . 'Classes';
    } else {
        $key = $name . 'Styles';
    }
    if ( Cache::has( $key ) ) {
        return Cache::get( $key );
    }

    return cacheStyles( $name, $type );
}

function cacheStyles( $name, $type )
{
    if ( $type === 'class' ) {
        $key = $name . 'Classes';
    } else {
        $key = $name . 'Styles';
    }
    return Cache::rememberForever(
        $key,
        function ( $name, $type ) {
            return DB::table( 'styles' )->where( 'name', $name )->first()->{$type};
        }
    );
}

function updateStyles( $name, $class, $style )
{
    DB::table( 'styles' )
        ->where( 'name', $name )
        ->update(
            array(
                'class' => $class,
                'style' => $style
            )
        );
    cacheStyles( $name, 'class' );
    cacheStyles( $name, 'style' );

    return true;
}

I have cleared routes cache etc and I load the page with this table and i get the above error.

The closure function does have 2 arguments and they are strings ($name which is 'table' and $type which is 'class') so why the error?

I am caching to phpredis if it makes a difference. I also think I had this working (but it may have been cached with an earlier version of the code). Prior to clearing the cache I had added the 4 events into EventServiceProvider.php

        CacheHit::class => [
            LogCacheHit::class,
        ],

        CacheMissed::class => [
            LogCacheMissed::class,
        ],

        KeyForgotten::class => [
            LogKeyForgotten::class,
        ],

        KeyWritten::class => [
            LogKeyWritten::class,
        ],

I also added the listeners for these with no further amends (methods are empty). Do not know if related but once I cleared the cache My code stopped.

The prior method used was getTableClass but I switched to make it generic. Consequently the closure function originally had no $name and $class.

So I guess my question is 2 fold, am i using closure wrong and how can i stop this error?

I am using Laravel9.10 and php8.1 on an Ubuntu22.04 box

thanks

*** EDIT *** So I read I can use 'use' and moved the 2 variables into this but i now get a new error Attempt to read property "class" on null which implies the paramenters are still not being passed into this closure.

function cacheStyles( $name, $type )
{
    if ( $type === 'class' ) {
        $key = $name . 'Classes';
    } else {
        $key = $name . 'Styles';
    }
    return Cache::rememberForever(
        $key,
        function () use ( $name, $type )
        {
            return DB::table( 'styles' )->where( 'name', $name )->first()->{$type};
        }
    );
}

Solution

  • rememberForever() second parameter accepts a closure without any parameters. You can't link it to values other that the key itself (indirectly)

    function cacheStyles( $name, $type )
    {
        if ( $type === 'class' ) {
            $key = $name . 'Classes';
        } else {
            $key = $name . 'Styles';
        }
    
        return Cache::rememberForever(
            $key,
            function () use($name, $type) {
                return DB::table( 'styles' )->where( 'name', $name )->value($type);
            }
        );
    }