任务时间: 2025年05月27日 20:50
任务状态: ✅ 已完成
处理人员: AI Assistant
在实现宠物技能持续时间友好显示功能后,出现了以下错误:
Call to undefined method App\Module\Pet\Models\PetSkill::formatDuration()
在 PetSkillController 的Grid列定义中:
$grid->column('duration_time', '持续时间')->display(function ($value) {
return $this->formatDuration($value); // ❌ 错误:$this指向PetSkill模型实例
})->unescape()->sortable();
$this 指向 PetSkillController 实例$this 指向 PetSkill 模型实例formatDuration() 方法,导致调用失败在Dcat Admin的Grid列display回调中:
$this 上下文是当前行的模型实例考虑了以下几种解决方案:
将格式化方法移到模型中作为静态方法,便于复用
在回调外部定义变量,但不够优雅
创建全局helper函数,但污染全局命名空间
/**
* 格式化持续时间显示
*
* @param int $seconds 秒数
* @return string 友好的时间显示
*/
public static function formatDuration(int $seconds): string
{
if ($seconds <= 0) {
return '<span class="text-muted">无持续时间</span>';
}
$days = floor($seconds / 86400);
$hours = floor(($seconds % 86400) / 3600);
$minutes = floor(($seconds % 3600) / 60);
$remainingSeconds = $seconds % 60;
$parts = [];
if ($days > 0) {
$parts[] = "<span class='badge badge-primary'>{$days}天</span>";
}
if ($hours > 0) {
$parts[] = "<span class='badge badge-info'>{$hours}小时</span>";
}
if ($minutes > 0) {
$parts[] = "<span class='badge badge-success'>{$minutes}分钟</span>";
}
if ($remainingSeconds > 0 && empty($parts)) {
$parts[] = "<span class='badge badge-secondary'>{$remainingSeconds}秒</span>";
}
if (empty($parts)) {
return '<span class="text-muted">瞬间</span>';
}
$result = implode(' ', $parts);
$result .= "<br><small class='text-muted'>({$seconds}秒)</small>";
return $result;
}
/**
* 获取格式化的持续时间
*
* @return string
*/
public function getFormattedDurationTimeAttribute(): string
{
return self::formatDuration($this->duration_time);
}
/**
* 获取格式化的冷却时间
*
* @return string
*/
public function getFormattedCoolDownAttribute(): string
{
return self::formatDuration($this->cool_down);
}
// 修改前(错误)
$grid->column('duration_time', '持续时间')->display(function ($value) {
return $this->formatDuration($value); // ❌ $this指向模型实例
})->unescape()->sortable();
// 修改后(正确)
$grid->column('duration_time', '持续时间')->display(function ($value) {
return \App\Module\Pet\Models\PetSkill::formatDuration($value); // ✅ 静态方法调用
})->unescape()->sortable();
删除控制器中不再使用的 formatDuration() 方法。
// 可以在任何地方使用
$formattedTime = PetSkill::formatDuration(7200);
// 模型访问器
$skill = PetSkill::find(1);
echo $skill->formatted_duration_time;
echo $skill->formatted_cool_down;
// 静态方法易于单元测试
$this->assertEquals('2小时', strip_tags(PetSkill::formatDuration(7200)));
// 其他模块可以直接使用
use App\Module\Pet\Models\PetSkill;
$formattedTime = PetSkill::formatDuration($someSeconds);
// 在模板中直接使用
{{ $skill->formatted_duration_time }}
{{ $skill->formatted_cool_down }}
测试宠物技能格式化方法修复
============================
测试静态方法 PetSkill::formatDuration():
----------------------------------------
0秒 -> 无持续时间
2小时 -> 2小时(7200秒)
20小时 -> 20小时(72000秒)
1天 -> 1天(86400秒)
测试模型访问器:
================
自动除草: 持续时间=20小时(72000秒), 冷却时间=无持续时间
自动种植: 持续时间=20小时(72000秒), 冷却时间=无持续时间
自动收获: 持续时间=2小时(7200秒), 冷却时间=无持续时间
自动浇水: 持续时间=2小时(7200秒), 冷却时间=无持续时间
自动杀虫: 持续时间=2小时(7200秒), 冷却时间=无持续时间
PetSkill::formatDuration() 正常工作$skill->formatted_duration_time 正常工作$this 指向当前行的模型实例// 访问器命名规范
public function getFormattedDurationTimeAttribute() // formatted_duration_time
public function getFormattedCoolDownAttribute() // formatted_cool_down
// ✅ 推荐:使用模型静态方法
$grid->column('field')->display(function ($value) {
return ModelClass::formatMethod($value);
});
// ✅ 推荐:使用模型访问器
$grid->column('formatted_field');
// ❌ 避免:调用控制器方法
$grid->column('field')->display(function ($value) {
return $this->controllerMethod($value); // $this不是控制器
});
// 在模型中定义静态方法
public static function formatDuration(int $seconds): string
// 在其他地方复用
PetSkill::formatDuration($seconds);
成功修复了宠物技能时间格式化方法调用错误:
现在宠物技能管理页面的时间显示功能完全正常,代码结构也更加合理和可维护。
🎉 修复完成!宠物技能时间格式化功能现在完全正常工作!