# PhpRenderer and basePath

**URL:** <https://discourse.slimframework.com/t/phprenderer-and-basepath/4893>\
**Category:** Questions\
**Created:** [July 17, 2021, 3:40am UTC](https://discourse.slimframework.com/t/phprenderer-and-basepath/4893 "2021-07-17T03:40:49Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![dafriend](https://avatars.discourse-cdn.com/v4/letter/d/da6949/32.png) [@dafriend](https://discourse.slimframework.com/u/dafriend)\
**Post date:** [July 17, 2021, 3:40am UTC](https://discourse.slimframework.com/t/phprenderer-and-basepath/4893/1 "2021-07-17T03:40:49Z")

</div>

I’ve got `\Slim\Views\PhpRenderer` working as expected and most of Odan’s `PhpViewExtensionMiddleware` (from [here](https://odan.github.io/2020/12/09/slim4-php-view.html)) working too. The problem is that, from within the middleware, `$this->app->getBasePath()` is returning an empty string. In other contexts, `$app->getBasePath();` returns the same.

The file structure is standard, with the web root set to `/var/www/slim4/public/` and all other “application” folders at the same level as public.

The output of Odan’s check.php looks like this:

```auto
System ....................... Linux
Webserver .................... Apache/2.4.38 (Debian)
PHP-Version .................. ✓ 8.0.8
PHP-SAPI ..................... fpm-fcgi
Apache mod_cgi ............... Not found
Current directory: public/ ... ✓ OK
File: public/index.php ....... ✓ Found
File: public/.htaccess ....... ✗ Not found
File: public/../.htaccess .... ✗ Not found
URL: /public ................. ✓ Valid
Done

```

The .htaccess files are missing because they are not implemented. The appropriate directives are in the Apache site config file instead. The site works except that I cannot obtain a base path.

I have tried `BasePathMiddleware` and hard coding a basePath with `$app->setBasePath('/various/absolute/or/relative/paths/');` with and without the BasePathMiddleware, all without success.

Any insight appreciated?

---

<div class="post-metadata">

**Author:** ![odan](https://avatars.discourse-cdn.com/v4/letter/o/9de053/32.png) [@odan](https://discourse.slimframework.com/u/odan)\
**Post date:** [July 17, 2021, 8:18am UTC](https://discourse.slimframework.com/t/phprenderer-and-basepath/4893/2 "2021-07-17T08:18:45Z")

</div>

Hi @dafriend

I would try to change the DocumentRoot first to the `public/` directory, e.g.:

```auto
DocumentRoot /var/www/slim4/public

```

To proxy all `.php` files in your vhost to the fcgi server using their real php file locations, you can try to change a more flexible match:

`ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/var/www/slim4/public/$1`

---

<div class="post-metadata">

**Author:** ![dafriend](https://avatars.discourse-cdn.com/v4/letter/d/da6949/32.png) [@dafriend](https://discourse.slimframework.com/u/dafriend)\
**Post date:** [July 17, 2021, 10:34pm UTC](https://discourse.slimframework.com/t/phprenderer-and-basepath/4893/3 "2021-07-17T22:34:36Z")

</div>

Thanks @odan for the suggestions.

The `DocumentRoot` is (and was) set as you describe - `/var/www/slim4/public/`

This setup is a developer’s workstation and Apache resides on that workstation. No particular proxy has been configured for it.

Adding the suggested `ProxyPassMatch` directive results in Apache returning a 500 Internal Server Error. So I changed the SAPI setup to apache2handler and running `check.php` now gives me the following.

```auto
System ....................... Linux
Webserver .................... Apache/2.4.38 (Debian)
PHP-Version .................. ✓ 8.0.8
PHP-SAPI ..................... apache2handler
Apache mod_rewrite ........... ✓ Enabled
Apache mod_cgi ............... ✓ Enabled
Current directory: public/ ... ✓ OK
File: public/index.php ....... ✓ Found
File: public/.htaccess ....... ✗ Not found
File: public/../.htaccess .... ✗ Not found
URL: /public ................. ✓ Valid
Detect Slim basePath .........
Done

```

Note that a `basePath` is still not found.  
`Check.php` is running from `/var/www/slim4/public/`  
What would the expected value of `basePath` be in this case?

It is interesting to note that if I remove `BasePathMiddleware` and explicitly set a base path with

```
$app->setBasePath('/var/www/slim4/public/');

```

every request turns into a 404. Without the above every page works perfectly. Doesn’t seem to matter what the value provided is either.

Any other thoughts? I appreciate your time and expertise.

---

<div class="post-metadata">

**Author:** ![odan](https://avatars.discourse-cdn.com/v4/letter/o/9de053/32.png) [@odan](https://discourse.slimframework.com/u/odan)\
**Post date:** [July 18, 2021, 9:02am UTC](https://discourse.slimframework.com/t/phprenderer-and-basepath/4893/4 "2021-07-18T09:02:04Z")

</div>

> [@dafriend](#):
>
> This setup is a developer’s workstation and Apache resides on that workstation. No particular proxy has been configured for it.

> apache2handler

Ok, then it should be pretty “standard” to set up. You can find the configuration for Apache in the Slim [documentation](https://www.slimframework.com/docs/v4/start/web-servers.html#apache-configuration)

You should really add the `.htaccess` file(s) as documented in the [BasePathMiddleware](https://github.com/selective-php/basepath#installation).

Note that the Slim basePath is a **[URL path](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Syntax)** and not a filesystem path.

For example, when you set the DocumentRoot to `/var/www/slim4/public/`, then the basePath is `''` (empty string). This is usually the case on a **production** server.

```php
$app->setBasePath('');

```

On a **development** machine, you may want to run multiple websites or applications on the same apache instance. Then just keep the `DocumentRoot` default value, e.g. `/var/www/html` and create  
a sub-directly per project, e.g. `/var/www/html/slim4`. Also add the two `.htaccess` files. The Slim (URL) basePath is then `/slim4` (without the public path).

```php
$app->setBasePath('/slim4');

```

---

<div class="post-metadata">

**Author:** ![dafriend](https://avatars.discourse-cdn.com/v4/letter/d/da6949/32.png) [@dafriend](https://discourse.slimframework.com/u/dafriend)\
**Post date:** [July 18, 2021, 6:53pm UTC](https://discourse.slimframework.com/t/phprenderer-and-basepath/4893/5 "2021-07-18T18:53:21Z")

</div>

> [@odan](#):
>
> Ok, then it should be pretty “standard” to set up. You can find the configuration for Apache in the Slim [documentation](https://www.slimframework.com/docs/v4/start/web-servers.html#apache-configuration)
> 
> You should really add the `.htaccess` file(s) as documented in the [BasePathMiddleware](https://github.com/selective-php/basepath#installation).

I’m sorry but I disagree about using `.htaccess`. Consider what [Apache.org](https://httpd.apache.org/docs/current/howto/htaccess.html) has to say about using them.

> You should avoid using `.htaccess` files completely if you have access to httpd main server config file. Using `.htaccess` files slows down your Apache http server. Any directive that you can include in a `.htaccess` file is better set in a `Directory` block, as it will have the same effect with better performance.

You might find [this article](https://www.danielmorell.com/guides/htaccess-seo/basics/dont-use-htaccess-unless-you-must) a convincing explanation of why they should be avoided. Even if you’re not convinced it is an interesting read.

Because I do have access to the server config files, the appropriate `mod_rewrite` and `<Directory>` directives have been implemented therein.

> [@odan](#):
>
> Note that the Slim basePath is a **[URL path](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Syntax)** and not a filesystem path.

That was my original assumption. However, let’s be absolutely clear about what we mean by URL. Toward that end, consider the following URL generic syntax diagram.

> _URL generic syntax_  
> URL = scheme:[//authority]_ **path** _[?query][#fragment]

According to that syntax do you:

- agree that a “basePath” would make up some portion of the _ **path** _ element?
- agree that “basePath” does not contain any part of the _scheme:[//authority]_ elements?

If you agree with both questions then `basePath` is not a URL. Instead, it is a string representing a portion of a filesystem path leading to a folder below the folder set as `DocumentRoot`.

The purpose of `basePath` is to eliminate the need for bad URLs like this.

> `https://www.example.com/my-app/public`

Right?

Now that all that is out of the way, let’s return to my original issue. (Which I am now convinced has nothing to do with my configuration or settings.)

I was working through the code in your [Slim 4 - PHP Templates](https://odan.github.io/2020/12/09/slim4-php-view.html) blog post. All was going well and made sense until I got to the [Assets](https://odan.github.io/2020/12/09/slim4-php-view.html#assets) section where you present a technique for setting a value in a `<base href="...">` tag. Here is a snippet from the example

```http
<base href="<?= $basePath ?>/"/>

```

As I understand it, the `href` needs to hold a complete URL, i.e. `https://example.com/` And if it doesn’t “need” to be, that is what I’d like to have.

Examining the `<base>` tag the middleware created is where the empty string I mention in the OP first became apparent to me.

The value of `$basePath` is set in a piece of middleware the Blog presents -`PhpViewExtensionMiddleware` - which adds some “attributes” to a `\Slim\Views\PhpRenderer` instance. Here’s the relevant line of code from `PhpViewExtensionMiddleware::process(...)`

```auto
$this->phpRenderer->addAttribute('basePath', $this->app->getBasePath());

```

The crux of the matter is that `$this->app->getBasePath()` which, because I do have a perfectly “standard” setup, returns an empty string. This is what it should do in my case, but what we need is the base URL.

One way to get a full URL is accomplished like so.

```auto
// Remove these two lines of code
$this->phpRenderer->addAttribute('uri', $request->getUri());
$this->phpRenderer->addAttribute('basePath', $this->app->getBasePath());

```

```auto
// Replace with this code
$uri = $request->getUri();
$this->phpRenderer->addAttribute('uri', $uri);
$baseURL = $uri->getScheme() . '://' . $uri->getHost();
$this->phpRenderer->addAttribute('basePath', $baseURL);

```

This may or may not work for people serving out of a subdirectory. I’m not going to test for that setup.

> [@odan](#):
>
> On a **development** machine, you may want to run multiple websites or applications on the same apache instance. Then just keep the `DocumentRoot` default value, e.g. `/var/www/html` and create  
> a sub-directly per project, e.g. `/var/www/html/slim4` . Also add the two `.htaccess` files. The Slim (URL) basePath is then `/slim4` (without the public path).

Yes, that will work. My preference is to leave `/var/www/html` in the state that Apache creates when it is first installed. Individual projects are hung off of `/var/www/`, e.g. `/var/www/slim4`. Each project has a virtual host configuration (in `/etc/apache2/sites-available`) where the `DocumentRoot` is explicitly set. `/var/www` is locked down so it won’t accept HTTP requests.

Thanks for the really interesting Blog postings!
