Laravel:无法声明类AppModelsCustomer,因为该名称已被使用
我有点困惑。我在我的用户(实际上是“客户”)模型上有一个简单的方法来返回用户的订阅续订日期:
public function subscriptionRenewalDate() : string
{
$subscription = $this->subscriptions()->active()->first()->asStripeSubscription();
return Carbon::createFromTimeStamp($subscription->current_period_end)->format('F jS, Y');
}
我从刀片模板 ( {{ auth()->user()->subscriptionRenewalDate() }})对经过身份验证的用户调用此方法,它在本地工作正常,但是一旦我将其上传到远程登台服务器,它就会失败并显示错误:
无法声明类 AppModelsCustomer,因为该名称已被使用
它指向 Customer 模型中的这一行:
class Customer extends Authenticatable
{
奇怪的是,它不仅仅是远程登台服务器,它也是 Travis CI 失败的地方(运行 PHPUnit 测试时——这些相同的测试在本地工作正常)。
显然,这似乎是某种缓存或配置问题,但我无法理解是什么导致了此错误。
它与数据库无关,因为测试使用RefreshDatabase. 如果我删除 ENV 变量 ( CASHIER_MODEL: AppModelsCustomer),它会因预期的“找不到模型用户”错误而失败,因此它正确获取了 ENV 变量。我尝试清除我的 Laravel 缓存 ( php artisan optimize:clear) 和composer dump-autoload. 这很令人困惑。
我所知道的是该错误是由asStripeSubscription(). 如果我从方法中删除它,刀片模板加载正常(一切正常)。
需要明确的是,我可以成功(这是本地、远程和 Travis CI):
- 在 Laravel 中注册
- 登录 Laravel
- 重置我的密码
- 更新我的个人资料
- 输入付款信息以订阅 Stripe 订阅
- 查看和修改我的 Stripe 订阅
- 在 Stripe.com 上查看我的所有客户和订阅信息
- 在 Stripe.com 上编辑我的信息并查看通过我服务器上的 webhook 更新的信息
asStripeSubscription()出现问题的唯一时间是在代码中出现时。它仅在远程服务器上。在本地,即使这样也能正常工作。
我试过把这个电话转移到各种模型上。我试过从控制器调用它并将结果传递给视图。我什至尝试重新启动服务器并清除 Travis CI 的缓存。错误保持不变。
什么会导致asStripeSubscription()产生这个错误?如果我可以在本地复制,我可以调试它!它固执地坚持在本地完美工作,但远程失败。
我使用的是 Laravel 8、PHP 7.3 和 Cashier 12.10。
我只是无法理解会导致Cannot declare class AppModelsCustomer, because the name is already in use错误的原因。
堆栈跟踪:
来自 Laravel.log:
[2021-03-22 10:29:23] production.ERROR:无法声明类 AppModelsCustomer,因为名称已被使用 {"userId":1127215,"exception":"[object] (Symfony ComponentErrorHandlerErrorFatalError(code: 0): 无法声明类 AppModelsCustomer,因为该名称已在 /var/app/current/app/Models/Customer.php:13) [stacktrace]
回答
我找到了解决方案。我不知道这一点,但这基本上是一个与 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那么 Cashier 将无法按预期工作(给出完全令人困惑的错误)。
所以我将我的生产环境变量从 .config 文件移动到他们自己的 .env 文件,然后.env在部署期间使用命令将该文件重命名为。
现在一切都按预期进行。
随着特拉维斯CI是类似的东西:我搬到了重要的环境变量.env.travis,然后确定我跑config:cache在.travis.yml。
在 Travis CI 中,现在一切都按预期进行。
我不知道 Elastic Beanstalk 环境变量的处理方式与 .env 文件中的环境变量不同……但我不会很快忘记!