FireWire Posted November 30, 2021 Share Posted November 30, 2021 (edited) Hey all, I've been building a new feature on our PW site and the URL hooks are exactly what the doctor ordered. I am developing a RESTful web API to allow external platforms to integrate with our site. The API endpoints are namespaced at /api/v1. I am having trouble making use of the named route parameter using regex. I have a hook for /api/v1/offline-events that gets all Offline Event pages. The next route to be defined is /api/v1/offline-events/{event ID}. The event ID is using a custom string (not the Page ID) that is a 15 character alphanumeric string like this: E4LxQRXZadgjstw. However when I use a PCRE compliant regular expression (tested on regexr.com) I get an error. Here is my hook code for reference and the error produced: <?php namespace ProcessWire; $wire->addHook('/api/v1/offline-events/{eventId:#(?=.{15}$)([A-Za-z0-9])\w+#}/?', function($e) { // ommitted for brevity }); // Error thrown: Warning: preg_match(): Unknown modifier '(' in /wire/core/WireHooks.php on line 1170 I've tried using all delimiters in the documentation (!@#%) but no change in the outcome. The second question is how do I create a wildcard capture for all 404s that occur after the /api endpoint? Currently it is loading the website 404 page. Many thanks! Edited December 9, 2021 by FireWire Updated title to note as solved. Link to comment Share on other sites More sharing options...
monollonom Posted November 30, 2021 Share Posted November 30, 2021 Your regex looks strangely complicated for what you're trying to achieve. I got it working using: <?php namespace ProcessWire; $wire->addHook('/api/v1/offline-events/(eventId:[[:alnum:]]{15})', function($e) { $e->return = "Hello $e->eventId"; }); As for the 404s, if you're not returning anything it will result in a pageNotFound() call you could hook after to check the url and execute code accordingly: $wire->addHookAfter('ProcessPageView::pageNotFound', function($e) { $url = $e->arguments(1); if(strpos($url, "/api") === 0) { $e->return = "API 404"; } }); 1 1 Link to comment Share on other sites More sharing options...
FireWire Posted November 30, 2021 Author Share Posted November 30, 2021 @monollonom HECK YEAH! If there's anything that demonstrates my complete lack of regex abilities... it's this post. Excellent 404 fix. First time using the URL hooks and didn't know if there was a "URL Hook way" of handling. 1 Link to comment Share on other sites More sharing options...
FireWire Posted November 30, 2021 Author Share Posted November 30, 2021 Some follow-up thoughts. Even though @monollonom had a more elegant Regex string that works, I still wanted to find out if I could make my ugly string work since technically it should have and there might be a case where an alternate isn't possible. I found some curiosities that may help some other people if they run into a similar problem. Original string: '/api/v1/offline-events/{eventId:#(?=.{15}$)([A-Za-z0-9])\w+#}/?' First off, I had to remove the # regex delimiters at the start/end. Then I had to replace the {eventId:regex} curly braces and apply parenthesis (eventId:regex) then it worked with the ugly regex. New String: '/api/v1/offline-events/(eventId:[[:alnum:]]{15})/?' This was a little confusing because in the URL hooks documentation I just noticed that /route/(variable) and /route/{variable} are used interchangeably. The second issue is that the documentation states the following: Quote Should you want to go full in to a regular expression, feel free to, by using one of the following characters !@#% as the starting and ending delimiters, and any regular expression in-between Expand Using any of the !@#% characters at the beginning/end of the regex expression caused it to fail whether using {} or () to surround the route argument. So long story boring, I'm not sure if the documentation could be clarified or if there's a bug somewhere (or if I'm just reading it all wrong). Documentation I am referring to here for reference. Something @ryan should review? Link to comment Share on other sites More sharing options...
monollonom Posted November 30, 2021 Share Posted November 30, 2021 On 11/30/2021 at 6:25 PM, FireWire said: This was a little confusing because in the URL hooks documentation I just noticed that /route/(variable) and /route/{variable} are used interchangeably. Expand It's not exactly the case. {variable} will return anything matching the route and will populate the value $e->variable accordingly, whereas (variable:value) will make sure `variable` is equal to `value` (which can be a regex) before making it accessible as $e->variable. There's an example where there is /route/(variable1|variable2|variable3) but in this case it will be accessible through $e->arguments(1) and will have to match either of the three values. On 11/30/2021 at 6:25 PM, FireWire said: Using any of the !@#% characters at the beginning/end of the regex expression caused it to fail whether using {} or () to surround the route argument. Expand At first this confused me as well but re-reading I think we misunderstood what Ryan meant: he's not talking about the regex part of (variable:regex) but rather making the whole hook a regex, as in: $wire->addHook("#/(event|person)/([[:alnum:]]{15})#", function($e) { $type = $e->arguments(1); $id = $e->arguments(2); return "Looking up data for ID $id of type $type"; }); That's why he mentioned that "...PW converts your match path to a regular expression (if it isn't one already)..." 2 Link to comment Share on other sites More sharing options...
monollonom Posted November 30, 2021 Share Posted November 30, 2021 On 11/30/2021 at 4:48 PM, FireWire said: If there's anything that demonstrates my complete lack of regex abilities... it's this post. Expand (re: this, I'm no master and just religiously use https://regex101.com/ or stackoverflow in desperate cases) 1 Link to comment Share on other sites More sharing options...
FireWire Posted November 30, 2021 Author Share Posted November 30, 2021 @monollonom Good observations on that. I think the regex section could use an example like the others on that page. I just wasn't able to visualize that. Many many thanks for your assistance an insight on this! 1 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now