控制器和闭包路由中的基本类型

发布时间 作者

Primitive Types in Controllers and Closure Routes image

我之前没有考虑过在 Laravel 控制器中对基本类型进行类型提示。PHP 只有四种标量基本类型:boolintfloatstring - 关于路由,stringint 是您最可能想要的类型。但是,我通常不会在我的控制器中对标量基本类型进行类型提示。

我最近看到一个由 TypeError 引起的对控制器操作进行类型提示的问题,因此我想演示一些可以在其中安全使用带有 int 类型的类型提示控制器的示例。

考虑以下路由操作,并思考当调用时 $orderId 将是什么类型

Route::get('/order/{order_id}', function ($orderId) {
return [
'type' => gettype($orderId),
'value' => $orderId,
];
});

当调用此闭包时,$orderId 将是一个 string。如果您进行快速测试,您将看到以下内容通过

/**
* A basic test example.
*
* @return void
*/
public function test_example()
{
$response = $this->get('/order/123');
 
$response->assertJson([
'type' => 'string',
'value' => '123',
]);
}

现在,假设您期望订单 ID 始终是一个整数,因此您想对参数进行类型提示

Route::get('/order/{order_id}', function (int $orderId) {
return [
'type' => gettype($orderId),
'value' => $orderId,
];
});

如果您返回到您的测试,它现在将失败,并显示以下输出

--- Expected
+++ Actual
@@ @@
array (
- 'type' => 'string',
- 'value' => '123',
+ 'type' => 'integer',
+ 'value' => 123,
)

尽管我们实际上将 123string 传递给路由函数,但 PHP 通过类型强制默认处理它。换句话说,PHP 在调用路由函数时尝试将我们的值从字符串转换为整数。

虽然从技术上讲这种方法将起作用并保证 integer 类型,但我们仍然有另一个您可能已经发现的问题:如果用户传递了一些无法从字符串转换为整数的内容怎么办?

如果我们将我们的测试更新为以下内容,我们将收到一个 TypeError

public function test_example()
{
$this->withoutExceptionHandling();
 
$response = $this->get('/order/ABC-123');
 
$response->assertJson([
'type' => 'integer',
'value' => 123,
]);
}

运行测试将给出以下错误

TypeError: Illuminate\Routing\RouteFileRegistrar::{closure}():
Argument #1 ($orderId) must be of type int, string given, called in .../vendor/laravel/framework/src/Illuminate/Routing/Route.php on line 238

如果我们想在路由中进行类型提示整数,我们应该确保我们的路由具有 正则表达式约束

Route::get('/order/{order_id}', function (int $orderId) {
return [
'type' => gettype($orderId),
'value' => $orderId,
];
})->where('order_id', '[0-9]+');

在添加路由参数约束后,只有数字值才能匹配路由,从而确保类型强制按预期工作。以下测试将更准确,以确保您无法使用非数字路由器参数匹配订单路由

public function test_example()
{
$response = $this->get('/order/ABC-123');
 
$response->assertNotFound();
}

现在,如果您想使用类型提示,您可以假设您的闭包路由的类型可以安全地强制转换为整数。虽然用例有限,但我认为了解这种细微差别可以帮助尝试对路由器参数进行类型提示的人们。

这如何受到严格类型的影响?

我想指出,declare(strict_types=1); 没有效果,因为调用代码位于 Laravel 框架内,该框架不使用 strict_types 声明,因此将发生类型强制

  1. Laravel 的 Controller::callAction() 用于控制器
  2. Laravel 的 Route::runCallable() 用于基于闭包的路由

在 PHP 的类型 声明文档 中,严格类型具有以下关于严格类型如何工作的说明

严格类型适用于从内部启用严格类型的文件进行的函数调用,而不适用于在该文件中声明的函数。如果未启用严格类型的文件调用在启用严格类型的文件中定义的函数,则将尊重调用者的首选项(强制类型),并且将强制转换该值。

其他方法

如果您在控制器和闭包中具有标量路由参数,您可以省略标量类型并在您的控制器方法中进行类型转换

