You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

执行Job后Laravel每分钟报Call to undefined method错误排查

Laravel计划任务报错:调用未定义的getName()方法

问题详情

我编写了OdataSyncStoragesService类用于从API拉取数据并存入数据库,同时有一个命令类负责创建Job并分配到队列,Job会调用该Service的sync()方法。执行命令后Job能正常运行,但laravel.log中每分钟都会出现以下错误:

production.ERROR: Call to undefined method
    App\Services\Odata\OdataSyncStoragesService::getName() 
{"exception":"[object] (Error(code: 0): 
Call to undefined method App\\Services\\Odata\\OdataSyncStoragesService::getName() at
 /var/www/fastuser/data/www/89.191.229.227/vendor/laravel/framework/src/Illuminate/Console/Scheduling/Schedule.php:138)

执行schedule:list命令时也会触发相同错误。项目中已有多个同模板的OdataSync****Service类,均能正常运行,不清楚为何该类会每分钟报错一次。

相关代码

OdataSyncStoragesService.php代码:

<?php

namespace App\Services\Odata;

use App\Models\OdataStorage;
use GuzzleHttp\Exception\GuzzleException;
use Throwable;

class OdataSyncStoragesService extends OdataBaseService
{

    const URL_STORAGES = "Catalog_Склады";

    /**
     * Синхронизация атрибутов
     *
     * @return void
     * @throws GuzzleException
     * @throws Throwable
     */
    public function sync(): void
    {
        $storages = $this->fetchStorages();

        foreach ($storages as $storage) {
            $parsedStorage = $this->parseStorage($storage);
            OdataStorage::updateOrCreate([
                'Ref_Key' => $parsedStorage['Ref_Key']
            ],$parsedStorage);
        }
    }

    private function parseStorage(array $storage) {
        return [
            'Ref_Key' => $storage['Ref_Key'],
            'DataVersion' => $storage['DataVersion'],
            'DeletionMark' => $storage['DeletionMark'],
            'Parent_Key' => $storage['Parent_Key'],
            'IsFolder' => $storage['IsFolder'],
            'Description' => $storage['Description'],
            'groupSelection' => $storage['ВыборГруппы'],
            'useAddressStorage' => $storage['ИспользоватьАдресноеХранение'],
            'useReferenceAddressStorage' => $storage['ИспользоватьАдресноеХранениеСправочно'],
            'useOrderSchemeOnShipment' => $storage['ИспользоватьОрдернуюСхемуПриОтгрузке'],
            'useOrderSchemeOnSurplusShortageReflection' => $storage['ИспользоватьОрдернуюСхемуПриОтраженииИзлишковНедостач'],
            'useOrderSchemeOnReceipt' => $storage['ИспользоватьОрдернуюСхемуПриПоступлении'],
            'useItemSeries' => $storage['ИспользоватьСерииНоменклатуры'],
            'useWarehouseRooms' => $storage['ИспользоватьСкладскиеПомещения'],
            'calendar_Key' => $storage['Календарь_Key'],
            'controlOperationalBalances' => $storage['КонтролироватьОперативныеОстатки'],
            'addressStorageSettings' => $storage['НастройкаАдресногоХранения'],
            'department_Key' => $storage['Подразделение_Key'],
            'businessRegion_Key' => $storage['БизнесРегион_Key'],
            'retailPriceType_Key' => $storage['РозничныйВидЦены_Key'],
            'currentResponsiblePosition' => $storage['ТекущаяДолжностьОтветственного'],
            'currentResponsible_Key' => $storage['ТекущийОтветственный_Key'],
            'warehouseType' => $storage['ТипСклада'],
            'serviceLevel' => $storage['УровеньОбслуживания'],
            'priceType_Key' => $storage['УчетныйВидЦены_Key'],
            'startShipmentAfterTransportTaskCreation' => $storage['НачинатьОтгрузкуПослеФормированияЗаданияНаПеревозку'],
            'useWorkAreas' => $storage['ИспользованиеРабочихУчастков'],
            'priceInformationSourceForPrinting' => $storage['ИсточникИнформацииОЦенахДляПечати'],
            'useIssueOrderStatuses' => $storage['ИспользоватьСтатусыРасходныхОрдеров'],
            'useReceiptOrderStatuses' => $storage['ИспользоватьСтатусыПриходныхОрдеров'],
            'useGoodsRevaluationStatuses' => $storage['ИспользоватьСтатусыПересчетовТоваров'],
            'orderSchemeStartDateOnShipment' => $storage['ДатаНачалаОрдернойСхемыПриОтгрузке'],
            'orderSchemeStartDateOnReceipt' => $storage['ДатаНачалаОрдернойСхемыПриПоступлении'],
            'orderSchemeStartDateOnSurplusShortageReflection' => $storage['ДатаНачалаОрдернойСхемыПриОтраженииИзлишковНедостач'],
            'warehouseUsageStartDate' => $storage['ДатаНачалаИспользованияСкладскихПомещений'],
            'inventoryStorageStartDate' => $storage['ДатаНачалаАдресногоХраненияОстатков'],
            'considerCostBySeries' => $storage['УчитыватьСебестоимостьПоСериям'],
            'controlFreeBalances' => $storage['КонтролироватьСвободныеОстатки'],
            'responsibleStorage' => $storage['СкладОтветственногоХранения'],
            'luggageHolderType' => $storage['ВидПоклажедержателя'],
            'luggageHolder' => $storage['Поклажедержатель'],
            'luggageHolderTypeEnum' => $storage['Поклажедержатель_Type'],
            'storageResponsibilityPeriod' => $storage['СрокОтветственногоХранения'],
            'responsibleStorageUntilClaim' => $storage['ОтветственноеХранениеДоВостребования'],
            'specialMarks' => $storage['ОсобыеОтметки'],
            'goodsStorageConditions' => $storage['УсловияХраненияТоваров'],
            'workshopWarehouse' => $storage['ЦеховаяКладовая'],
            'orderPickingSupportedInStore' => $storage['ВМагазинеПоддерживаетсяСборкаЗаказов'],
            'deliveryByOwnCouriersSupportedInStore' => $storage['ВМагазинеПоддерживаетсяДоставкаСвоимиКурьерами'],
            'orderPickingRealizationMethod' => $storage['СпособСозданияРеализацииПриСборкеЗаказов'],
            'fiscalizationMethodOnDelivery' => $storage['СпособФискализацииПриДоставке'],
            'orderPickingAndDeliveryPerformedByOneEmployee' => $storage['СборкаИДоставкаВыполняетсяОднимСотрудником'],
            'couriersCanAssignOrdersToThemselves' => $storage['КурьерыМогутНазначатьСебеЗаказы'],
            'pickersCanAssignOrdersToThemselves' => $storage['СборщикиМогутНазначатьСебеЗаказы'],
            'orderDeliveryStandardPeriod' => $storage['НормативныйСрокДоставкиЗаказов'],
            'couriersUsePaymentTerminals' => $storage['КурьерыИспользуютЭквайринговыеТерминалы'],
            'couriersUseAutonomousCashRegisters' => $storage['КурьерыИспользуютАвтономныеККТ'],
            'orderPickingStartDate' => $storage['ДатаНачалаСборкиЗаказов'],
            'deliveryByOwnCouriersStartDate' => $storage['ДатаНачалаДоставкиСвоимиКурьерами'],
            'goodsGrouping' => $storage['ГруппировкаТоваров'],
            'individualPriceType_Key' => $storage['ИндивидуальныйВидЦены_Key'],
            'contactInformation' => json_encode($storage['КонтактнаяИнформация']),
            'additionalAttributes' => json_encode($storage['ДополнительныеРеквизиты']),
            'predefined' => $storage['Predefined'],
            'predefinedDataName' => $storage['PredefinedDataName'],
            'parentNavigationLinkUrl' => $storage['Parent@navigationLinkUrl'] ?? '',
            'departmentNavigationLinkUrl' => $storage['Подразделение@navigationLinkUrl'] ?? '',
            'retailPriceTypeNavigationLinkUrl' => $storage['РозничныйВидЦены@navigationLinkUrl'] ?? ''
        ];
    }


