slimphp / Twig-View

Slim Framework view helper built on top of the Twig templating component
http://slimframework.com
MIT License
356 stars 86 forks source link

is_current_url() doesn't take basepath into consideration #199

Open MrBrax opened 3 years ago

MrBrax commented 3 years ago

When using is_current_url() and a slimphp basepath is set, it won't return true when visiting that route. Removing the basepath fixes it.

l0gicgate commented 3 years ago

Are you instantiating the TwigMiddleware with the same basePath as you have set in Slim?

MrBrax commented 3 years ago

I'm not sure actually, i remember implementing it being a real pain.

Current setup

l0gicgate commented 3 years ago

Are you sure this gets called: https://github.com/MrBrax/TwitchAutomator/blob/947956114a9002ebcbb909d1efc8b191b249ac9b/public/index.php#L57

Because if you look in the TwigMiddleware it gets the basePath from the app: https://github.com/slimphp/Twig-View/blob/3.x/src/TwigMiddleware.php#L71

MrBrax commented 3 years ago

I didn't know that was possible, nor what that thing does. Gonna have to research more.

MrBrax commented 3 years ago

Are you sure this gets called: https://github.com/MrBrax/TwitchAutomator/blob/947956114a9002ebcbb909d1efc8b191b249ac9b/public/index.php#L57

Yes, the basepath works everywhere else, in the base_path() function too

l0gicgate commented 3 years ago

You should try and do some debugging by putting a var_dump($currentUrl) at this line: https://github.com/slimphp/Twig-View/blob/3.x/src/TwigRuntimeExtension.php#L80

As you can see, the base path is taken into consideration there.

MrBrax commented 3 years ago

That tells me that the basepath is appended twice.

<a href="{{ url_for('about') }}" becomes /path/path/about

l0gicgate commented 3 years ago

That doesn't give me any insight on what's going on. You will need to debug what's happening in TwigRuntimeExtension and var_dump($this->uri) and var_dump($this->basePath).

Add those statements in the vendor source files where those files are located.

MrBrax commented 3 years ago

$currentUrl = "/path/path/dashboard"

$this->uri = object(Slim\Psr7\Uri)#160 (8) { ["scheme":protected]=> string(4) "http" ["user":protected]=> string(0) "" ["password":protected]=> string(0) "" ["host":protected]=> string(17) "example.com" ["port":protected]=> int(14184) ["path":protected]=> string(15) "/path/dashboard" ["query":protected]=> string(10) "/dashboard" ["fragment":protected]=> string(0) "" }

$this->basePath = "/path"

l0gicgate commented 3 years ago

It seems that something is modifying the request URI and adding the basepath to it and it shouldn’t.

MrBrax commented 3 years ago

nginx maybe? setting nginx up with subfolders took me days of trial and error, almost nothing worked. maybe there's something in there

MrBrax commented 3 years ago

I'll keep it broken though, too much weird stuff to debug. Thanks though.

kloor commented 3 years ago

Hello @l0gicgate,

I think I've run into the same issue, and made a simple test case. Within my Apache DocumentRoot, I created a folder named testcase and added the following index.php file:

<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
use Slim\Views\Twig;
use Slim\Views\TwigMiddleware;

require __DIR__ . '/vendor/autoload.php';

$app = AppFactory::create();
$app->setBasePath('/testcase');

$twig = Twig::create('.');
$app->add(TwigMiddleware::create($app, $twig));

$app->get('/', function (Request $request, Response $response, $args) {
    $view = Twig::fromRequest($request);
    $response->getBody()->write($view->fetchFromString('{{ current_url() }}'));

    return $response;
});

$app->run();

The following .htaccess file:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]

And the following composer.json file:

{
    "require": {
        "slim/slim": "^4.6",
        "slim/twig-view": "^3.1",
        "slim/psr7": "^1.2"
    }
}

After composer install if I access the directory in the web browser, the output from the current_url() is /testcase/testcase/. I haven't investigated further, but it does seem like base path should not be prepended to the path from the URI.

bYemma commented 3 years ago

I have the same issue. The base path is applied twice.

