真正的快速:如果您使用spatie/laravel-markdown
并遇到此问题(我如何遇到此问题),它是最近用PR#53固定的。 ð
这个标题可能是您的头抓手。这是我最近遇到的一个问题,我没有立即挖掘。
基本上,运行artisan config:cache
开始给我错误地说无法序列化我的配置。
倒带
如果您以前没有使用过Laravel,则该项目的目录之一是config/
。该目录包含用于项目设置的PHP文件,主要是Laravel的,但您也可以创建和注册。一些安装的软件包还可以让您发布到该目录的 配置以供您自定义。
通常为每个请求重建组合的应用程序配置。为了加快这一速度,Laravel具有一个config:cache
命令来生成1个配置文件。这包括任何可能通过函数调用等人进行动态解析的值。而且通常只是有效。
当工作不起作用时
有时您可能需要在配置中一个对象,例如您使用Spatie的Laravel Markdown软件包并创建自定义渲染器。
例如:
<?php
return [
// ...
'block_renderers' => [
['class' => BlockQuote::class, 'renderer' => new BlockQuoteRenderer(), 'priority' => 1],
['class' => Heading::class, 'renderer' => new HeadingRenderer(), 'priority' => 1],
['class' => ListItem::class, 'renderer' => new ListItemRenderer(), 'priority' => 1],
],
//...
];
现在,这看起来并不糟糕。但是,如果您这样做然后运行config:cache
,您将获得与此类似的错误:
LogicException
Your configuration files are not serializable.
at /path/to/project/vendor/laravel/framework/src/Illuminate/Foundation/Console/ConfigCacheCommand.php:80
76▕ require $configPath;
77▕ } catch (Throwable $e) {
78▕ $this->files->delete($configPath);
79▕
➜ 80▕ throw new LogicException('Your configuration files are not serializable.', 0, $e);
81▕ }
82▕
83▕ $this->info('Configuration cached successfully!');
84▕ }
1 /path/to/project/bootstrap/cache/config.php:<line-number>
Error::("Call to undefined method App\Markdown\Renderers\BlockQuoteRenderer::__set_state()")
2 /path/to/project/vendor/laravel/framework/src/Illuminate/Foundation/Console/ConfigCacheCommand.php:76
require()
是什么原因造成的? ð
错误消息可能需要澄清。对于1,它说不可序列化。这可能会导致您相信config:cache
将serialize()
称为引擎盖下,但这不是。
它也没有指出 conform an an。
但是,在挖掘laravel/framework
时,我们找到了this section of code:
<?php
//...
$configPath = $this->laravel->getCachedConfigPath();
$this->files->put(
$configPath, '<?php return '.var_export($config, true).';'.PHP_EOL
);
try {
require $configPath;
} catch (Throwable $e) {
// ...
}
// ...
在那里,打电话给var_export()
。如果我们查看PHP manual以获取该功能,它显示了不同类型的输出的示例。
但专门查看示例#3:导出类。它具有此样本输出:
A::__set_state(array(
'var' => 5,
))
您可能还记得,静态方法__set_state()
出现在堆栈跟踪中。
如果我们读取PHP’s magic methods page,我们会看到这种静态方法允许将导出的对象字符串解析回对象中,同时自动向其提供其旧导出的数据!
和从laravel/framework
重读该片段,现在发生的事情是有道理的。调用config:cache
:
- Laravel正在以完整的,生成的配置读取并从中生成合并的PHP文件。然后,
- 它立即在此预构建的PHP文件中读取,触发对该魔法方法的调用。
因此,似乎这个错误只是配置缓存方式的副作用。
那么我们如何解决这个问题? ð
我们可以为我们的配置中的新课程实现__set_state()
。 return
值也应该是该类的实例。
对于我的渲染器,我写了一个特质:
<?php
trait Resumeable
{
public static function __set_state(array $state_array): static
{
$object = new static();
foreach ($state_array as $prop => $state) {
if (!property_exists($object, $prop)) continue;
$object->{$prop} = $state;
}
return $object;
}
}
我在PHP 8.1上测试了这一点。由于它是从班级中调用的,因此它也可以在private
和protected
属性上工作。
也是一件好事,因为var_export()
从private
和protected
属性导出数据。
摘要ð
您可能不需要这个。而且,如果您使用spatie/laravel-markdown
,PR#53确实很快合并了,因此您可以现在使用类字符串(感谢erikn69和freekmurze!)
,这是解决您可能遇到的config缓存问题的一种方法。
感谢您的阅读!ð