Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

front controller in subdirectory #86

Closed
pine3ree opened this issue Apr 23, 2015 · 20 comments
Closed

front controller in subdirectory #86

pine3ree opened this issue Apr 23, 2015 · 20 comments

Comments

@pine3ree
Copy link

I know this sounds silly....but
I cannot make the router to recognize urls when the index.php is inside a subdirectory.
I added the RewriteBase rule but still the router works only if I prepend the subdirectory in rooute definitions.

/path/to/project/web/subdir/index.php
// web/ is the public web folder, the docroot
$dispatcher->setObject('hello',//doesn't work
$dispatcher->setObject('subdir/hello',// works...

what am i missing?

@pmjones
Copy link
Member

pmjones commented Apr 23, 2015

Post a gist of your router code.

@pine3ree
Copy link
Author

hi @pmjones
it's the basic hello / example. I used other aura components, i wanted to give the whole framework-stack a try. components used are ~2.0. I just pulled the aura/framework-project, i didn't add any extra route yet.

the dir layout is:

path/to/project/app
    ....
    composer.json
path/to/project/web/subdir
    index.php
    .htaccess

i have a setup with apache 2.2 fast-cgi php-cgi.

with the same setup all other frameworks zf2, sf2, yii2, slim, flight and a couple of mine all recognize the directory relative to the webroot and i don't need to include it in route definitions, which makes the application more portable.

thanks

  • updated comment
  • i forgot the subdir in the example

@pmjones
Copy link
Member

pmjones commented Apr 23, 2015

I wonder if it's the .htaccess file.

@pmjones
Copy link
Member

pmjones commented Apr 23, 2015

I just tried it here and it seems to work. Here was the process:

mkdir -p foo/bar/baz
cd foo/bar/baz
composer create-project aura/framework-project
cd ../../..
php -S localhost:8080

Browse to http://localhost:8080/foo/bar/baz/framework-project/web/index.php and I see "Hello World!".

@pine3ree
Copy link
Author

hi @pmjones
it's the one that comes wth the installation and looks good. I tried adding a RewriteBase /subdir/ but it seems the route won't recognize the url part before the webroot. I just tried a new installation with router v 2.2 , same results.

I am quickly reading the router code. In my implementations i have routing components trying matches againt a request object (which provides the subdirectory part), while aura-routing (Route) seems to get that (isMatch()) parsing a $server parameter by itself, which i guess in non testing environment is the $_SERVER superglobal.

i will look into it later,
thanks for your time anyway.

@pine3ree
Copy link
Author

@pmjones

but the builtin web-server always has the working directory translated to a root "/" url, so it doesn't matter where the index.php is located as you usually run the server inside the directory it resides in.

@pmjones
Copy link
Member

pmjones commented Apr 23, 2015

I'm starting the web-server multiple directories up, so there's no index in that directory.

@harikt
Copy link
Member

harikt commented Apr 23, 2015

Hi @pine3ree ,

I have not heard such an issue before. I will try to replicate this.

So if I am correct you are working with aura/web-project .

Could you give a tree -L 3 or 4 level from project path .

@pine3ree
Copy link
Author

i just found this old post, not sure it still applies:

http://elofson.ca/2013/10/mini-framework-with-aura/
"Note that I included the ‘/aura’ in my pattern. If you don’t use /aura in your url, then leave that out!"

The author adds the subdirecory in route definitions too.

@harikt
Copy link
Member

harikt commented Apr 23, 2015

@pine3ree thanks for the link. Nice post also, never noticed it. It is not using the framework, but components only. But over all functionality is some what similar. One of the problem I could not figure is how we could replicate the issue. May be you could give the steps you did like .

composer create-project aura/web-project here
cd here 

Your virtual host points to /here/web ? or some where else ?

@pine3ree
Copy link
Author

hello again @harikt.
I used aura input, filter, di b4 . I had a free hour and i wanted to try the router and everything else.
I had an old 2.0 framework-project lying around and i created a fresh web-project.

// tree -aL 3
├── app
│   ├── 2
│   │   ├── CHANGES.md
│   │   ├── cli
│   │   ├── composer.json
│   │   ├── composer.lock
│   │   ├── config
│   │   ├── CONTRIBUTING.md
│   │   ├── .gitignore
│   │   ├── LICENSE
│   │   ├── phpunit.php
│   │   ├── phpunit.sh
│   │   ├── phpunit.xml.dist
│   │   ├── README.md
│   │   ├── src
│   │   ├── tests
│   │   ├── tmp
│   │   ├── .travis.yml
│   │   ├── vendor
│   │   └── web
│   └── subdir
│       ├── CHANGES.md
│       ├── composer.json
│       ├── composer.lock
│       ├── config
│       ├── CONTRIBUTING.md
│       ├── .gitignore
│       ├── LICENSE
│       ├── phpunit.php
│       ├── phpunit.sh
│       ├── phpunit.xml.dist
│       ├── README.md
│       ├── src
│       ├── tests
│       ├── tmp
│       ├── .travis.yml
│       └── vendor
├── log
│   └── 2015
│       ├── 2015-04-23.access.log
└── web
    ├── 2
    │   ├── .htaccess
    │   └── index.php
    └── subdir
        ├── .htaccess
        └── index.php

the 2/ dir has the 2.0 components
the subdir/ has the fresh installation

anyway, i don't want to waste your time guys.
I will look into it myself, i was just hoping for a quick explaination for a silly mistake of mine.

thanks a lot! regards!

@pmjones
Copy link
Member

pmjones commented Apr 23, 2015

The only thing I can suggest is to use index.php when browsing; e.g., /foo/bar/baz/index.php/hello, instead of /foo/bar/baz/hello. (Seeing index.php in the URL is how the WebKernelRouter knows to strip off the earlier portions of the path.) If you come up with a better solution let us know.

@pine3ree
Copy link
Author

@pmjones
thanks You Paul.
calling http://aura.local/subdir/index.php works!
calling http://aura.local/subdir/ results in unresolved route
calling http://aura.local/subdir/ works if routes are defined with "/subdir" prefix.

@pine3ree
Copy link
Author

Hi @harikt

steps

// my/project/path/web and /my/project/path/app exists
// /my/project/path/web is the apache vhost docroot

cd /my/project/path/app
composer create-project aura/web-project subdir
mkdir -p /my/project/path/web/subdir
mv  /my/project/path/app/subdir/web/index.php /my/project/path/web/subdir
mv  /my/project/path/app/subdir/web/.htaccess /my/project/path/web/subdir
rm /my/project/path/app/subdir/web

optionally add a RewriteBase in .htaccess

basically application surces live inside subdirs in a common folder

/my/project/path/app
   app1/
   app2/
   subdir/

so the app/ directory name real meaning would be apps/, i just avoid plurals

app entry points inside subdirs the vhost webroot

/my/project/path/web
    app1/index.php
    app2/index.php
    subdir/index.php

I always use this strategy when starting a new project so i can test suburl handling, features and response times, before deciding which framework to use.

btw, in my request implementation i get the PATH_INFO virtual path or build one if not set in the php request environment, and pass it to the router component. Maybe this is the missing part? My components are not decoupled: the router depends on the request object, but before rewriting them i will wait for a definitive version of psr-7.

@pine3ree
Copy link
Author

Hi @pmjones @harikt ,
i just took a deeper look into the aura-router and aura-web code.
The webKernelRouter::getPath() is used to get the Route when invoked => the router will try to find a match using the value returned by this method.

The webKernelRouter::getPath() works like this:
it uses the $path determined parsing REQUEST_URI (short version of what Request/Url really does)

  • if there is no 'index.php' string in the $path it simply return it (es. '/subdir/' => '/subdir/')
  • if it contains 'index.php' it will strip it and everything that precedes it (es
    '/subdir/index.php' => '/'
    '/subdir/index.php/hello' => '/hello'
    )

When the entry script is inside a subdir the subdir part will never get stripped unless you use the full entry script path, as @pmjones suggests, so, without using the script filename in the urls the router will never find a match unless the subdir is added as a prefix in all route definitions.

i believe there are a couple of way of solving this:

  1. make the web kernel be aware of the subir parts and feed the stripped url to the router/route.
  2. add a global mount parameter to the route definition part, so it is automatically added when defining routes.

@pine3ree
Copy link
Author

hi @pmjones ,

could auraphp/Aura.Web_Kernel#30 be a valid (quick) fix? This PR is not to be merged as it is, as it uses a superglobal. Just as quick fix. I am not sure if it could break anything else in aura.

If so, the script name could be retrieved adding a new key in Request\Url:

$path = $this->request->url->get('script_name');
//...
    /**
     *
     * @var array component constants, see http://php.net/parse-url
     *
     */
    protected $keys = array(
        PHP_URL_SCHEME      => 'scheme',
        PHP_URL_HOST        => 'host',
        PHP_URL_PORT        => 'port',
        PHP_URL_USER        => 'user',
        PHP_URL_PASS        => 'pass',
        PHP_URL_PATH        => 'path',
        PHP_URL_QUERY       => 'query',
        PHP_URL_FRAGMENT    => 'fragment',
        'script_name'       => 'script_name'
    );
//...
    protected function setParts($server)
    {
        $parts = parse_url($this->string);
        if ($this->hostIsMissing($server)) {
            $parts[PHP_URL_HOST] = null;
        }
        $this->parts = $parts;
        $this->parts['script_name'] = $this->getScriptName($server);
    }
//...
    /**
     *
     * Get the $_SERVER['SCRIPT_NAME'] value.
     *
     * @param array $server A copy of $_SERVER.
     *
     * @return bool
     *
     */
    protected function getScriptName($server)
    {
        return isset($server['SCRIPT_NAME'])
             ? $server['SCRIPT_NAME']
             : null;
    }

@pmjones
Copy link
Member

pmjones commented Apr 24, 2015

I just landed; at first glance this looks OK. I'll review further and comment or merge as appropriate. Thanks!

@pine3ree
Copy link
Author

@pmjones
hi, please do not merge the PR as it is. I leave the implementation of
$this->request->url->get('script_name');
or
$this->request->url->getScriptName(); // public
or whatever...
to your coding style.
the pr is intended only as a suggestion of a way to address the issue i met.

kind regards,
maks

@pmjones
Copy link
Member

pmjones commented Jul 16, 2015

I've been thinking about this, and @harikt had a related idea in PR #84 . There's a related issue, in that generated URLs need to have the prefix added to them. I propose adding a $prefix parameter to the Router constructor. This will be stripped from the incoming URL before matching, and added to generated URLs. That should allow explicit setup of the expected prefix, instead of implicitly calculating it. @pine3ree @harikt thoughts?

@pmjones
Copy link
Member

pmjones commented Jul 17, 2015

Fixed in #96.

@pmjones pmjones closed this as completed Jul 17, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants