From e588a10ade354a7a4680e5167bfa76c6f33f6871 Mon Sep 17 00:00:00 2001 From: Mikhail Alferov Date: Mon, 31 Aug 2026 13:13:11 +0200 Subject: [PATCH 1/2] Yaf_Route_Regex::__construct: fix the page and modernise the examples - describe what the constructor does, the description was an empty para - declare map, verify and reverse as nullable with a null default, which is what zend_parse_parameters_throw(..., "Sa|a!a!S!", ...) says - attribute the false return to Yaf_Route_Regex::route() rather than to the class, and fix "if doesn't matched" - spell out module, controller and action instead of "m/c/a", which the manual never expands, and say that a route entry starting with ":" is resolved against the parameters map produces - describe what map really does: it selects which numeric captures become request parameters, an unlisted one is discarded, and named capture groups are added under their own name without being listed - document verify, which was an empty para: it is stored on the route and never consulted while routing - fill the empty returnvalues para with the wording the sibling constructor pages use - fix the capture group in the three product examples: the + sat outside the group, so "#^/product/([^/]+)/([^/])+#" captured a single character and the documented $request->getParam("id") returned "4" for an id of "1234" - give the four examples distinct titles and align their comments with the ones in yaf_route_regex/route.xml - add Yaf_Route_Regex::route and ::assemble to the see also list Rebased onto the Yaf documentation revision in #5809, which converted the note on the reverse parameter to a simpara; that conversion is kept. Sources - routes/yaf_route_regex.c: the zpp string in the constructor; the map handling in yaf_route_regex_match(), where a numeric capture with no map entry is dropped and a named group is kept unconditionally; the ":" branch of yaf_route_regex_route(); the absence of any read of regex->verify - verified with php 8.5.4: preg_match("#^/product/([^/]+)/([^/])+#", "/product/php-book/1234", $m) gives $m[2] === "4" --- reference/yaf/yaf_route_regex/construct.xml | 204 +++++++++++--------- 1 file changed, 111 insertions(+), 93 deletions(-) diff --git a/reference/yaf/yaf_route_regex/construct.xml b/reference/yaf/yaf_route_regex/construct.xml index 4388693cb399..64a7c68d0df4 100644 --- a/reference/yaf/yaf_route_regex/construct.xml +++ b/reference/yaf/yaf_route_regex/construct.xml @@ -13,12 +13,14 @@ public Yaf_Route_Regex::__construct stringmatch arrayroute - arraymap - arrayverify - stringreverse + arraynullmap&null; + arraynullverify&null; + stringnullreverse&null; - - + + Constructs a Yaf_Route_Regex route, which routes a + request URI matching a regular expression to a module, controller and action. + @@ -28,52 +30,60 @@ match - - A complete Regex pattern, will be used to match a request uri, if - doesn't matched, Yaf_Route_Regex will return - &false;. - + + A complete regular expression pattern, used to match the request URI. + When it does not match, Yaf_Route_Regex::route + returns &false; and the router moves on to the next route. + route - - When the match pattern matches the request uri, - Yaf_Route_Regex will use this to decide which - m/c/a to routed. - - - either of m/c/a in this array is optional, if you don't assign a - specific value, it will be routed to default. - + + When the pattern matches the request URI, this &array; determines the + module, controller and action to route to. + + + Each of the three entries is optional; when one is not given, the + default is used. An entry whose value starts with : + is resolved against the parameters produced by + map. + map - - An array to assign name to the captures in the match result. - + + An &array; mapping capture group indexes to parameter names. Only the + captures listed here become request parameters; a numeric capture that + is not listed is discarded. + + + Named capture groups are always added under their own name and do not + need to be listed. + verify - - - + + Accepted and stored on the route, but not used: the current + implementation never consults it while routing. + reverse - a string, used to assemble url, see + A &string;, used to assemble URL, see Yaf_Route_Regex::assemble. - this parameter is introduced in 2.3.0 + This parameter is introduced in 2.3.0 @@ -84,108 +94,114 @@ &reftitle.returnvalues; - - - + No value is returned. &reftitle.examples; - <classname>Yaf_Route_Regex</classname> example + <classname>Yaf_Route_Regex</classname> via <methodname>Yaf_Router::addRoute</methodname> getRouter()->addRoute("name", - new Yaf_Route_Regex( - "#^/product/([^/]+)/([^/])+#", //match request uri leading "/product" - array( - 'controller' => "product", //route to product controller, - ), - array( - 1 => "name", // now you can call $request->getParam("name") - 2 => "id", // to get the first captrue in the match pattern. - ) + +/** + * Add a regex route to the Yaf_Router route stack + */ +Yaf_Dispatcher::getInstance()->getRouter()->addRoute( + "name", + new Yaf_Route_Regex( + "#^/product/([^/]+)/([^/]+)#", // match a URI leading "/product" + array( + 'controller' => "product", // route to the product controller + ), + array( + 1 => "name", // $request->getParam("name") holds the first capture + 2 => "id", // and $request->getParam("id") the second ) - ); + ) +); ?> ]]> - <classname>Yaf_Route_Regex</classname> (as of 2.3.0) example + <classname>Yaf_Route_Regex</classname> using a capture as the controller name getRouter()->addRoute("name", - new Yaf_Route_Regex( - "#^/product/([^/]+)/([^/])+#i", //match request uri leading "/product" - array( - 'controller' => ":name", // route to :name, which is $1 in the match result as controller name - ), - array( - 1 => "name", // now you can call $request->getParam("name") - 2 => "id", // to get the first captrue in the match pattern. - ) + +/** + * Use a capture as the controller name + */ +Yaf_Dispatcher::getInstance()->getRouter()->addRoute( + "name", + new Yaf_Route_Regex( + "#^/product/([^/]+)/([^/]+)#i", // match a URI leading "/product" + array( + 'controller' => ":name", // the "name" capture (see map) becomes the controller + ), + array( + 1 => "name", // $request->getParam("name") holds the first capture + 2 => "id", // and $request->getParam("id") the second ) - ); + ) +); ?> ]]> - <classname>Yaf_Route_Regex</classname> and named capture group (as of 2.3.0) example + <classname>Yaf_Route_Regex</classname> using a named capture group getRouter()->addRoute("name", - new Yaf_Route_Regex( - "#^/product/(?[^/]+)/([^/])+#i", //match request uri leading "/product" - array( - 'controller' => ":name", // route to :name, - // which is named capture group 'name' in the match result as controller name - ), - array( - 2 => "id", // to get the first captrue in the match pattern. - ) + +/** + * Use a named capture group as the controller name + */ +Yaf_Dispatcher::getInstance()->getRouter()->addRoute( + "name", + new Yaf_Route_Regex( + "#^/product/(?[^/]+)/([^/]+)#i", // match a URI leading "/product" + array( + 'controller' => ":name", // the "name" capture becomes the controller + ), + array( + 2 => "id", // group 1 is named, only group 2 needs a map entry ) - ); + ) +); ?> ]]> - <classname>Yaf_Route_Regex</classname> example + <classname>Yaf_Route_Regex</classname> via <methodname>Yaf_Router::addConfig</methodname> array( - "type" => "regex", //Yaf_Route_Regex route - "match" => "#(.*)#", //match arbitrary request uri - "route" => array( - 'controller' => "product", //route to product controller, - 'action' => "dummy", //route to dummy action - ), - "map" => array( - 1 => "uri", // now you can call $request->getParam("uri") - ), + +/** + * Add a regex route to the Yaf_Router route stack through a config array + */ +$config = array( + "name" => array( + "type" => "regex", // a Yaf_Route_Regex route + "match" => "#(.*)#", // match any request URI + "route" => array( + 'controller' => "product", // route to the product controller + 'action' => "dummy", // and to the dummy action ), - ); - Yaf_Dispatcher::getInstance()->getRouter()->addConfig( - new Yaf_Config_Simple($config)); + "map" => array( + 1 => "uri", // $request->getParam("uri") holds the matched URI + ), + ), +); + +Yaf_Dispatcher::getInstance()->getRouter()->addConfig( + new Yaf_Config_Simple($config) +); ?> ]]> @@ -195,6 +211,8 @@ &reftitle.seealso; + Yaf_Route_Regex::route + Yaf_Route_Regex::assemble Yaf_Router::addRoute Yaf_Router::addConfig Yaf_Route_Static From ef710aedaaf925da7768d8c601187769174c0966 Mon Sep 17 00:00:00 2001 From: Louis-Arnaud Date: Mon, 31 Aug 2026 13:13:11 +0200 Subject: [PATCH 2/2] Yaf_Loader: fix the synopses of registerNamespace and its alias The Yaf documentation revision in #5809 rewrote both loader pages and already carries most of what this pull request proposed there. Four things it did not get right are fixed here. registerNamespace documented its first parameter as name_prefix. That name comes from yaf_loader.stub.php, and nothing in the extension includes the arginfo generated from it; the registered arginfo is the hand-written yaf_loader_regnamespace_arginfo, which names the parameter namespace, as the alias target page already documented. A named argument using name_prefix fails. The return union carried null, which no longer has a reachable path: the only bare return is after a zend_parse_parameters failure, and since PHP 8.0 that throws instead of returning. Both pages already said in their return values section that the method returns the instance or false. string|array is not how the manual writes a union type. It occurred twice in the whole of reference/, both introduced by that commit, against more than three thousand occurrences of . Likewise null against &null;. The prefix matching rule is worth stating, since the obvious reading of "prefix" is wrong: yaf_loader_register_namespace() strips a leading backslash and then splits the name on backslash and underscore, so a registered prefix only matches at one of those boundaries. Note the claim is deliberately limited to the lookup side: a class name is sanitised with backslashes rewritten to underscores before resolution, but the registration path scans for a backslash across the whole string before falling back to an underscore, so the two delimiters are not interchangeable in a registered prefix. Sources - yaf_loader.c, yaf_loader_regnamespace_arginfo and the PHP_MALIAS that registers registerNamespace against it - yaf_loader.c, yaf_loader_register_namespace(), the *name == '\\' skip and the memchr on '\\' then '_' - yaf_loader.c, yaf_loader_sanitize_name() and yaf_loader_resolve_namespace(), which split on '_' alone --- reference/yaf/yaf_loader/registerlocalnamespace.xml | 7 ++++--- reference/yaf/yaf_loader/registernamespace.xml | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/reference/yaf/yaf_loader/registerlocalnamespace.xml b/reference/yaf/yaf_loader/registerlocalnamespace.xml index 3b3b648b3be0..1b855fdffe1d 100644 --- a/reference/yaf/yaf_loader/registerlocalnamespace.xml +++ b/reference/yaf/yaf_loader/registerlocalnamespace.xml @@ -10,9 +10,9 @@ &reftitle.description; - public Yaf_LoaderfalsenullYaf_Loader::registerLocalNamespace - string|arraynamespace - stringpathnull + public Yaf_LoaderfalseYaf_Loader::registerLocalNamespace + stringarraynamespace + stringpath&null; Register a local namespace. Classes whose prefix belongs to a local namespace are looked up under the given path (or the local library directory when no path is given) instead of the global one. This lets you place your own classes into the local library directory, while shared classes live in the global library directory (see the yaf.library ini setting). @@ -25,6 +25,7 @@ namespace A namespace prefix string, or an array of prefix/path pairs (when the value is a path string) or prefix strings. +A prefix only matches at an underscore or backslash boundary: registering Models makes Models_User and Models itself local, but not ModelsUser. A leading backslash is ignored, and a class name written with backslashes is looked up as if they were underscores. diff --git a/reference/yaf/yaf_loader/registernamespace.xml b/reference/yaf/yaf_loader/registernamespace.xml index 78a34b3017cd..310691e0787a 100644 --- a/reference/yaf/yaf_loader/registernamespace.xml +++ b/reference/yaf/yaf_loader/registernamespace.xml @@ -10,9 +10,9 @@ &reftitle.description; - public Yaf_LoaderfalsenullYaf_Loader::registerNamespace - string|arrayname_prefix - stringpathnull + public Yaf_LoaderfalseYaf_Loader::registerNamespace + stringarraynamespace + stringpath&null; Alias of Yaf_Loader::registerLocalNamespace. @@ -21,7 +21,7 @@ &reftitle.parameters; - name_prefix + namespace A namespace prefix string, or an array of prefix/path pairs (when the value is a path string) or prefix strings.