Skip to content

Commit 652cc51

Browse files
authored
[12.x] Improve php artisan config:cache and php artisan optimize error messages for non-serializable values (#57249)
* Improve `php artisan config:cache` and `php artisan optimize` error messages for non-serializable values Enhanced ConfigCacheCommand to provide precise error messages when configuration values cannot be serialized during caching. When serialization fails, the command now iterates through the flattened config array to identify the exact configuration key containing the non-serializable value, rather than throwing a generic error. The improved error messages help developers quickly locate and fix configuration issues when running `php artisan config:cache` or `php artisan optimize`. ## Previously ``` Your configuration files are not serializable. ``` ## Now ``` Your configuration files could not be serialized because The value at "testconfig.nested.deep.closure" contains a non-serializable type. ``` * Improve `php artisan config:cache` and `php artisan optimize` error messages for non-serializable values Enhanced ConfigCacheCommand to provide precise error messages when configuration values cannot be serialized during caching. When serialization fails, the command now iterates through the flattened config array to identify the exact configuration key containing the non-serializable value, rather than throwing a generic error. The improved error messages help developers quickly locate and fix configuration issues when running `php artisan config:cache` or `php artisan optimize`. ## Previously ``` Your configuration files are not serializable. ``` ## Now ``` Your configuration files could not be serialized because The value at "testconfig.nested.deep.closure" contains a non-serializable type. ``` * Improve `php artisan config:cache` and `php artisan optimize` error messages for non-serializable values Enhanced ConfigCacheCommand to provide precise error messages when configuration values cannot be serialized during caching. When serialization fails, the command now iterates through the flattened config array to identify the exact configuration key containing the non-serializable value, rather than throwing a generic error. The improved error messages help developers quickly locate and fix configuration issues when running `php artisan config:cache` or `php artisan optimize`. ## Previously ``` Your configuration files are not serializable. ``` ## Now ``` Your configuration files could not be serialized because the value at "testconfig.nested.deep.closure" contains a non-serializable type. ``` * Improve `php artisan config:cache` and `php artisan optimize` error messages for non-serializable values Enhanced ConfigCacheCommand to provide precise error messages when configuration values cannot be serialized during caching. When serialization fails, the command now iterates through the flattened config array to identify the exact configuration key containing the non-serializable value, rather than throwing a generic error. The improved error messages help developers quickly locate and fix configuration issues when running `php artisan config:cache` or `php artisan optimize`. ## Previously ``` Your configuration files are not serializable. ``` ## Now ``` Your configuration files could not be serialized because the value at "testconfig.nested.deep.closure" contains a non-serializable type. ``` * Improve `php artisan config:cache` and `php artisan optimize` error messages for non-serializable values Enhanced ConfigCacheCommand to provide precise error messages when configuration values cannot be serialized during caching. When serialization fails, the command now iterates through the flattened config array to identify the exact configuration key containing the non-serializable value, rather than throwing a generic error. The improved error messages help developers quickly locate and fix configuration issues when running `php artisan config:cache` or `php artisan optimize`. ## Previously ``` Your configuration files are not serializable. ``` ## Now ``` Your configuration files could not be serialized because the value at "testconfig.nested.deep.closure" is non-serializable. ```
1 parent 6b5f87d commit 652cc51

File tree

2 files changed

+136
-0
lines changed

2 files changed

+136
-0
lines changed

src/Illuminate/Foundation/Console/ConfigCacheCommand.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Illuminate\Console\Command;
66
use Illuminate\Contracts\Console\Kernel as ConsoleKernelContract;
77
use Illuminate\Filesystem\Filesystem;
8+
use Illuminate\Support\Arr;
89
use LogicException;
910
use Symfony\Component\Console\Attribute\AsCommand;
1011
use Throwable;
@@ -69,6 +70,14 @@ public function handle()
6970
} catch (Throwable $e) {
7071
$this->files->delete($configPath);
7172

73+
foreach (Arr::dot($config) as $key => $value) {
74+
try {
75+
eval(var_export($value, true).';');
76+
} catch (Throwable $e) {
77+
throw new LogicException("Your configuration files could not be serialized because the value at \"{$key}\" is non-serializable.", 0, $e);
78+
}
79+
}
80+
7281
throw new LogicException('Your configuration files are not serializable.', 0, $e);
7382
}
7483

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<?php
2+
3+
namespace Illuminate\Tests\Integration\Foundation\Console;
4+
5+
use Illuminate\Filesystem\Filesystem;
6+
use Illuminate\Tests\Integration\Generators\TestCase;
7+
use LogicException;
8+
use Orchestra\Testbench\Concerns\InteractsWithPublishedFiles;
9+
10+
class ConfigCacheCommandTest extends TestCase
11+
{
12+
use InteractsWithPublishedFiles;
13+
14+
protected $files = [
15+
'bootstrap/cache/config.php',
16+
'config/testconfig.php',
17+
];
18+
19+
protected function setUp(): void
20+
{
21+
$files = new Filesystem;
22+
23+
$this->afterApplicationCreated(function () use ($files) {
24+
$files->ensureDirectoryExists($this->app->configPath());
25+
});
26+
27+
$this->beforeApplicationDestroyed(function () use ($files) {
28+
$files->delete($this->app->configPath('testconfig.php'));
29+
});
30+
31+
parent::setUp();
32+
}
33+
34+
public function testConfigurationCanBeCachedSuccessfully()
35+
{
36+
$files = new Filesystem;
37+
$files->put($this->app->configPath('testconfig.php'), <<<'PHP'
38+
<?php
39+
40+
return [
41+
'string' => 'value',
42+
'number' => 123,
43+
'boolean' => true,
44+
'array' => ['foo', 'bar'],
45+
'from_env' => env('SOMETHING_FROM_ENV', 10),
46+
'nested' => [
47+
'key' => 'value',
48+
],
49+
];
50+
PHP
51+
);
52+
53+
$this->artisan('config:cache')
54+
->assertSuccessful()
55+
->expectsOutputToContain('Configuration cached successfully');
56+
57+
$this->assertFileExists($this->app->getCachedConfigPath());
58+
}
59+
60+
public function testConfigurationCacheFailsWithNonSerializableValue()
61+
{
62+
$files = new Filesystem;
63+
$files->put($this->app->configPath('testconfig.php'), <<<'PHP'
64+
<?php
65+
66+
return [
67+
'closure' => function () {
68+
return 'test';
69+
},
70+
];
71+
PHP
72+
);
73+
74+
$this->expectException(LogicException::class);
75+
$this->expectExceptionMessage('Your configuration files could not be serialized because the value at "testconfig.closure" is non-serializable.');
76+
77+
$this->artisan('config:cache');
78+
}
79+
80+
public function testConfigurationCacheFailsWithNestedNonSerializableValue()
81+
{
82+
$files = new Filesystem;
83+
$files->put($this->app->configPath('testconfig.php'), <<<'PHP'
84+
<?php
85+
86+
return [
87+
'nested' => [
88+
'deep' => [
89+
'closure' => function () {
90+
return 'test';
91+
},
92+
],
93+
],
94+
];
95+
PHP
96+
);
97+
98+
$this->expectException(LogicException::class);
99+
$this->expectExceptionMessage('Your configuration files could not be serialized because the value at "testconfig.nested.deep.closure" is non-serializable.');
100+
101+
$this->artisan('config:cache');
102+
}
103+
104+
public function testConfigurationCacheIsDeletedWhenSerializationFails()
105+
{
106+
$files = new Filesystem;
107+
$files->put($this->app->configPath('testconfig.php'), <<<'PHP'
108+
<?php
109+
110+
return [
111+
'closure' => function () {
112+
return 'test';
113+
},
114+
];
115+
PHP
116+
);
117+
118+
try {
119+
$this->artisan('config:cache');
120+
$this->fail('should have thrown an exception');
121+
} catch (LogicException) {
122+
// Expected exception
123+
}
124+
125+
$this->assertFileDoesNotExist($this->app->getCachedConfigPath());
126+
}
127+
}

0 commit comments

Comments
 (0)