    /**
     * @param bool $onlyVersions
     * @return array|mixed
     * @throws GuzzleException
     */
    private function fetchStorages(): mixed
    {
        $params = [
            '$format' => 'json',
        ];

        $result = $this->sendRequest(self::URL_STORAGES, 'GET', $params);

        if (!$result['success']) {
            return [];
        }

        return $result['data']['value'] ?? [];
    }
}

原因分析

错误出现在Laravel的Schedule类中,说明你的OdataSyncStoragesService被误配置为计划任务的执行主体。Laravel计划任务系统会调用任务类的getName()方法来标识任务,但你的Service类并未实现该方法。每分钟报错是因为Laravel的schedule:run命令默认每分钟执行一次,执行时会加载所有已配置的计划任务并验证其结构。

解决方案

  1. 检查计划任务配置
    打开app/Console/Kernel.php,找到schedule方法,确认是否错误地将OdataSyncStoragesService直接添加到计划任务中。正确的配置应该是调用对应的命令类,而非Service类:

    // 错误写法:直接引用Service类
    // $schedule->call(OdataSyncStoragesService::class)->everyMinute();
    
    // 正确写法:引用命令类
    $schedule->command('odata:sync-storages')->everyMinute();
    
  2. 对比正常Service类的结构
    检查项目中其他正常运行的OdataSync****Service类,查看父类OdataBaseService是否实现了getName()方法,或者这些类是否混入了计划任务相关的Trait。如果父类有该方法,确保你的Service类正确继承了父类的所有方法。

  3. 临时修复(若需保留错误配置)
    如果因特殊需求必须将Service类作为计划任务执行,可以手动添加getName()方法:

    public function getName(): string
    {
        return 'odata.sync.storages'; // 返回自定义的任务名称
    }
    

内容的提问来源于stack exchange,提问作者Eugene Nail

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 22:04:49