If I create a function of some kind I should add it as a plugin in the plugins
folder right?
I try to redirect a slash with PHP
. htaccess
became to complicated for me. I place this code in a plugin:
$slash_test = substr( $_SERVER['REQUEST_URI'], -1 );
if( $slash_test != '/' ) {
header::redirect( $page->url() . '/', 301);
}
It does not work because the page object has not yet been loaded. Can this code not be added in a plugin?
I know that I could add this code first in my header snippet
but is that the right way to do it?
This question does not only have to do with redirects but all code that should happen before the template has loaded that require the page object.
The variables are not set, but you can define them with their corresponding functions:
$site = site();
$pages = pages();
$page = page();
Think this should work!
Once Kiby is initialized, you ought to be able to use the page()
, and site()
functions to retrieve the equivalent of the equivalent of the $page
and $site
variables in your template. These functions are defined in the global scope, and are therefore available in all other contexts.
It does not work. Here is my new plugin code:
redirect_slash();
function redirect_slash() {
$page = page();
$slash_test = substr( $_SERVER['REQUEST_URI'], -1 );
if( $slash_test != '/' ) {
header::redirect( $page->url() . '/', 301);
}
}
What it does is it takes the root page, not the current one.
Luke
May 19, 2015, 12:03pm
5
No promises, but in the past I feel that Iāve used it like thisā¦
$site = site();
$pages = $site->pages();
This didnāt work:
$pages = pages();
This worked for pages:
$site = site();
$pages = $site->pages();
However, in my case above I need the current $page, not all pages.
I print out the page url
$site = site();
$page = $site->page();
echo $page->url();
When I do this inside a plugin I still got the root page, not the current one.
I guess thatās simply because the plugins are loaded before the router is initialized.
Yes. It would be good to have access to the current $page
on plugin init.
I tried to find a solution to it. The best way might be to try to use the build in function that create the current $page
and use that function in the plugin.
Here is my very hackish solution to it
It works in some cases.
$uri = rtrim( substr( str_replace( url::base(), '', url::current() ), 1 ), '/' );
echo $pages->findByURI($uri)->slug();
It might not work on tag type of pages, or with get variables and if Kirby is in a folder I need to add it after url::base()
.
Hereās mine (also very hackish and not reliable in all cases):
$site = site();
$site->visit(kirby()->path());
$page = $site->page();
Now I have tested your function.
Wrong in the docs, or incomplete?
In the docs it says nothing about kirby()->path()
. Iāve found this: $request->path() | Kirby CMS
kirby()->path();
kirby()->request()->path();
These functions seems to work exactly the same?
Where your solution work
Works with standard pages.
Works with pages with get variables (ignores them). Get variables can still be get by get()
. It works like expected.
Routes donāt work
Routed urls fail. Is there any way to call the router to get the original url, the url that $site->visit()
wants?
I tried to use this:
http://getkirby.com/docs/toolkit/api/router/run
router::run($path);
I get this error:
Strict standards: Non-static method Router::run() should not be called statically, assuming $this from incompatible context
I donāt know if itās even the right function but at least I tried.
Update
I just created a new thread for the subject:
Iāve stumbled across this question in other threads. Now I feel itās time to solve this if possible.
My content uri:s (real paths)
computer/item/company/microsoft
about/contact
My routed uri:s (fake path)
company/microsoft
contact
Question
I want to āconvertā my routed uri to my original uri or $page object, something like this.
$uri_or_page_obj1 = route->run('company/microsoft');
$uri_or_page_obj2 = route->run('contact');
echo $uri_or_page_obj1; // computer/item/company/microsoft or objectā¦
Not tested
I have not tried tags/categories or pagination in the url because I donāt have them in my project.
Are there any other cases that we should test that Iāve missed?
Yeah, but not fully. They both use the same string as the base value, but kirby()->request()->path()
returns a collection (you can iterate over the parts of the path string), while kirby()->path()
returns the string.
You can use both as strings though, so it therefore doesnāt matter.
Please donāt even try to hack together the whole Kirby routing implementation to duplicate it in your plugin. It wonāt be robust enough to be reliable.
They probably wonāt work either.
Multi-language support is one example.
Conclusion : What I posted is a hackish solution. The true and only real solution would be to change the order of code invocation in the core so that plugins are loaded after the router has determined what page to use. That would probably break custom routes in plugins though, so it isnāt easy to implement at all. If you really care about this issue, please open it on GitHub. Discussing hackish solutions and their pitfalls isnāt worth it.
Luke
September 7, 2015, 11:42am
15
What if plugins had a flag for delay property/option you could set. If flagged, mark plugin for load post routerā¦ else load plugin now?
I would say itās a little bit more complicated than that. When do we want to run plugins?
Direcly (after some Kirby functions are loaded, like it is now)
Just before template loads (will have $page set)
Just after template loads (a plugin might want to catch the output)
Before some custom plugin ( now we can use kirby()->plugin() )
After some custom plugin ( now we can use kirby()->plugin() )
Itās a mix of placements in time and order, if many plugins want to run at the same time placement.