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

 
silentdrummer replied on at Permalink Reply
to anticipate some questions:
- 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?
jlgrall replied on at Permalink Reply
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:
<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++;
        }


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 !
darbie replied on at Permalink Reply
darbie
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":

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,
    ],   
];
pixelsnbeards replied on at Permalink Reply
I followed your steps but everytime I add the script to index.php I get this error:

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++;
jlgrall replied on at Permalink Reply
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):
function ___FIX_HIDDEN_SUBDIR_IN_PATH(string $realpath, string $visiblepath, string $regscript = null): string {
    if($regscript === null) $regscript = '#[^/]+.php#';
pixelsnbeards replied on at Permalink Reply
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

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++;
pixelsnbeards replied on at Permalink Reply
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!
jlgrall replied on at Permalink Reply
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...
pekka replied on at Permalink Reply
pekka
It's probably too late, but this rewrite seems to work for me:
function ___FIX_HIDDEN_SUBDIR_IN_PATH( $realpath,  $visiblepath,  $regscript = '#[^/]+.php#') {
bayleafmedia replied on at Permalink Reply
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
jlgrall replied on at Permalink Reply
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.