{"record":{"id":"b431e8ecbbf8a03c","repo":"phalcon/cphalcon","slug":"parameter-replace-must-be-an-array-or-a-string","errorCode":null,"errorMessage":"Parameter replace must be an array or a string","messagePattern":"Parameter replace must be an array or a string","errorType":"exception","errorClass":"Phalcon\\Support\\Helper\\Str\\Exceptions\\InvalidReplaceFormat","httpStatus":null,"severity":"error","filePath":"phalcon/Support/Helper/Str/Friendly.zep","lineNumber":68,"sourceCode":"        if lowercase {\n            let friendly = this->toLower(friendly);\n        }\n\n        let friendly = preg_replace(\"/[\\\\/_|+ -]+/\", separator, friendly);\n\n        return trim(friendly, separator);\n    }\n\n    /**\n     * @param array<array-key, string>|string $replace\n     *\n     * @return array<array-key, string>\n     * @throws InvalidReplaceFormat\n     */\n    private function checkReplace(var replace) -> array\n    {\n        if typeof replace !== \"array\" && typeof replace !== \"string\" {\n            throw new InvalidReplaceFormat(\n                \"Parameter replace must be an array or a string\"\n            );\n        }\n\n        if typeof replace === \"string\" {\n            let replace = [replace];\n        }\n\n        return replace;\n    }\n\n    /**\n     * @param array<array-key, string> $replace\n     *\n     * @return array<string, string>\n     */\n    private function getMatrix(array replace) -> array\n    {","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Support/Helper/Str/Friendly.zep#L50-L86","documentation":"Phalcon\\Support\\Helper\\Str\\Friendly produces URL-friendly titles. Its 4th argument $replace (extra characters to strip, in addition to the built-in accent matrix) must be a string or an array of strings; checkReplace() throws Phalcon\\Support\\Helper\\Str\\Exceptions\\InvalidReplaceFormat ('Parameter replace must be an array or a string') for any other type. Note that falsy values (null, '') are skipped safely — truthy non-strings (int, float, true, objects) are what throw.","triggerScenarios":"(new Friendly())('My Title', '-', true, 123); passing true or a float as $replace; a config-driven replace value that comes back typed as int (e.g. 45 instead of '45' or ['-']).","commonSituations":"Copy-pasting call sites where the 4th argument was numeric in a different helper; config values with wrong types feeding slug generation; passing an ASCII code instead of the character itself.","solutions":["Pass a string ('.') or an array of strings (['-', '_', '.']) as $replace","Omit the argument entirely when no extra replacements are needed","Normalize at the boundary: $replace = is_string($r) || is_array($r) ? $r : [];"],"exampleFix":"// before\n$slug = (new Friendly())($title, '-', true, 45); // int -> throws\n\n// after\n$slug = (new Friendly())($title, '-', true, ['-', '.']);","handlingStrategy":"validation","validationCode":"if (!is_string($replace) && !is_array($replace)) {\n    $replace = []; // null is also safe to pass; truthy scalars are not\n}\n\n$slug = (new \\Phalcon\\Support\\Helper\\Str\\Friendly())($title, '-', true, $replace);","typeGuard":"function isValidFriendlyReplace($replace): bool\n{\n    return null === $replace || is_string($replace) || is_array($replace);\n}","tryCatchPattern":"use Phalcon\\Support\\Helper\\Str\\Exceptions\\InvalidReplaceFormat;\n\ntry {\n    $slug = (new Friendly())($title, '-', true, $replace);\n} catch (InvalidReplaceFormat $e) {\n    $slug = (new Friendly())($title, '-', true); // retry without replace\n}","preventionTips":["Type-check config values that feed the $replace argument before they reach the helper","Remember null/empty are safe but truthy non-strings (int, float, true) throw","Wrap helper calls in thin app-level functions that normalize argument types"],"tags":["phalcon","string","slug","parameter-validation"],"backgroundTag":"invalid-parameter-type","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}