For a new application I'd like to work with the URI to determine what content should be loaded. Nothing special so far ... But how can I let the slug have slash(es) in it and make sure Zend Framework sees them as 1 variable? ZF splits the requested URL in chunks where every part is the string between 2 slashed. Now I'd like to have all the parts in 1 variable to work with.
For Example:
/de/my/page
de > language
my/page > 1 variable
Any ideas?
Advice from Hari K is the best choice, but if you really want to keep your slash, you can work with a Zend_Controller_Router_Route_Regex to catch your parameter, you just need to find a good regexp, a simple example :
$routetotry = new Zend_Controller_Router_Route_Regex('([^/]+)/(.*)',
array(1 => 'de', 'controller' => 'someController', 'action' => 'someAction'),
array(1 => 'lang',2=>'my_variable_with_slash'),
'%s/%s'
);
$router->addRoute('routetotry', $routetotry);
Custom router. Most flexible solution, but not the easiest one :(
Replace the slashes in the slug with someother value of your choice.
For example hyphen ( - ) or underscore ( _ ) .
Related
In Symfony 5, I would like to generate an URL partially based on GET paramaters already posted.
Let's assume that the URL posted is:
user/edit/5?foo=1&bar=1&baz=1&qux=1
I would like to generate in the controller without foo:
user/edit/5?bar=1&baz=1&qux=1
First, I remove foo parameter :
$request->query->remove('foo');
If I didn't get the user_id in the URL as route parameter (5), I would use:
$this->generateUrl('user_edit', $request->query->all());
But this is not working because user_id is missing. So how can I generated such URL without rewriting all variables:
$this->generateUrl('user_edit', ['id' => $user->getId(), ???]);
I was thinking about PHP function array_merge() but this seems to me more a trick than an elegant solution:
$this->generateUrl('user_edit', array_merge(
['id' => $user->getId()],
$request->query->all())
);
There is nothing wrong in using array_merge(). That's exactly what you want to accomplish. It's not a "trick", it's a language feature.
If you want a less verbose syntax, just use +.
$this->generateUrl('user_edit', $request->query->all() + ['id' => $user->getId()]);
The end result is exactly the same for the above, and it's shorter.
I've trying to make my own route class - and I've hot problem with parsing valid url's.
This is an example url:
http://localhost/app/module/command/i15
And I need every element after slash / to be an additional element in array creating using preg_match in php.
So - for searching of numbers I've got: ([0-9]+)
Searching strings that contains letters, signs like - or _ I've got ([^.]+) (here's the problem)
whole regexp looks like this:
(app)\/(module)\/([^.]+)\/i([0-9]+)
i want an array of 5 elements, something like that:
0 => app, 1=> module, 2 => command, 3 => i15
It will be more beauty if preg_match will return only something like that:
0 => app, 1=> module, 2 => command, 3 => 15 (without I as param identifier)
Can anyone quick help me with this ? I stuck 2 days in that, and can't find right solution.
EDIT:
I've got some regexp predefined like:
/app/contacts/list => (app)\/(contacts)\/([^.]+)
/app/contacts/edit/i15 => (app)\/(contacts)\/([^.]+)\/i([\d]+)
/app/contacts/view/i15-c2 => (app)\/(contacts)\/([^.]+)\/i([\d]+)-c([\d]+)
And for all of those I prepare different regexp like above. Problem stars when I need to parse something between:
/app/contacts/preview/random-name/i15-c2
or
/app/contacts/preview/random-name-i15-c2
([^.]+) catches also \ (slash) - and in above first example this slash broke whole regexp :-(
EDIT SECOND TIME :-)
I've got some predefined regexps for some paths. Lets have a look:
$regexp = [
[0 => '(app)\/([^/]+)'],
[1 => '(app)\/([^/]+)\/i([0-9]+)']
];
Next i check current url and match the best result - I know what I want, but php doesn't know what user select so:
if I enter url with path:
app/username/i15
System shows me that $regexp[0] is best result - what it is not true, because $regexp[1] are the best.
I hope this explains my problem.
Since you're using groups to capture in your regex, you can use them to create your desired array. Pass a variable to preg_match() to store the groups:
$components = [];
preg_match('#(app)/(module)/([^.]+)/i([0-9]+)#', $uri, $components);
Now the first element of $components is the whole match, and then the groups.
array_shift($components); # discard first element
Ok heres class for my routing:
https://gist.github.com/djmassive/d7487cef92e3adb1abf7ca31d3e96a53
Whole magic are done in method parse()
I've adding routings:
$route->get('(app)\/:string', [ 'schema' => '2', 'module' => 'system', 'file' => 'profile' ]);
$route->get('(app)\/:string\/i:id', [ 'schema' => '2,3', 'module' => 'system', 'file' => 'profile', 'command' => 'view' ]);
schema define what I want to be na id - it can be int, string or array.
module is folder name
file is filename
command is command use in file for show directly what I want
If I had url:
app/list - system reads it like that:
$command is list (schema shows second element) - works
app/username/i15
$command should be view
$id should be [ username, 15 ]
in this case, first regexp is showing 66% of match like second one - but second one should be 100%
Have a look at debuging:
Checking regexp: #(app)\/([^/]+)# - to match path: app/username/i15
Results preg_match \$matches array:
Array ( [0] => app/username [1] => app [2] => username )
Percentage match: 66.6666666667%
Checking regexp: #(app)\/([^/]+)\/i([\d]+)# - to match path: app/username/i15
Results preg_match \$matches array:
Array ( [0] => app/username/i15 [1] => app [2] => username [3] => 15 )
Percentage match: 66.6666666667%
we see, that first regexp are not good because there are not third element.
From what I know, the whole problem is mainly to not return what does not meet the full condition.
Example:
I want to make an url with different categorised variables. And there is an order. First variable is vegetables({variable01}), second is fruits({variable02}), third is trees ({variable03}) etc.
xxx.com/{variable01}-{variable02}-{variable03}-{variable04}-......
Yes I got this url.
BUT
What if a variable have two words(or three) AND I want the seperator is also a hyphen(brussels-sprouts)?
Example:
xxx.com/brussels-sprouts-{variable02}-{variable03}-{variable04}-......
or
xxx.com/{variable02}-green-apple-{variable03}-{variable04}-......
xxx.com/brussels-sprouts-green-apple
How can this be possible?
Thanks.
There is no way to specify the boundaries of your variables anymore, so it's only possible if you know the exact amount of variables and only 1 of your variables may contain hyphens. You can create a regex for that:
First variable:
^([\w-]+)-(\w+)-(\w+)-(\w+)$
Second variable:
^(\w+)-([\w-]+)-(\w+)-(\w+)$
But: if you know that each variable can have at most 1 hyphen, you can also do this:
/var1-foo1-var2-foo2-var3-foo3-var4
RewriteRule ^(\w+(-\w+)?)-(\w+(-\w+)?)-(\w+(-\w+)?)-(\w+(-\w+)?)$ index.php?var1=$1&var2=$3&var3=$5&var4=$7 [L]
Which results in:
array (
'var1' => 'var1-foo1',
'var2' => 'var2-foo2',
'var3' => 'var3-foo3',
'var4' => 'var4',
)
I'm currently working on an advance search feature that needs to work with .htaccess clean urls. This search could have 3-5 Parameters depending on what the user inputs. So basically the search string ( before clean URL ) could be something like this:
http://www.example.com?category=lorem&subcategory=ipsum&on_sale=1&featured=1&vendor=foo
These parameters could also be in a different order, so I can't use the standard regex method to clean up the URL.
The way I solved this was to use keywords & terms in the URL.
My final URL looked like so:
http://www.example.com/search/term/lorem/category/shirts/subcategory/tank-top/color/red/featured/1
In htaccess I looked for the signifier "/search" and made rules for search parameters that followed.
RewriteRule ^search/([A-Za-z0-9_-\s]+)/([A-Za-z0-9_-\s]+)/?$ http://www.example.com/?page=search&keywords[]=$1&terms[]=$2 [QSA,NC]
etc,etc.
So basically in PHP, all odd indices are stored in a $keywords array and all even indices are stored in a $terms array.
I then check all keywords against a list of acceptable keywords to prevent MySQL injection.
$allowable_keywords = array('term','category','subcategory','color','featured');
I am then able to filter the search results with this tidy little search array by combining the keywords and terms.
$params = array_combine($keywords,$terms);
$params = array(
'term' => 'lorem',
'category' => 'shirts',
'subcategory' => 'tank-top',
'color' => 'red',
'featured' => 1
);
Hope this helps!
In CakePHP putting a querystring in the url doesn't cause it to be automatically parsed and split like it normally is when the controller is directly invoked.
For example:
$this->testAction('/testing/post?company=utCompany', array('return' => 'vars')) ;
will result in:
[url] => /testing/post?company=utCompany
While invoking the url directly via the web browser results in:
[url] => Array
(
[url] => testing/post
[company] => utCompany
)
Without editing the CakePHP source, is there some way to have the querystring split when running unit tests?
I have what is either a hack (i.e. may not work for future CakePHP releases) or an undocumented feature.
If the second testAction parameter includes an named array called 'url' then the values will be placed in the $this->params object in the controller. This gives us the same net result as when the controller is directly invoked.
$data = array ('company' => 'utCompany') ;
$result = $this->testAction('/testing/post', array
(
'return' => 'vars',
'method' => 'get',
'url' => $data)
) ;
I'm satisfied with this method for what I need to do. I'll open the question to the community shortly so that it in the future a better answer can be provided.
None of these answers will woerk in Cake 1.3. You should instead set the following before your testAction call:
$this->__savedGetData['company'] = 'utcompany';
CakePHP does provide some level of url splitting but it only seems to work in the run-time configuration and not the test configuration. I'll contact the CakePHP if this is intentional.
I suggestion for your querystring parser would be to use the PHP function explode.
I believe you can do something like this:
$result = explode ('&', $queryString, -1) ;
which would give you your key-pairs in seperate array slots upon which you can iterate and perform a second explode like so:
$keyPair = explode ('=', $result[n], -1) ;
However, all this being said it would be better to peek under the hood of CakePHP and see what they are doing.
What I typed above won't correctly handle situations where your querystring contains html escaped characters (prefixed with &), nor will it handle hex encoded url strings.
use _GET['parmname'];