XF 2.2 force lowercase links

and if i use caps for VIEW, it returns all caps because the callback doesn't seem to match because the instanceof myentity doesn't match $data
Yeah, that's what I'm getting at. $r in the template becomes $data in the callback. If you dump $data, what does it give you?
 
it gives me my entity and the xf standard as well in the big nested list, simliar to if i dump the vars in the template with {{ dump(vars()) }}
 
it gives me my entity and the xf standard as well in the big nested list, simliar to if i dump the vars in the template with {{ dump(vars()) }}
...and the rootClass property of the dump matches your instanceof conditional (but with a leading backslash, such as $data instanceof \XF\Entity\Thread)?

1618000833500.png

and so on all exist as per my entity structure. Again, i do not have type/item/act in this object as it's not in the db schema.
If you really can't make this information available via the entity (via getters or otherwise) and you have to use a hard-coded array, you could use:

HTML:
<a href="{{ link('base', {'type': 'HARDCODED TYPE', 'item': {$r.name}}) }}">{$r.name}</a>

I just meant that it won't work with the example I provided because $data would be an array rather than an instance of your entity, and you'd have to adapt your callback accordingly.

PHP:
// ...
if (!empty($data['item'])
{
    $data['item'] = $router->prepareStringForUrl($data['item']);
}
// ...
 
I need to re-read that a few more times as it's not sinking in.

I just can't understand why something that should be so simple (making a link) is the hardest thing i've done on xf to date (and still doesn't work).

There's next to no documentation on how any of this stuff works. How did you ramp up?

I do appreciate your time on this though, thanks!
 
How did you ramp up?
Mostly just reading through the framework code itself. An IDE or text editor with good language support helps with navigating the codebase and piecing things together.

If it helps, the template link() function arguments correspond to the route callback arguments like so:
Code:
link('prefix/action', $data, $params)

The prefix is the route prefix, the action is the desired controller action, $data is an array (or an object implementing \ArrayAccess, like an entity) from which to automatically derive the route format parameters (meaning :str<title> will pull from $data['title'], and so on), and $params is an array of key-value pairs to add to the query string (?key=value&key2=value2).

Code:
link('base', {'type': 'HARDCODED TYPE', 'item': $r.name})

In the above call, your $prefix is 'base', your $action is '' (blank), your $data is ['type' => 'HARDCODED TYPE', 'item' => $r->name], and your $params is [] (blank).

Your callback is just a static method which is called when the route is being built (when the link() function is called). It also receives the $router object as an argument if you want to call (public) methods on the router.

In your callback, you have a few options. You can return a string or a \XF\Mvc\RouteBuiltLink object, but I would personally reserve that for more advanced use-cases. Your other option is to simply manipulate the arguments as needed (they are passed by reference) and return null. The router will proceed with building the link as if the manipulated arguments were passed from the link() function directly. In other words, the callback simply sits between the link() function and the router, modifying the arguments as needed.

The example in my post above normalizes the $data['item'] string, which corresponds to the :str<item> format parameter.

Though, all of this may be moot if you're always building the $data array manually. You could probably just do:
Code:
link('base', {'type': 'HARDCODED TYPE', 'item': $r.name|to_lower})
 
Last edited:
Does the router support nesting?

you said:
link('prefix/action', $data, $params)

I'm actually trying to build:
link('base/category/action', $data, $params)

Is that where i'm going wrong with some of this? Do I need to flatten it? Make more routes for each category instead of making it nest deeper?
 
Last edited:
The middle part will be derived from the route format parameters and $data array. So link('prefix/action' $data, $params) with a route format :str<type> and $data = ['type' => 'example'] will return prefix/example/action.

If you mean you have different sub-sections nested under your base route, you would define the sub-name in your route definition and format, and use that alongside the prefix in your link() calls:

1618259157700.png

PHP:
// returns base/category/ex-type/ex-item/action
link('base/category/action', {'type': 'ex-type', 'item': 'ex-item'}, $params)
 
I added slug columns to my db schema and so I made some progress here and i'm getting good urls with everything except my edit/add links which are action handlers.

How do i pick up the 3rd param in link?

Code:
<a href="{{ link('base/type', {$myobject}, {'act': 'edit'}) }}"

It doesn't come through to the ParameterBag $params

I tried stuffing $action in there but it didn't work....


I changed the route to include
/:str<act> as a suffix
and that works if it's part of $myobject, but not as the 3rd parameter action handler (and makes the url look like base/type/edit instead of base/type/?act=edit which is preferred.
 
If you really want to use query strings here, remove :str<act> from the route format and keep your link(...) as-is. Then in your controller you can fetch the value with $action = $this->filter('act', 'str');
 
Top Bottom