Laravel: 无法声明 class App\Models\Customer,因为该名称已被使用

Laravel: Cannot declare class App\Models\Customer, because the name is already in use

我有点困惑。我在我的用户(实际上是“客户”)模型上有一个简单的方法 return 用户的订阅续订日期:

public function subscriptionRenewalDate() : string
{
    $subscription = $this->subscriptions()->active()->first()->asStripeSubscription();

    return Carbon::createFromTimeStamp($subscription->current_period_end)->format('F jS, Y');
}

我从 blade 模板 ({{ auth()->user()->subscriptionRenewalDate() }}) 对经过身份验证的用户调用此方法,它在本地工作正常,但一旦我上传它到远程登台服务器它失败并出现错误:

Cannot declare class App\Models\Customer, because the name is already in use

它指向 Customer 模型中的这一行:

class Customer extends Authenticatable
{

奇怪的是,它不仅仅是远程登台服务器,它也是 Travis CI 失败的地方(当 运行 PHP 单元测试时 - 这些相同的测试在本地运行良好).

显然这似乎是某种缓存或配置问题,但我不明白是什么导致了这个错误。

它与数据库无关,因为测试使用 RefreshDatabase。如果我删除 ENV 变量 (CASHIER_MODEL: App\Models\Customer),它将失败并出现预期的“找不到模型用户”错误,因此它正确地获取了 ENV 变量。我已经尝试清除 Laravel 缓存 (php artisan optimize:clear) 和 composer dump-autoload。很混乱。

我只知道错误是由asStripeSubscription()引起的。如果我从方法中删除它,blade 模板加载正常(一切正常)。

明确地说,我可以成功(这是本地、远程和 Travis CI):

只有当 asStripeSubscription() 出现在代码中时才会出现问题。而且它只在远程服务器上。即使在本地也能正常工作。

我已经尝试将此调用转移到各种模型。我试过从控制器调用它并将结果传递给视图。我什至尝试过重启服务器并清除 Travis CI 的缓存。错误保持不变。

什么会导致 asStripeSubscription() 产生此错误?如果我可以在本地复制,我就可以调试它!固执地坚持本地完美,远程失败

我正在使用 Laravel 8、PHP 7.3 和 Cashier 12.10。

我只是无法理解会导致 Cannot declare class App\Models\Customer, because the name is already in use 错误的原因。


堆栈跟踪:

来自 Laravel.log:

[2021-03-22 10:29:23] production.ERROR: Cannot declare class App\Models\Customer, because the name is already in use {"userId":1127215,"exception":"[object] (Symfony\Component\ErrorHandler\Error\FatalError(code: 0): Cannot declare class App\Models\Customer, because the name is already in use at /var/app/current/app/Models/Customer.php:13) [stacktrace]

你在数据库中更新你的关系吗?也许您应该在生产服务器上刷新迁移。

If you're using a model other than Laravel's supplied App\Models\User model, you'll need to publish and alter the Cashier migrations provided to match your alternative model's table name.

另一个可能的问题是您没有为授权设置合适的模型。

// auth.php
'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\Models\Customer::class,
    ],
],

还要确保您的模型具有正确的命名空间。

PHP 可能不会报告重复的 classes,而没有重复的 classes。

通常存在三种可能的陷阱:

A) 重复项 class 的问题可能是由重复项 class.
引起的 这可以通过查找并删除有问题的 class 文件来解决,例如:

find . | grep Customer.php

这应该return两个结果,其中一个导致了错误信息;然后 运行 rm filename.

B) 它可能来自一个过时的 autoload.php,可以通过 运行ning composer dump-autoload.

刷新

C) 可能是命名空间的东西;例如。 use Stripe\Customer as StripeCustomer;


method 除了:

StripeSubscription::retrieve(
    ['id' => $this->stripe_id, 'expand' => $expand], $this->owner->stripeOptions()
 );

App\Models\Customer可能是SubscriptionBuilder.php$owner

我找到了解决方案。我不知道这一点,但这基本上是一个与 ENV 变量相关的缓存问题,以及我如何传递这些变量。

对于我们的 Elastic Beanstalk 暂存服务器,我通过 .ebextensions 文件夹中的 .config 文件声明环境变量。例如:

option_settings:
  "aws:elasticbeanstalk:application:environment":
     APP_NAME: Membership
     APP_ENV: production
     ...

这在大多数情况下都非常有效。您可以在 AWS 中看到变量,大多数应用程序将完全按预期工作。

但是在这种情况下,我需要确保我 运行 php artisan config:cache 作为部署的一部分(感谢@DimitriMostrey)。如果您这样做...它会忽略您已传递给 Elastic Beanstalk 的 ENV 变量!呵呵

我不知道为什么,因为您可以轻松确认您的应用程序能够读取 env('DB_HOST') 等,但它实际上无法使用它们连接到您的数据库或其他任何东西。

如果您不这样做 运行 config:cache,那么收银台将无法按预期工作(给出完全令人困惑的错误)。

所以我将我的生产环境变量从 .config 文件移动到他们自己的 .env 文件,然后在部署期间使用命令将该文件重命名为 .env

现在一切正常。

对于 Travis CI,情况类似:我将重要的环境变量移至 .env.travis,然后确保 运行 config:cache.travis.yml 中。

在 Travis 中 CI 现在一切也都按预期工作了。

我不知道 Elastic Beanstalk 环境变量的处理方式与 .env 文件中的不同...但我不会忘记的!