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

View Replies:
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 the dirname or dir structure is changed.

First, remember from the link you gave: in your .htaccess, you probably 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, 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: upgrading your concrete5 site 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, 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#') {