Route::get(
'/order/{order_id}',
function ($orderId, SomeService $someService) {
// Cast for a method that strictly type-hints an integer
$result = $someService->someMethod((int) $orderId);
// ...
}
);

大多数情况下,您将使用 路由模型绑定 用于匹配数字 ID 的路由参数;但是,当您具有想要使用基本标量类型 int 进行类型提示的数字路由参数时,请考虑这种方法。

Paul Redmond photo

Laravel 新闻的特约撰稿人。全栈 Web 开发人员和作家。

Cube

Laravel 新闻通讯

加入 40,000 多名其他开发人员,绝不错过新的技巧、教程等。

Laravel Forge logo

Laravel Forge

轻松创建和管理您的服务器,并在几秒钟内部署您的 Laravel 应用程序。

Laravel Forge
Tinkerwell logo

Tinkerwell

Laravel 开发人员必备的代码运行器。使用 AI、自动完成功能和对本地和生产环境的即时反馈进行调试。

Tinkerwell
No Compromises logo

不妥协

Joel 和 Aaron,来自 No Compromises 播客的两位经验丰富的开发人员,现在可以为您的 Laravel 项目聘用。 ⬧ 固定价格 7500 美元/月。 ⬧ 没有冗长的销售流程。 ⬧ 没有合同。 ⬧ 100% 退款保证。

不妥协
Kirschbaum logo

Kirschbaum

提供创新和稳定性,以确保您的 Web 应用程序成功。

Kirschbaum
Shift logo

Shift

运行旧的 Laravel 版本?即时、自动化的 Laravel 升级和代码现代化,让您的应用程序保持新鲜。

Shift
Bacancy logo

Bacancy

只需每月 2500 美元,即可让经验丰富的 Laravel 开发人员(拥有 4-6 年经验)为您的项目增光添彩。获得 160 小时的专业知识和 15 天免费试用。立即预约通话!

Bacancy
Lucky Media logo

Lucky Media

立即获得幸运 - Laravel 开发的理想选择,拥有超过十年的经验!

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar:Laravel 电子商务

适用于 Laravel 的电子商务。一个开源软件包,为 Laravel 带来了现代无头电子商务功能的力量。

Lunar:Laravel 电子商务
LaraJobs logo

LaraJobs

官方 Laravel 工作板

LaraJobs
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit:Laravel SaaS 启动套件

SaaSykit 是一个 Laravel SaaS 启动套件,它包含运行现代 SaaS 所需的所有功能。支付、精美结帐、管理面板、用户仪表板、身份验证、现成组件、统计、博客、文档等等。

SaaSykit:Laravel SaaS 启动套件
Rector logo

Rector

您无缝 Laravel 升级、降低成本和加快创新的合作伙伴,为成功公司服务

Rector
MongoDB logo

MongoDB

通过强大的 MongoDB 和 Laravel 集成增强您的 PHP 应用程序,使开发人员能够轻松高效地构建应用程序。支持事务、搜索、分析和移动用例,同时使用熟悉的 Eloquent API。了解 MongoDB 的灵活的现代数据库如何改变您的 Laravel 应用程序。

MongoDB
Maska is a Simple Zero-dependency Input Mask Library image

Maska 是一个简单的零依赖输入掩码库

阅读文章
Add Swagger UI to Your Laravel Application image

将 Swagger UI 添加到您的 Laravel 应用程序

阅读文章
Assert the Exact JSON Structure of a Response in Laravel 11.19 image

在 Laravel 11.19 中断言响应的精确 JSON 结构

阅读文章
Build SSH Apps with PHP and Laravel Prompts image

使用 PHP 和 Laravel 提示构建 SSH 应用程序

阅读文章
Building fast, fuzzy site search with Laravel and Typesense image

使用 Laravel 和 Typesense 构建快速、模糊的网站搜索

阅读文章
Add Comments to your Laravel Application with the Commenter Package image

使用 Commenter 软件包向您的 Laravel 应用程序添加评论

阅读文章