iRaziul commented 3 years ago

Why?

The problem occurs while using slim in the sub-directory.

While running slim in a sub-directory the $request->getUri()->getPath() will returns the absolute path.

// create app
$app = AppFactory::create();
$app->setBasePath('/project/slim4');

// twig
$twig = Twig::create('.');

// middleware
$app->add(TwigMiddleware::create($app, $twig))

Let's check the path (in middleware or controller/action)

public function __invoke(ServerRequestInterface $request, ResponseInterface $response, array $args = []) : ResponseInterface
{
    exit($request->getUri()->getPath());  # /project/slim4
}

The constructor of TwigRuntimeExtension accepts 3 parameters routeParser, uri and basePath.

In isCurrentUrl and getCurrenturl methods:

$currentUrl = $this->basePath.$this->uri->getPath();

$this->basePath returns /project/slim4

$this->uri->getPath() returns /projects/slim4/

so $currentUrl returns /project/slim4/project/slim4/ 😒

Solution!

This method can be applied to make it work without making any changes to Twig-View

// create app
$app = AppFactory::create();
$app->setBasePath('/project/slim4');

// twig
$twig = Twig::create('.');

// middleware
$app->add(new TwigMiddleware($twig, $app->getRouteCollector()->getRouteParser()));
l0gicgate commented 3 years ago

I think there is an issue with double invocation when resolving the middleware perhaps.. It'd be great to get a failing test case so we can fix this.

MrBrax commented 3 years ago

Funny how I've moved on to a SPA since then, but i hope this gets resolved.

paulocanedo commented 2 years ago

I have the same issue, configured a nginx as a reverse proxy to my application:

https://domain.com/myapp -> http://internal_ip/

In TwigRuntimeExtension::isCurrentUrl:

The solution proposed by @iRaziul worked for me.

diodo commented 1 year ago

Any news on this issue ? Because the solution proposed by iRaziul not work for me. I use TwigWebpackExtension and it break all links to js and css. I need to set the basePath.

dfranco commented 6 months ago

Any news on this issue ? Because the solution proposed by iRaziul not work for me. I use TwigWebpackExtension and it break all links to js and css. I need to set the basePath.

I have the exact same issue, is there any will to fix it ?

odan commented 2 months ago

I can confirm this behavior (bug).

Minimal example application:

<?php

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
use Slim\Views\Twig;
use Slim\Views\TwigMiddleware;

require __DIR__ . '/../vendor/autoload.php';

$app = AppFactory::create();
$app->setBasePath('/slim4-demo');

$twig = Twig::create('.');
$app->add(TwigMiddleware::create($app, $twig));

$app->get('/', function (Request $request, Response $response) {
    $view = Twig::fromRequest($request);
    $response->getBody()->write($view->fetchFromString('Twig-View current_url: {{ current_url() }}<br>'));
    $response->getBody()->write('Request URI Path: ' . $request->getUri()->getPath());

    return $response;
});

$app->run();

Running this application on Apache in a sub-directory of the webroot directory /slim4-demo the result looks as follows:

URL: http://localhost:8080/slim4-demo/

Actual result

Twig-View current_url: /slim4-demo/slim4-demo/
Request URI Path: /slim4-demo/

Expected result:

Twig-View current_url: /slim4-demo/
Request URI Path: /slim4-demo/

The suggested workaround might work in some situation, but it might cause errors in combination with Twig::fromRequest. Example:

$app->add(new TwigMiddleware($twig, $app->getRouteCollector()->getRouteParser()));

// ...
$app->get('/', function (Request $request, Response $response) {
    $view = Twig::fromRequest($request); // RuntimeException!
    // ...
    return $response;
});

This would throw an Exception like: Uncaught RuntimeException: Twig could not be found in the server request attributes using the key "view".

So it might not be the best solution for all.

The basePath is already part of the request URI. Tested with slim/psr7 and nyholm/psr7. So adding the basePath twice should be fixed as shown in the commit: https://github.com/blast007/Twig-View/commit/65c1a9fcc0499cb5479eddc5e2bc9a4f141f62df