Php agent 2.1.2 - Your configuration files are not serializable on php artisan optimize

When doing a migration from the v1 laravel forestadmin agent to v2.

  1. Used php artisan forest:install to initiate the config file.
  2. Left as default, manages to run through the database schema build process itself.
  3. When running php artisan optimize, the artisan process is unable to serialize the new config file.

As shown below, the config and optimize process works when the config file doesn’t exist.

Feature(s) impacted

Forest init command

Observed behavior

v2 forest init process fails, unable to build laravel project

Expected behavior

php artisan optimize succeeds as normal

Context

  • Agent (forest package) name & version: “forestadmin/laravel-forestadmin”: “2.1.2”,
  • Database type: MySQL 5.6/8
  • Recent changes made on your end if any: Upgraded laravel forestadmin from 1.5.3 to 2.1.2

Hello @EFGP

I reproduced the bug on my end.
I’ve just created a ticket on our dashboard and I’ll get back to you as soon as we’ve fixed it.

2 Likes

Thanks again as always!

Hello, sorry for my late reply
I’ve just created a pull request to fix this problem.

FYI there were 2 problems:

  • the inability to serialize
  • avoid using the env() helper which returns null if the configuration is cached.

This fix should be published early next week. In the meantime, if you want to use it, just migrate to the fix/config-agent branch.
In particular, you’ll need to :

  • clear the cache
  • clear the config cache
  • publish the vendor using the command: php artisan vendor:publish --provider=“ForestAdmin\LaravelForestAdmin\ForestServiceProvider” --tag=forest --tag=config
  • copy any customisations from config/forest_admin.php to forest/forest_admin.php
  • delete the old config/forest_admin.php file

I’ll keep you posted on the release

Excellent thank you we’ll give this a go early next week.

Hey - as below it’s not finding any config to copy across on that branch - I’ve manually copied it from agentTemplate/forest_admin.php for now, but then get the not serialisable error again

I have just published the new version of the package. I’m in the process of writing a migration note, but in the meantime you can follow these steps

In your composer.json file specify the new package version

"forestadmin/laravel-forestadmin": "^3.0"

Then update the package with the following command

composer update forestadmin/laravel-forestadmin

Before going any further, can you tell me that when you do a php artisan vendor:publish you find the following 3 lines:

  • Provider: ForestAdmin\LaravelForestAdmin\ForestServiceProvider
  • Tag: config
  • Tag: forest

if ok, run the command.
(/!\ I’ve just noticed that in my previous message the double quotes “” have been replaced by the wrong character)

php artisan vendor:publish --provider="ForestAdmin\LaravelForestAdmin\ForestServiceProvider" --tag=forest --tag=config

I have just updated our documentation with a migration note https://docs.forestadmin.com/developer-guide-agents-php/upgrade/upgrade-laravel-agent-to-v3#breaking-changes

Hi Matt,

Thanks for this. I’ve tried this but had to make some changes for it to work in a virtualised container / docker. Since the $this->appRoot tries to get the actual directory on my local Mac, rather than the virtual directory inside docker (ubuntu, so /var/www etc. rather than /users/username/project-dir etc.).

In order to get around this, can you add an appPath variable to the env/config? This worked when I replaced $this->appRoot with “./”, so if I can interface with that rather than hard coding inside the vendor package that will work.

ClassFinder.php:

    private function getNamespaceDirectory(string $namespace): string
    {
        $composerNamespaces = $this->getDefinedNamespaces();

        $namespaceFragments = explode('\\', $namespace);
        $undefinedNamespaceFragments = [];

        $appPath = "./";

        while($namespaceFragments) {
            $possibleNamespace = implode('\\', $namespaceFragments) . '\\';
            if(array_key_exists($possibleNamespace, $composerNamespaces)) {
                return realpath($appPath . '/' . $composerNamespaces[$possibleNamespace] . implode('/', $undefinedNamespaceFragments));
            }
        }
    }

    private function fetchFiles(string $directory): array
    {
        if (empty($directory))
        {
            $directory = "./";
        }

SchemaEmmitter.php


    public static function getSerializedSchema(Datasource $datasource)
    {
        if (config('isProduction')) {
            if (config('schemaPath') && file_exists(config('schemaPath'))) {
                $schema = json_decode(file_get_contents(config('schemaPath')), true, 512, JSON_THROW_ON_ERROR);
            } else {
                Logger::log('Warn', 'The .forestadmin-schema.json file doesn\'t exist');
                $schema = [
                    'meta'        => self::meta(sha1(json_encode([], JSON_THROW_ON_ERROR))),
                    'collections' => [],
                ];
            }
        } else {
            $schema = self::generate($datasource);
            $hash = sha1(json_encode($schema, JSON_THROW_ON_ERROR));
            $schema = [
                'meta'        => self::meta($hash),
                'collections' => $schema,
            ];

            $pretty = json_encode($schema, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT);
            file_put_contents("./.forestadmin-schema.json", $pretty);
        }

        return self::serialize($schema);
    }

Lastly, had to override the schemaPath in the forest.php config from

    'schemaPath'           => base_path() . '/.forestadmin-schema.json',

to

'schemaPath'           => base_path() . './.forestadmin-schema.json',

Finally this gets to update the forestschema but returns to the original error of not being able to serialize it:

[2024-02-08T10:04:51.441323+00:00] forestadmin.INFO: schema was updated, sending new version  
Configuration cache cleared!
[2024-02-08T10:04:56.299992+00:00] forestadmin.INFO: Schema was not updated since last run  

In order to help you we have sent you an email for a debugging session.