From bd87a946aa0941712286e251f2756f22c5552b29 Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Thu, 5 Nov 2026 19:59:23 +0800 Subject: [PATCH 1/2] fix(request): rename the array macro to inputArray Laravel 11+ ships a native Request::array(), and native methods win over macros, so on Laravel 12 this macro silently stops running. `?sort=a,b` and `?without=a,b` become a single value, and a sorted index returns a 500 for an unknown column. Renaming it now is safe on Laravel 10 and keeps the comma splitting after the upgrade. Callers and test harnesses follow the new name, with no behaviour change. --- src/Expansions/Request.php | 5 ++- .../Api/v1/ChatChannelController.php | 4 +-- .../Internal/v1/ChatChannelController.php | 2 +- .../Internal/v1/ChatMessageController.php | 2 +- .../Internal/v1/CompanyController.php | 6 ++-- .../Internal/v1/LookupController.php | 6 ++-- .../Internal/v1/PolicyController.php | 4 +-- .../Internal/v1/RoleController.php | 8 ++--- .../Internal/v1/SettingController.php | 32 +++++++++---------- .../Internal/v1/TwoFaController.php | 2 +- .../Internal/v1/UserController.php | 16 +++++----- src/Models/File.php | 2 +- src/Traits/HasApiModelBehavior.php | 8 ++--- .../Expansions/CoreExpansionContractsTest.php | 8 ++--- tests/Unit/Http/ChatChannelControllerTest.php | 4 +-- tests/Unit/Http/CommentControllerTest.php | 4 +-- tests/Unit/Http/CompanyControllerTest.php | 4 +-- tests/Unit/Http/FileControllerTest.php | 4 +-- tests/Unit/Http/GroupControllerTest.php | 4 +-- .../Http/LookupControllerContractsTest.php | 4 +-- tests/Unit/Http/PolicyControllerTest.php | 4 +-- tests/Unit/Http/RoleControllerTest.php | 4 +-- tests/Unit/Http/SettingControllerMailTest.php | 4 +-- ...tingControllerNotificationChannelsTest.php | 4 +-- .../Http/SettingControllerSaveConfigTest.php | 4 +-- tests/Unit/Http/TwoFaControllerTest.php | 4 +-- tests/Unit/Http/UserControllerTest.php | 4 +-- tests/Unit/SecurityFindingsTest.php | 2 +- tests/Unit/Traits/HasApiModelBehaviorTest.php | 4 +-- 29 files changed, 83 insertions(+), 80 deletions(-) diff --git a/src/Expansions/Request.php b/src/Expansions/Request.php index 42cf6ad5..eecd161a 100644 --- a/src/Expansions/Request.php +++ b/src/Expansions/Request.php @@ -67,8 +67,11 @@ public function or() * * @return \Closure returns a closure that splits a string parameter into an array, * or directly returns the array parameter + * + * Not named `array`: Laravel 11+ ships a native Request::array(), and native methods + * win over macros, so a macro of that name silently stops running. */ - public function array() + public function inputArray() { return function (string $param) { /** @var \Illuminate\Http\Request $this */ diff --git a/src/Http/Controllers/Api/v1/ChatChannelController.php b/src/Http/Controllers/Api/v1/ChatChannelController.php index d10aa787..b116c2ba 100644 --- a/src/Http/Controllers/Api/v1/ChatChannelController.php +++ b/src/Http/Controllers/Api/v1/ChatChannelController.php @@ -31,7 +31,7 @@ public function create(CreateChatChannelRequest $request) { // get request input $name = $request->input('name'); - $participants = $request->array('participants'); + $participants = $request->inputArray('participants'); // create the chat channel $chatChannel = ChatChannel::create([ @@ -273,7 +273,7 @@ public function sendMessage($id, Request $request) // Get the message contents and attachment file id $content = $request->input('content'); - $attachments = $request->array('files'); + $attachments = $request->inputArray('files'); // Create chat message $chatMessage = ChatMessage::create([ diff --git a/src/Http/Controllers/Internal/v1/ChatChannelController.php b/src/Http/Controllers/Internal/v1/ChatChannelController.php index 2fc1820f..e9ec97f2 100644 --- a/src/Http/Controllers/Internal/v1/ChatChannelController.php +++ b/src/Http/Controllers/Internal/v1/ChatChannelController.php @@ -28,7 +28,7 @@ public function createRecord(Request $request) try { $name = $request->input('chatChannel.name'); $meta = $request->input('chatChannel.meta', []); - $participants = $request->array('chatChannel.participants'); + $participants = $request->inputArray('chatChannel.participants'); $chatChannel = ChatChannel::create([ 'company_uuid' => session('company'), diff --git a/src/Http/Controllers/Internal/v1/ChatMessageController.php b/src/Http/Controllers/Internal/v1/ChatMessageController.php index 2a794229..61f26b4f 100644 --- a/src/Http/Controllers/Internal/v1/ChatMessageController.php +++ b/src/Http/Controllers/Internal/v1/ChatMessageController.php @@ -25,7 +25,7 @@ public function createRecord(Request $request) { try { $record = $this->model->createRecordFromRequest($request, null, function (&$request, &$chatMessage) { - $attachmentFiles = $request->array('chatMessage.attachment_files'); + $attachmentFiles = $request->inputArray('chatMessage.attachment_files'); // If has attachment files create the attachments foreach ($attachmentFiles as $attachmentFileId) { diff --git a/src/Http/Controllers/Internal/v1/CompanyController.php b/src/Http/Controllers/Internal/v1/CompanyController.php index f9baaffa..4d45b26c 100644 --- a/src/Http/Controllers/Internal/v1/CompanyController.php +++ b/src/Http/Controllers/Internal/v1/CompanyController.php @@ -179,7 +179,7 @@ public function getTwoFactorSettings() */ public function saveTwoFactorSettings(Request $request) { - $twoFaSettings = $request->array('twoFaSettings'); + $twoFaSettings = $request->inputArray('twoFaSettings'); $company = Auth::getCompany(); if (!$company) { @@ -269,7 +269,7 @@ public function users(string $id, Request $request) $searchQuery = $request->searchQuery(); $limit = $request->input(['limit', 'nestedLimit'], 20); $paginate = $request->boolean('paginate'); - $exclude = $request->array('exclude'); + $exclude = $request->inputArray('exclude'); // Start user query $usersQuery = CompanyUser::where('company_uuid', $company->uuid) @@ -580,7 +580,7 @@ public function removeAdminUser(string $id, string $userId, AdminRequest $reques public function export(ExportRequest $request) { $format = $request->input('format', 'xlsx'); - $selections = $request->array('selections'); + $selections = $request->inputArray('selections'); $fileName = trim(Str::slug('company-' . date('Y-m-d-H:i')) . '.' . $format); return Excel::download(new CompanyExport($selections), $fileName); diff --git a/src/Http/Controllers/Internal/v1/LookupController.php b/src/Http/Controllers/Internal/v1/LookupController.php index 9c574c12..701effa6 100644 --- a/src/Http/Controllers/Internal/v1/LookupController.php +++ b/src/Http/Controllers/Internal/v1/LookupController.php @@ -132,9 +132,9 @@ public function countries(Request $request) { $query = strtolower($request->input('query', null)); $simple = $request->boolean('simple'); - $columns = $request->array('columns'); - $only = array_map(fn ($s) => strtolower($s), $request->array('only')); - $except = array_map(fn ($s) => strtolower($s), $request->array('except')); + $columns = $request->inputArray('columns'); + $only = array_map(fn ($s) => strtolower($s), $request->inputArray('only')); + $except = array_map(fn ($s) => strtolower($s), $request->inputArray('except')); $countries = Country::search($query); diff --git a/src/Http/Controllers/Internal/v1/PolicyController.php b/src/Http/Controllers/Internal/v1/PolicyController.php index cc03a8e3..2a95a85d 100644 --- a/src/Http/Controllers/Internal/v1/PolicyController.php +++ b/src/Http/Controllers/Internal/v1/PolicyController.php @@ -34,7 +34,7 @@ public function createRecord(Request $request) try { $record = $this->model->createRecordFromRequest($request, null, function ($request, &$policy) { if ($request->isArray('policy.permissions')) { - $permissions = Permission::whereIn('id', $request->array('policy.permissions'))->get(); + $permissions = Permission::whereIn('id', $request->inputArray('policy.permissions'))->get(); $policy->syncPermissions($permissions); } }); @@ -59,7 +59,7 @@ public function updateRecord(Request $request, string $id) try { $record = $this->model->updateRecordFromRequest($request, $id, function ($request, &$policy) { if ($request->isArray('policy.permissions')) { - $permissions = Permission::whereIn('id', $request->array('policy.permissions'))->get(); + $permissions = Permission::whereIn('id', $request->inputArray('policy.permissions'))->get(); $policy->syncPermissions($permissions); } }); diff --git a/src/Http/Controllers/Internal/v1/RoleController.php b/src/Http/Controllers/Internal/v1/RoleController.php index a488e2ca..bea89f7e 100644 --- a/src/Http/Controllers/Internal/v1/RoleController.php +++ b/src/Http/Controllers/Internal/v1/RoleController.php @@ -43,13 +43,13 @@ public function createRecord(Request $request) $record = $this->model->createRecordFromRequest($request, null, function ($request, &$role) { // Sync Permissions if ($request->isArray('role.permissions')) { - $permissions = Permission::whereIn('id', $request->array('role.permissions'))->get(); + $permissions = Permission::whereIn('id', $request->inputArray('role.permissions'))->get(); $role->syncPermissions($permissions); } // Sync Policies if ($request->isArray('role.policies')) { - $policies = $this->getAssignablePolicies($request->array('role.policies')); + $policies = $this->getAssignablePolicies($request->inputArray('role.policies')); $role->syncPolicies($policies); } }); @@ -75,13 +75,13 @@ public function updateRecord(Request $request, string $id) $record = $this->model->updateRecordFromRequest($request, $id, function ($request, &$role) { // Sync Permissions if ($request->isArray('role.permissions')) { - $permissions = Permission::whereIn('id', $request->array('role.permissions'))->get(); + $permissions = Permission::whereIn('id', $request->inputArray('role.permissions'))->get(); $role->syncPermissions($permissions); } // Sync Policies if ($request->isArray('role.policies')) { - $policies = $this->getAssignablePolicies($request->array('role.policies')); + $policies = $this->getAssignablePolicies($request->inputArray('role.policies')); $role->syncPolicies($policies); } }); diff --git a/src/Http/Controllers/Internal/v1/SettingController.php b/src/Http/Controllers/Internal/v1/SettingController.php index 40364756..1ee21bc9 100644 --- a/src/Http/Controllers/Internal/v1/SettingController.php +++ b/src/Http/Controllers/Internal/v1/SettingController.php @@ -327,13 +327,13 @@ public function getMailConfig(AdminRequest $request) public function saveMailConfig(AdminRequest $request) { $mailer = $request->input('mailer', 'smtp'); - $from = $request->array('from', []); - $smtp = $request->array('smtp'); - $mailgun = $request->array('mailgun'); - $postmark = $request->array('postmark'); - $sendgrid = $request->array('sendgrid'); - $resend = $request->array('resend'); - $microsoftGraph = $request->array('microsoftGraph'); + $from = $request->inputArray('from', []); + $smtp = $request->inputArray('smtp'); + $mailgun = $request->inputArray('mailgun'); + $postmark = $request->inputArray('postmark'); + $sendgrid = $request->inputArray('sendgrid'); + $resend = $request->inputArray('resend'); + $microsoftGraph = $request->inputArray('microsoftGraph'); Setting::configureSystem('mail.mailer', $mailer); Setting::configureSystem('mail.from', $from); @@ -372,11 +372,11 @@ public function testMailConfig(AdminRequest $request) ] ); $smtp = $request->input('smtp', []); - $microsoftGraph = $request->array('microsoftGraph'); - $mailgun = $request->array('mailgun'); - $postmark = $request->array('postmark'); - $sendgrid = $request->array('sendgrid'); - $resend = $request->array('resend'); + $microsoftGraph = $request->inputArray('microsoftGraph'); + $mailgun = $request->inputArray('mailgun'); + $postmark = $request->inputArray('postmark'); + $sendgrid = $request->inputArray('sendgrid'); + $resend = $request->inputArray('resend'); $user = $request->user(); $message = 'Mail configuration is successful, check your inbox for the test email to confirm.'; $status = 'success'; @@ -646,8 +646,8 @@ public function getNotificationChannelsConfig(AdminRequest $request) */ public function saveNotificationChannelsConfig(AdminRequest $request) { - $apn = array_merge(config('broadcasting.connections.apn', []), $request->array('apn', [])); - $firebase = array_merge(config('firebase.projects.app', []), $request->array('firebase', [])); + $apn = array_merge(config('broadcasting.connections.apn', []), $request->inputArray('apn', [])); + $firebase = array_merge(config('firebase.projects.app', []), $request->inputArray('firebase', [])); // Get the APN key file and it's contents and store to config $apn = static::_setupApnConfigUsingFileId($apn); @@ -675,8 +675,8 @@ public function testNotificationChannelsConfig(AdminRequest $request) $message = $request->input('message', 'This is a test push notification!'); $apnToken = $request->input('apnToken'); $fcmToken = $request->input('fcmToken'); - $apn = $request->array('apn', config('broadcasting.connections.apn')); - $firebase = $request->array('firebase', config('firebase.projects.app')); + $apn = $request->inputArray('apn', config('broadcasting.connections.apn')); + $firebase = $request->inputArray('firebase', config('firebase.projects.app')); // Get the APN key file and it's contents and store to config $apn = static::_setupApnConfigUsingFileId($apn); diff --git a/src/Http/Controllers/Internal/v1/TwoFaController.php b/src/Http/Controllers/Internal/v1/TwoFaController.php index 7fb7f632..d3464c38 100644 --- a/src/Http/Controllers/Internal/v1/TwoFaController.php +++ b/src/Http/Controllers/Internal/v1/TwoFaController.php @@ -34,7 +34,7 @@ public function __construct() */ public function saveSystemConfig(Request $request) { - $twoFaSettings = $request->array('twoFaSettings'); + $twoFaSettings = $request->inputArray('twoFaSettings'); if (isset($twoFaSettings['enabled']) && $twoFaSettings['enabled'] === false) { $twoFaSettings['enforced'] = false; } diff --git a/src/Http/Controllers/Internal/v1/UserController.php b/src/Http/Controllers/Internal/v1/UserController.php index abee4653..c466b6e3 100644 --- a/src/Http/Controllers/Internal/v1/UserController.php +++ b/src/Http/Controllers/Internal/v1/UserController.php @@ -228,13 +228,13 @@ public function createRecord(Request $request) // Sync Permissions if ($request->isArray('user.permissions')) { - $permissions = Permission::whereIn('id', $request->array('user.permissions'))->get(); + $permissions = Permission::whereIn('id', $request->inputArray('user.permissions'))->get(); $user->syncPermissions($permissions); } // Sync Policies if ($request->isArray('user.policies')) { - $policies = $this->getAssignablePolicies($request->array('user.policies')); + $policies = $this->getAssignablePolicies($request->inputArray('user.policies')); $user->syncPolicies($policies); } }); @@ -306,13 +306,13 @@ public function updateRecord(Request $request, string $id) // Sync Permissions if ($request->isArray('user.permissions')) { - $permissions = Permission::whereIn('id', $request->array('user.permissions'))->get(); + $permissions = Permission::whereIn('id', $request->inputArray('user.permissions'))->get(); $record->syncPermissions($permissions); } // Sync Policies if ($request->isArray('user.policies')) { - $policies = $this->getAssignablePolicies($request->array('user.policies')); + $policies = $this->getAssignablePolicies($request->inputArray('user.policies')); $record->syncPolicies($policies); } @@ -705,7 +705,7 @@ public function getTwoFactorSettings(Request $request) #[SkipAuthorizationCheck] public function saveTwoFactorSettings(Request $request) { - $twoFaSettings = $request->array('twoFaSettings'); + $twoFaSettings = $request->inputArray('twoFaSettings'); $user = $request->user(); if (!$user) { @@ -933,11 +933,11 @@ private function promoteManagedAccount(User $user, Request $request, Role $role) $user->assignSingleRole($role); if ($request->isArray('user.permissions')) { - $user->syncPermissions(Permission::whereIn('id', $request->array('user.permissions'))->get()); + $user->syncPermissions(Permission::whereIn('id', $request->inputArray('user.permissions'))->get()); } if ($request->isArray('user.policies')) { - $user->syncPolicies($this->getAssignablePolicies($request->array('user.policies'))); + $user->syncPolicies($this->getAssignablePolicies($request->inputArray('user.policies'))); } if ($user->email && !Invite::isAlreadySentToJoinCompany($user, $company)) { @@ -1528,7 +1528,7 @@ public function searchRecords(Request $request) public function export(ExportRequest $request) { $format = $request->input('format', 'xlsx'); - $selections = $request->array('selections'); + $selections = $request->inputArray('selections'); $fileName = trim(Str::slug('users-' . date('Y-m-d-H:i')) . '.' . $format); return Excel::download(new UserExport($selections), $fileName); diff --git a/src/Models/File.php b/src/Models/File.php index 19b32734..539eba82 100644 --- a/src/Models/File.php +++ b/src/Models/File.php @@ -673,7 +673,7 @@ public static function storageExtensionForUpload(UploadedFile $file): string */ public static function fromRequest(Request $request, string $param = 'files'): Collection { - $ids = $request->array($param); + $ids = $request->inputArray($param); return static::whereIn('uuid', $ids)->get(); } diff --git a/src/Traits/HasApiModelBehavior.php b/src/Traits/HasApiModelBehavior.php index a588056b..42401b57 100644 --- a/src/Traits/HasApiModelBehavior.php +++ b/src/Traits/HasApiModelBehavior.php @@ -565,7 +565,7 @@ function ($model) use ($request) { } $with = RequestRelations::eagerLoads($result, $request->or(['with', 'expand'], [])); - $without = array_filter($request->array('without'), 'is_string'); + $without = array_filter($request->inputArray('without'), 'is_string'); if ($with) { $result->load($with); @@ -629,7 +629,7 @@ public function fillSessionAttributes(?array $target = [], array $except = [], a public function withRelationships(Request $request, $builder) { $with = $request->or(['with', 'expand']); - $without = $request->array('without', []); + $without = $request->inputArray('without', []); if (!$with && !$without) { return $builder; @@ -682,7 +682,7 @@ public function withCounts($request, $builder) public function applySorts($request, $builder) { // Grab the raw sort input - $sorts = (array) $request->array('sort'); + $sorts = (array) $request->inputArray('sort'); // Nothing to sort by if (empty($sorts)) { @@ -923,7 +923,7 @@ public function applyCustomFilters(Request $request, $builder) // handle with/without here $with = $request->or(['with', 'expand'], []); - $without = $request->array('without'); + $without = $request->inputArray('without'); $withoutRelations = $request->boolean('without_relations'); // apply only the requested names that are relations of this model diff --git a/tests/Unit/Expansions/CoreExpansionContractsTest.php b/tests/Unit/Expansions/CoreExpansionContractsTest.php index d00cd8e6..721486e3 100644 --- a/tests/Unit/Expansions/CoreExpansionContractsTest.php +++ b/tests/Unit/Expansions/CoreExpansionContractsTest.php @@ -313,7 +313,7 @@ function core_expansion_builder_database(): Capsule $expansion = new RequestExpansion(); HttpRequest::macro('or', $expansion->or()); - HttpRequest::macro('array', $expansion->array()); + HttpRequest::macro('inputArray', $expansion->inputArray()); app('db')->connection('mysql')->table('companies')->insert([ 'uuid' => 'company-1', @@ -378,9 +378,9 @@ function core_expansion_builder_database(): Capsule ]) ->and($expansion->or()->call($request, ['missing', 'status'], 'fallback'))->toBe('active') ->and($expansion->or()->call($request, ['missing'], 'fallback'))->toBe('fallback') - ->and($expansion->array()->call($request, 'ids'))->toBe(['one', 'two', 'three']) - ->and($expansion->array()->call($request, 'tags'))->toBe(['fragile', 'cold']) - ->and($expansion->array()->call($request, 'missing'))->toBe([]) + ->and($expansion->inputArray()->call($request, 'ids'))->toBe(['one', 'two', 'three']) + ->and($expansion->inputArray()->call($request, 'tags'))->toBe(['fragile', 'cold']) + ->and($expansion->inputArray()->call($request, 'missing'))->toBe([]) ->and($expansion->isString()->call($request, 'status'))->toBeTrue() ->and($expansion->isUuid()->call($request, 'uuid'))->toBeTrue() ->and($expansion->isArray()->call($request, 'tags'))->toBeTrue() diff --git a/tests/Unit/Http/ChatChannelControllerTest.php b/tests/Unit/Http/ChatChannelControllerTest.php index f74da3ec..d066fa0c 100644 --- a/tests/Unit/Http/ChatChannelControllerTest.php +++ b/tests/Unit/Http/ChatChannelControllerTest.php @@ -287,8 +287,8 @@ function chat_channel_controller_database(): Capsule SupportStr::macro('humanize', $strExpansion->humanize()); } - if (!Request::hasMacro('array')) { - Request::macro('array', function (string $key, array $default = []): array { + if (!Request::hasMacro('inputArray')) { + Request::macro('inputArray', function (string $key, array $default = []): array { $value = $this->input($key, $default); return is_array($value) ? $value : $default; diff --git a/tests/Unit/Http/CommentControllerTest.php b/tests/Unit/Http/CommentControllerTest.php index 05adae52..922eb702 100644 --- a/tests/Unit/Http/CommentControllerTest.php +++ b/tests/Unit/Http/CommentControllerTest.php @@ -104,8 +104,8 @@ function comment_controller_database(): Capsule SupportStr::macro('humanize', $strExpansion->humanize()); } - if (!Request::hasMacro('array')) { - Request::macro('array', function (string $key, array $default = []): array { + if (!Request::hasMacro('inputArray')) { + Request::macro('inputArray', function (string $key, array $default = []): array { $value = $this->input($key, $default); return is_array($value) ? $value : $default; diff --git a/tests/Unit/Http/CompanyControllerTest.php b/tests/Unit/Http/CompanyControllerTest.php index 74b65700..5cbe2845 100644 --- a/tests/Unit/Http/CompanyControllerTest.php +++ b/tests/Unit/Http/CompanyControllerTest.php @@ -392,8 +392,8 @@ function company_controller_fixtures(): Capsule }); } - if (!Request::hasMacro('array')) { - Request::macro('array', function (string $key, array $default = []): array { + if (!Request::hasMacro('inputArray')) { + Request::macro('inputArray', function (string $key, array $default = []): array { $value = $this->input($key, $default); if (is_string($value) && str_contains($value, ',')) { diff --git a/tests/Unit/Http/FileControllerTest.php b/tests/Unit/Http/FileControllerTest.php index 109fa911..20aa7f9f 100644 --- a/tests/Unit/Http/FileControllerTest.php +++ b/tests/Unit/Http/FileControllerTest.php @@ -231,8 +231,8 @@ function file_controller_fixtures(): Capsule EloquentModel::clearBootedModels(); $_SERVER['REQUEST_METHOD'] = 'GET'; - if (!Request::hasMacro('array')) { - Request::macro('array', function (string $key, array $default = []): array { + if (!Request::hasMacro('inputArray')) { + Request::macro('inputArray', function (string $key, array $default = []): array { $value = $this->input($key, $default); return is_array($value) ? $value : $default; diff --git a/tests/Unit/Http/GroupControllerTest.php b/tests/Unit/Http/GroupControllerTest.php index 2a09b915..0271101b 100644 --- a/tests/Unit/Http/GroupControllerTest.php +++ b/tests/Unit/Http/GroupControllerTest.php @@ -163,8 +163,8 @@ function group_controller_boot_request_macros(): void }); } - if (!Request::hasMacro('array')) { - Request::macro('array', function (string $param) { + if (!Request::hasMacro('inputArray')) { + Request::macro('inputArray', function (string $param) { return (array) $this->input($param, []); }); } diff --git a/tests/Unit/Http/LookupControllerContractsTest.php b/tests/Unit/Http/LookupControllerContractsTest.php index 109312de..f7d6a4c7 100644 --- a/tests/Unit/Http/LookupControllerContractsTest.php +++ b/tests/Unit/Http/LookupControllerContractsTest.php @@ -149,8 +149,8 @@ function lookup_controller_boot(?LookupControllerContractsCacheFake $cache = nul { bind_test_container(); - if (!Request::hasMacro('array')) { - Request::macro('array', function (string $key, array $default = []): array { + if (!Request::hasMacro('inputArray')) { + Request::macro('inputArray', function (string $key, array $default = []): array { $value = $this->input($key, $default); return is_array($value) ? $value : $default; diff --git a/tests/Unit/Http/PolicyControllerTest.php b/tests/Unit/Http/PolicyControllerTest.php index 39492ec5..ef167bb9 100644 --- a/tests/Unit/Http/PolicyControllerTest.php +++ b/tests/Unit/Http/PolicyControllerTest.php @@ -132,8 +132,8 @@ function policy_controller_boot_request_macros(): void }); } - if (!Request::hasMacro('array')) { - Request::macro('array', function (string $param) { + if (!Request::hasMacro('inputArray')) { + Request::macro('inputArray', function (string $param) { return (array) $this->input($param, []); }); } diff --git a/tests/Unit/Http/RoleControllerTest.php b/tests/Unit/Http/RoleControllerTest.php index 0fa96ad0..2688133b 100644 --- a/tests/Unit/Http/RoleControllerTest.php +++ b/tests/Unit/Http/RoleControllerTest.php @@ -152,8 +152,8 @@ public function syncPolicies($policies): self function role_controller_boot_request_macros(): void { - if (!Request::hasMacro('array')) { - Request::macro('array', function (string $key, array $default = []): array { + if (!Request::hasMacro('inputArray')) { + Request::macro('inputArray', function (string $key, array $default = []): array { return (array) $this->input($key, $default); }); } diff --git a/tests/Unit/Http/SettingControllerMailTest.php b/tests/Unit/Http/SettingControllerMailTest.php index bdb9c8b2..1e4d2854 100644 --- a/tests/Unit/Http/SettingControllerMailTest.php +++ b/tests/Unit/Http/SettingControllerMailTest.php @@ -25,8 +25,8 @@ public function send(mixed $mailable): void function setting_controller_mail_fixtures(): SettingControllerMailFake { - if (!Request::hasMacro('array')) { - Request::macro('array', function (string $key, array $default = []): array { + if (!Request::hasMacro('inputArray')) { + Request::macro('inputArray', function (string $key, array $default = []): array { $value = $this->input($key, $default); return is_array($value) ? $value : $default; diff --git a/tests/Unit/Http/SettingControllerNotificationChannelsTest.php b/tests/Unit/Http/SettingControllerNotificationChannelsTest.php index 360aa03f..5c3ad428 100644 --- a/tests/Unit/Http/SettingControllerNotificationChannelsTest.php +++ b/tests/Unit/Http/SettingControllerNotificationChannelsTest.php @@ -31,8 +31,8 @@ public function sendNow($notifiables, $notification, ?array $channels = null): v function setting_controller_notification_fixtures(): SettingControllerNotificationDispatcherFake { - if (!Request::hasMacro('array')) { - Request::macro('array', function (string $key, array $default = []): array { + if (!Request::hasMacro('inputArray')) { + Request::macro('inputArray', function (string $key, array $default = []): array { $value = $this->input($key, $default); return is_array($value) ? $value : $default; diff --git a/tests/Unit/Http/SettingControllerSaveConfigTest.php b/tests/Unit/Http/SettingControllerSaveConfigTest.php index ce85f20b..b23d17be 100644 --- a/tests/Unit/Http/SettingControllerSaveConfigTest.php +++ b/tests/Unit/Http/SettingControllerSaveConfigTest.php @@ -275,8 +275,8 @@ function setting_controller_save_config_database(array $config = []): array { EloquentModel::clearBootedModels(); - if (!Request::hasMacro('array')) { - Request::macro('array', function (string $key, array $default = []): array { + if (!Request::hasMacro('inputArray')) { + Request::macro('inputArray', function (string $key, array $default = []): array { $value = $this->input($key, $default); return is_array($value) ? $value : $default; diff --git a/tests/Unit/Http/TwoFaControllerTest.php b/tests/Unit/Http/TwoFaControllerTest.php index 35128a70..1df6c6a3 100644 --- a/tests/Unit/Http/TwoFaControllerTest.php +++ b/tests/Unit/Http/TwoFaControllerTest.php @@ -167,8 +167,8 @@ function two_fa_controller_database(): TwoFaControllerRedisFake 'fleetbase.connection.db' => 'mysql', ]); - if (!Request::hasMacro('array')) { - Request::macro('array', function (string $key, array $default = []): array { + if (!Request::hasMacro('inputArray')) { + Request::macro('inputArray', function (string $key, array $default = []): array { $value = $this->input($key, $default); return is_array($value) ? $value : $default; diff --git a/tests/Unit/Http/UserControllerTest.php b/tests/Unit/Http/UserControllerTest.php index 44fce37e..095bb25f 100644 --- a/tests/Unit/Http/UserControllerTest.php +++ b/tests/Unit/Http/UserControllerTest.php @@ -440,8 +440,8 @@ function user_controller_database(): Capsule }); } - if (!Request::hasMacro('array')) { - Request::macro('array', function (string $key, array $default = []): array { + if (!Request::hasMacro('inputArray')) { + Request::macro('inputArray', function (string $key, array $default = []): array { $value = $this->input($key, $default); if (is_string($value) && str_contains($value, ',')) { diff --git a/tests/Unit/SecurityFindingsTest.php b/tests/Unit/SecurityFindingsTest.php index 8cce8af0..0c78d866 100644 --- a/tests/Unit/SecurityFindingsTest.php +++ b/tests/Unit/SecurityFindingsTest.php @@ -95,7 +95,7 @@ function bind_security_findings_config(array $values = []): void expect($source)->toContain('$this->getAssignablePolicies(') ->and($source)->toContain("->where('company_uuid', session('company'))") ->and($source)->toContain('->orWhereNull(\'company_uuid\')') - ->and($source)->not->toContain('Policy::whereIn(\'id\', $request->array(\'role.policies\'))->get()'); + ->and($source)->not->toContain('Policy::whereIn(\'id\', $request->inputArray(\'role.policies\'))->get()'); }); // File download cross-tenant scoping is covered behaviorally (ModelNotFoundException on a diff --git a/tests/Unit/Traits/HasApiModelBehaviorTest.php b/tests/Unit/Traits/HasApiModelBehaviorTest.php index 4c624324..bb47f2d2 100644 --- a/tests/Unit/Traits/HasApiModelBehaviorTest.php +++ b/tests/Unit/Traits/HasApiModelBehaviorTest.php @@ -479,8 +479,8 @@ function has_api_model_behavior_request(array $input = [], string $uri = '/api/v }); } - if (!Request::hasMacro('array')) { - Request::macro('array', function (string $key, array $default = []): array { + if (!Request::hasMacro('inputArray')) { + Request::macro('inputArray', function (string $key, array $default = []): array { $value = $this->input($key, $default); if (is_string($value) && str_contains($value, ',')) { From 739d941c4924f9223ffedaf02bca50f0380f6d9a Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Thu, 5 Nov 2026 20:27:41 +0800 Subject: [PATCH 2/2] fix(request): keep array as an alias until the extensions move Released extensions still call the old name, and removing it breaks them against a core-api with this change. Storefront's suite hit that through released fleetops. --- src/Expansions/Request.php | 10 ++++++++++ tests/Unit/Expansions/CoreExpansionContractsTest.php | 1 + 2 files changed, 11 insertions(+) diff --git a/src/Expansions/Request.php b/src/Expansions/Request.php index eecd161a..12dfc915 100644 --- a/src/Expansions/Request.php +++ b/src/Expansions/Request.php @@ -62,6 +62,16 @@ public function or() }; } + /** + * Alias of inputArray() for extensions that haven't moved to the new name yet. + * + * @deprecated use inputArray(); on Laravel 11+ the native Request::array() wins over this macro + */ + public function array() + { + return $this->inputArray(); + } + /** * Converts a specified request parameter into an array by splitting it by commas. * diff --git a/tests/Unit/Expansions/CoreExpansionContractsTest.php b/tests/Unit/Expansions/CoreExpansionContractsTest.php index 721486e3..582fa882 100644 --- a/tests/Unit/Expansions/CoreExpansionContractsTest.php +++ b/tests/Unit/Expansions/CoreExpansionContractsTest.php @@ -379,6 +379,7 @@ function core_expansion_builder_database(): Capsule ->and($expansion->or()->call($request, ['missing', 'status'], 'fallback'))->toBe('active') ->and($expansion->or()->call($request, ['missing'], 'fallback'))->toBe('fallback') ->and($expansion->inputArray()->call($request, 'ids'))->toBe(['one', 'two', 'three']) + ->and($expansion->array()->call($request, 'ids'))->toBe(['one', 'two', 'three']) ->and($expansion->inputArray()->call($request, 'tags'))->toBe(['fragile', 'cold']) ->and($expansion->inputArray()->call($request, 'missing'))->toBe([]) ->and($expansion->isString()->call($request, 'status'))->toBeTrue()