We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Issue with urlencoded parameter containing + or &

I have URLs with slugs like so: /object/123/label/some+nice%2B+stuff+%26+then+some (the original label being 'some nice+ stuff & then some', url encoded)

Unfortunately the '%2B' (+) and '%26' seem to get stripped out resulting in 'some nice stuff ' for the label param. So the %2B is converted to a space (there are two spaces between the words 'nice' and 'stuff' ), and the '%26' seems to be interpreted as a param separator, since the resulting param string is cut off at this point.

The param is apparently being url-decoded and in the process stripped of special chars? The $_GET['_url'] variable is already stripped as well, so I cannot use this.

My route is: $router->add('/object/{id:[0-9]}/label/{label:.}', 'MyController::label'); In my controller I have: public function labelAction($id, $label){}

I know I can resolve this by adding a querystring param ( ?label=some+nice%2B+stuff+%26+then+some ) but that doesn't feel like it should be the way to do this in Phalcon.

It is not really a problem for me since the slugs are only there for the purpose of having a nicer URL to look at, but I can imagine this being a problem in other cases.

Please advise how I should approach this 'Phalcon-style'.

hey, query_string is web standard, you can use it whenever you want. phalcon way is mapping /controller/action/param - but for query string is space too ;) eg ?q=search_word phalcon have got methods to get query string $this->request->get("q");

If you don' need SEO friendly url and need to use query_string then use it.

Second: your router file shouldn't use $_GET['_url'], you can use $_SERVER['REQUEST_URI']

<?php

$router = new Phalcon\Mvc\Router();

$router->setUriSource(\Phalcon\Mvc\Router::URI_SOURCE_SERVER_REQUEST_URI);

$router->removeExtraSlashes(true);
$router->setDefaultController('index');
$router->setDefaultAction('index');

$router->add("/whatever","whatever:index");

return $router;

for example for virtual server for nginx

server {
    listen 80;
    server_name domain.tld www.domain.tld;

    root /home/domain.tld/public;
    index index.php index.html index.htm;

    location ~* \.(eot|otf|ttf|woff)$ {
        add_header Access-Control-Allow-Origin *;
    }

    location = /favicon.ico {
      log_not_found off;
    }

    location / {
            try_files $uri $uri/ /index.php?&$args;
    }

    location ~ \.php$ {
        try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass unix:/var/run/php5-fpm.sock;
            fastcgi_index index.php;
            include fastcgi_params;
    }

    location ~ /\.ht {
            deny all;
    }
}

Thanks for your reply. Perhaps I need to clarify further. I'm aware of the many ways to use the querystring and have done so already, but I consider this a workaround. I'm not using $_GET['_url'], I was just checking it's contents to see if I could discover a point where I could intercept the param before it is wrongly decoded.

In short: I'm trying to find a way to use urlencoded params in a Phalcon route. Perhaps even more bluntly: I think it is a bug that urlencoded params are not relayed properly, but was hoping that I was doing something wrong.



98.9k

we have similar routes in Album O'Rama:

https://album-o-rama.phalcon.io/album/52/Kid+A https://album-o-rama.phalcon.io/album/20685/Born+To+Die+-+The+Paradise+Edition

The characters '+' are converted to spaces, but you're right, although Phalcon is not converting those characters, I think the browser/web server/php is doing that transformation, no sure why. I'm testing on Windows with Apache and the behavior is the same, maybe this behavior is related to PHP.



5.5k
Accepted
answer

Thanks for that suggestion. It made me realise that mod_rewrite might be the culprit. I found that if I add the [B] flag to my config, I do receive a urlencoded string as a param.

For background see: https://httpd.apache.org/docs/2.2/mod/mod_rewrite.html#rewriteflags .

This .htaccess works for me:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ index.php?_url=/$1 [QSA,L,B]
</IfModule>

Just wanted to comment that I was having the exact same problem (though in my case it was not just for SEO) & the [B] flag fixed it for me too. Thanks for posting the solution.

Might I suggest you amend your original subject to include [solved]?

I am getting Object not found error when i put B flag in project root htaccess file

Can you help me with this?

Thanks for that suggestion. It made me realise that mod_rewrite might be the culprit. I found that if I add the [B] flag to my config, I do receive a urlencoded string as a param.

For background see: https://httpd.apache.org/docs/2.2/mod/mod_rewrite.html#rewriteflags .

This .htaccess works for me:

<IfModule mod_rewrite.c>
   RewriteEngine On
   RewriteCond %{REQUEST_FILENAME} !-d
   RewriteCond %{REQUEST_FILENAME} !-f
   RewriteRule ^(.*)$ index.php?_url=/$1 [QSA,L,B]
</IfModule>