Hide the sub directory url in 5.7?
Permalink 1 user found helpful
I have installed concrete5 5.7 in a subdirectory "www.example.com/c5" and I would like to hide this subdirectory from the URL. To do this, i followed this how-to (link below) which describes the process for earlyer versions, but step 3 and 4 don't appear to apply for 5.7. Any suggestions how I can achieve this?
Here's the how to:
https://www.concrete5.org/documentation/how-tos/developers/hide-the-...
best
Wolfgang
Here's the how to:
https://www.concrete5.org/documentation/how-tos/developers/hide-the-...
best
Wolfgang
Solution that works in concrete5 5.7+ (also works in version 8.1.0+) by fixing the SCRIPT_NAME env variable.
Works with PHP 7.
We want to transparently redirect requests from root dir to the sub directory c5/
We can make this redirection in the .htaccess.
But then, unfortunately, concrete5 5.7 uses the environment variable SCRIPT_NAME to detect the canonical URL. So we need to fix that SCRIPT_NAME so that it looks like the DocumentRoot is in our sub directory.
I didn't find a way to fix it directly from the .htaccess, so we will need to do it in PHP at the beginning of the execution.
We will do this by comparing the SCRIPT_NAME which is a file path relative to the DocumentRoot, to the REQUEST_URI which is the public url relative to the site domain and which doesn't contain the hidden directories. This way, we can remove any hidden directory from the SCRIPT_NAME. It also works with multiple hidden dirs or if you change the dirname or the dir structure.
So here is what you need to do:
(Don't follow the instructions from the OP link to the old "Hide the subdirectory URL" how-to ! Just start here.)
First, in your .htaccess (the one in the directory containing your "c5" directory), you should have a redirection that looks like that:
Then at the beginning of your index.php (the root index.php: "c5/index.php"; the concrete5 entry point), add the following code:
This is it. Also because we didn't hack or modify the core concrete5 code, it should be fairly future-proof :)
Note: each time you upgrade your concrete5 site, it may overwrite the PHP code you added to the index.php script. So just don't forget to add it back.
Edit: tested in concrete5 8.1.0 and 8.2.1, works great !
Works with PHP 7.
We want to transparently redirect requests from root dir to the sub directory c5/
We can make this redirection in the .htaccess.
But then, unfortunately, concrete5 5.7 uses the environment variable SCRIPT_NAME to detect the canonical URL. So we need to fix that SCRIPT_NAME so that it looks like the DocumentRoot is in our sub directory.
I didn't find a way to fix it directly from the .htaccess, so we will need to do it in PHP at the beginning of the execution.
We will do this by comparing the SCRIPT_NAME which is a file path relative to the DocumentRoot, to the REQUEST_URI which is the public url relative to the site domain and which doesn't contain the hidden directories. This way, we can remove any hidden directory from the SCRIPT_NAME. It also works with multiple hidden dirs or if you change the dirname or the dir structure.
So here is what you need to do:
(Don't follow the instructions from the OP link to the old "Hide the subdirectory URL" how-to ! Just start here.)
First, in your .htaccess (the one in the directory containing your "c5" directory), you should have a redirection that looks like that:
<IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteCond %{REQUEST_URI} !^/c5 RewriteRule ^.*$ c5/$0 [L] </IfModule>
Then at the beginning of your index.php (the root index.php: "c5/index.php"; the concrete5 entry point), add the following code:
function ___FIX_HIDDEN_SUBDIR_IN_PATH(string $realpath, string $visiblepath, string $regscript = '#[^/]+.php#'): string { // Find the part of the realpath that is before the script filename: if(preg_match($regscript, $realpath, $matches, PREG_OFFSET_CAPTURE) !== 1) { throw new Exception('Script filename not found in realpath: "'.$realpath); } // Inspect dirs that are before the script filename: $realdirs = explode('/', substr($realpath, 0, $matches[0][1])); $visibledirs = explode('/', $visiblepath); // Only keep dirs that are not hidden: $dirs = []; for($r = 0, $v = 0, $len = count($realdirs); $r < $len; $r++) { if($realdirs[$r] === $visibledirs[$v]) { $dirs[] = $realdirs[$r]; $v++; }
Viewing 15 lines of 21 lines. View entire code block.
This is it. Also because we didn't hack or modify the core concrete5 code, it should be fairly future-proof :)
Note: each time you upgrade your concrete5 site, it may overwrite the PHP code you added to the index.php script. So just don't forget to add it back.
Edit: tested in concrete5 8.1.0 and 8.2.1, works great !
This is exactly what I was looking for after moving the website to some big webhosting company. They force developers to use specific directory structure for aliases and subdomains and propagate their own .htaccess for the root directory, which is NOT RECOMMENDED TO CHANGE. Concrete5 then generates functioning but full length URLs and doesn't hide webhost's recommended directory structure in URL.
My hosting also had bad .htaccess in root (this one, which IS NOT RECOMMENDED TO CHANGE). For Concrete5 (also Joomla and others) I had to add these lines after the "RewriteEngine On":
otherwise some tools didn't function:http://www.domain.tld/index.php/tools/required/dashboard/XY... (generating sitemap etc.).
Be aware to add QSA, not R in RewriteRule, since otherwise AJAX POSTs will not rewrite correctly and dashboard trees will not be rendered.
I also wanted pretty URLs in the Dashboard, so I added these lines of code in application\config\concrete.php:
My hosting also had bad .htaccess in root (this one, which IS NOT RECOMMENDED TO CHANGE). For Concrete5 (also Joomla and others) I had to add these lines after the "RewriteEngine On":
RewriteCond %{REQUEST_URI} ^/index\.php/ RewriteRule ^index.php/(.*) /$1 [QSA,L]
otherwise some tools didn't function:http://www.domain.tld/index.php/tools/required/dashboard/XY... (generating sitemap etc.).
Be aware to add QSA, not R in RewriteRule, since otherwise AJAX POSTs will not rewrite correctly and dashboard trees will not be rendered.
I also wanted pretty URLs in the Dashboard, so I added these lines of code in application\config\concrete.php:
<?php return [ 'seo' => [ 'url_rewriting_all' => true, ], ];
I followed your steps but everytime I add the script to index.php I get this error:
This is the index.php file:
Fatal error: Default value for parameters with a class type hint can only be NULL in /home/garagedeuren-nl.nl/public_html/index.php on line 2
This is the index.php file:
<?php function ___FIX_HIDDEN_SUBDIR_IN_PATH(string $realpath, string $visiblepath, string $regscript = '#[^/]+.php#'): string { // Find the part of the realpath that is before the script filename: if(preg_match($regscript, $realpath, $matches, PREG_OFFSET_CAPTURE) !== 1) { throw new Exception('Script filename not found in realpath: "'.$realpath); } // Inspect dirs that are before the script filename: $realdirs = explode('/', substr($realpath, 0, $matches[0][1])); $visibledirs = explode('/', $visiblepath); // Only keep dirs that are not hidden: $dirs = []; for($r = 0, $v = 0, $len = count($realdirs); $r < $len; $r++) { if($realdirs[$r] === $visibledirs[$v]) { $dirs[] = $realdirs[$r]; $v++;
Viewing 15 lines of 23 lines. View entire code block.
The code has only been tested in PHP 7, you are probably using PHP 5, so you need to translate it to PHP 5.
The problem is that type hinting for scalar (primitive) types like string was only added in PHP 7. See: http://php.net/manual/en/functions.arguments.php#functions.argument...
Try to change the function definition to something like this (untested):
The problem is that type hinting for scalar (primitive) types like string was only added in PHP 7. See: http://php.net/manual/en/functions.arguments.php#functions.argument...
Try to change the function definition to something like this (untested):
function ___FIX_HIDDEN_SUBDIR_IN_PATH(string $realpath, string $visiblepath, string $regscript = null): string { if($regscript === null) $regscript = '#[^/]+.php#';
It doesn't error anymore. But now the website loads completely empty. My php knowledge is very very low so I have no clue what happened.
Here's my new code
Here's my new code
function ___FIX_HIDDEN_SUBDIR_IN_PATH(string $realpath, string $visiblepath, string $regscript = null): string { if($regscript === null) $regscript = '#[^/]+.php#'; // Find the part of the realpath that is before the script filename: if(preg_match($regscript, $realpath, $matches, PREG_OFFSET_CAPTURE) !== 1) { throw new Exception('Script filename not found in realpath: "'.$realpath); } // Inspect dirs that are before the script filename: $realdirs = explode('/', substr($realpath, 0, $matches[0][1])); $visibledirs = explode('/', $visiblepath); // Only keep dirs that are not hidden: $dirs = []; for($r = 0, $v = 0, $len = count($realdirs); $r < $len; $r++) { if($realdirs[$r] === $visibledirs[$v]) { $dirs[] = $realdirs[$r]; $v++;
Viewing 15 lines of 22 lines. View entire code block.
Still haven't solved it, could you elaborate or maybe point me in the direction of what I should learn about PHP to solve it myself.
Thanks in advance!
Thanks in advance!
Well I can't help you with PHP 5.x, as I left it a long time ago...
I would recommend you to look at this migration guide from PHP 5.6 to 7.0, you may find what has to be changed for this script to work with PHP 5:http://php.net/manual/en/migration70.php...
I would recommend you to look at this migration guide from PHP 5.6 to 7.0, you may find what has to be changed for this script to work with PHP 5:http://php.net/manual/en/migration70.php...
It's probably too late, but this rewrite seems to work for me:
function ___FIX_HIDDEN_SUBDIR_IN_PATH( $realpath, $visiblepath, $regscript = '#[^/]+.php#') {
Hi,
(I am running PHP 7 and C5 version 8.2)
I have followed (I think) the instructions above in the first post as well as the updated instructions in this post. I now have created two .htaccess files (one in / and one in /subdirectory) and have placed the suggested content, as well as edited the index.php file.
The index.php file works for me. No subdirectory is visible (Excellent!). However, If I click on any link on my index page that (seemingly) has the subdirectory removed I receive an "Too Man Redirects" Error in Chrome and a "page isn’t redirecting properly" in Firefox.
Is there something I may have overlooked in this process (obviously there is because it isn't working :) )?
thanks
(I am running PHP 7 and C5 version 8.2)
I have followed (I think) the instructions above in the first post as well as the updated instructions in this post. I now have created two .htaccess files (one in / and one in /subdirectory) and have placed the suggested content, as well as edited the index.php file.
The index.php file works for me. No subdirectory is visible (Excellent!). However, If I click on any link on my index page that (seemingly) has the subdirectory removed I receive an "Too Man Redirects" Error in Chrome and a "page isn’t redirecting properly" in Firefox.
Is there something I may have overlooked in this process (obviously there is because it isn't working :) )?
thanks
Hello bayleafmedia, concerning your PHP 7 and C5 8.2 question,
You should only create one .htaccess, the one in the root "/" directory. And you shouldn't need to add or change any other .htaccess in any subdirectory. Then, if I understood you correctly ie. you installed your concrete5 inside "/subdirectory/", that means that you should add the php code to your "/subdirectory/index.php" file.
So if you have that wrong, probably you didn't follow exactly the instructions in my post above:https://www.concrete5.org/community/forums/installation/hide-the-sub... (only follow the instructions from that post, not from the first post, nor from the post above yours (which only concerns PHP5 users)). I also updated that post since you asked your question and made it a bit easier to understand.
Then, if your browser reports "Too many redirects" or "Page isn't redirecting properly", that means that the server sends redirect headers that redirects to an address that sends redirect headers etc, indefinitely. With your browser's developers tools, you should be able to read the headers and to see if the redirect headers are wrong. Also in the PHP code, try to echo the results of the "___FIX_HIDDEN_SUBDIR_IN_PATH(…)" to see if they are correct: it should only strip the path of the hidden dirs.
Hope it helps.
You should only create one .htaccess, the one in the root "/" directory. And you shouldn't need to add or change any other .htaccess in any subdirectory. Then, if I understood you correctly ie. you installed your concrete5 inside "/subdirectory/", that means that you should add the php code to your "/subdirectory/index.php" file.
So if you have that wrong, probably you didn't follow exactly the instructions in my post above:https://www.concrete5.org/community/forums/installation/hide-the-sub... (only follow the instructions from that post, not from the first post, nor from the post above yours (which only concerns PHP5 users)). I also updated that post since you asked your question and made it a bit easier to understand.
Then, if your browser reports "Too many redirects" or "Page isn't redirecting properly", that means that the server sends redirect headers that redirects to an address that sends redirect headers etc, indefinitely. With your browser's developers tools, you should be able to read the headers and to see if the redirect headers are wrong. Also in the PHP code, try to echo the results of the "___FIX_HIDDEN_SUBDIR_IN_PATH(…)" to see if they are correct: it should only strip the path of the hidden dirs.
Hope it helps.
- yes, I changed both .htaccess files as described in the how-to (and it works for the base domain)
- yes, I turned off the cache
- yes, I searched Documentation, Forums, and even the Github repo for cues but haven't found anything in particular (except, that they changed their URL system)
I also had a look into some php file to identify potential candidates for configuration:
- $app['app_relative_path'] is used in the /concrete/bootstrap/paths.php file
- DIR_BASE_CORE is used in the /concrete/bootstrap/autoload.php file
- DIR_BASE is used in the /concrete/bootstrap/configure.php ... this might be the right one. but how and where do I set it properly?