Tags: fleetbase/core-api
Tags
Two related errors were reported in production: ``` DEPRECATED mb_strtolower(): Passing null to parameter #1 ($string) of type string is deprecated in vendor/laravel/framework/src/Illuminate/Support/Str.php on line 611. TypeError: Fleetbase\Support\Utils::getCurrenyFromCountryCode(): Return value must be of type ?string, array returned (Utils.php:1235) ``` The `fleetbase/countries` package (a fork of PragmaRX Countries) returns the `currencies` field in **two distinct shapes** depending on the underlying data source: | Shape | Example | Scope | |---|---|---| | Sequential list of ISO 4217 strings | `["USD"]` | Most countries (239) | | Associative map — code as key, detail object as value | `{"USD": {"name": "United States dollar", "symbol": "$"}}` | 10 territories: BQ, CC, CX, GP, GF, MQ, YT, RE, SJ, TK | The previous code used `Arr::first()` unconditionally on the `currencies` collection: ```php // Before 'currency' => Arr::first(static::get($country, 'currencies', [])), ``` - **List shape** — `Arr::first()` returns the first *element* (the code string). ✅ - **Map shape** — `Arr::first()` returns the first *value* (an array like `["name" => "...", "symbol" => "..."]`). ❌ This array then propagated into the cached country data and was returned from `getCurrenyFromCountryCode()`, whose return type is `?string`, causing the `TypeError`. A secondary issue existed in `getCountryCodeByCurrency()` which used the dot-notation shorthand `currencies.0` (only valid for list-shape countries) and then called `strtolower($country['currency'])` without a null guard, triggering the `mb_strtolower(null)` deprecation for map-shape territories. Introduce a new `Utils::resolveCurrencyCode($currencies): ?string` helper that normalises both shapes: ```php public static function resolveCurrencyCode($currencies): ?string { if (empty($currencies)) { return null; } // Convert Coollection / Collection objects to a plain array. if (is_object($currencies) && method_exists($currencies, 'toArray')) { $currencies = $currencies->toArray(); } if (!is_array($currencies)) { return null; } // Sequential list shape: ["USD", "EUR", ...] if (array_is_list($currencies)) { $code = Arr::first($currencies); return is_string($code) ? $code : null; } // Associative map shape: {"USD": {"name": "...", "symbol": "..."}, ...} $code = array_key_first($currencies); return is_string($code) ? $code : null; } ``` - **`getCountryData()`** — replace `Arr::first(...currencies...)` with `resolveCurrencyCode()` so the cached country data always stores a string currency code, never an array. - **`getCountryCodeByCurrency()`** — replace `currencies.0` dot-notation with `resolveCurrencyCode()` (fixes map-shape countries), and add an `is_string()` guard before `strtolower()` to eliminate the `mb_strtolower(null)` deprecation. The following 10 territories had associative-map currencies and were broken before this fix: | cca2 | Territory | Currency | |---|---|---| | BQ | Caribbean Netherlands | USD | | CC | Cocos (Keeling) Islands | AUD | | CX | Christmas Island | AUD | | GP | Guadeloupe | EUR | | GF | French Guiana | EUR | | MQ | Martinique | EUR | | YT | Mayotte | EUR | | RE | Réunion | EUR | | SJ | Svalbard and Jan Mayen | NOK | | TK | Tokelau | NZD |
PreviousNext