I'm using PHP and ToroPHP for routing.
Unknown number of child pages
It works fine, but in my case I can add pages with childs and parents, where a parent can have an unknown number of have childpages.
In ToroPHP it might look like this:
// My Path: http://www.test.com/product/house/room/table/leg/color/
Toro::serve(array(
"/" => "Home",
"/:string/:string/:string/:string/:string/:string/" => "Page"
));
class Page {
function get($slug, $slug2, $slug3, $slug4, $slug5, $slug6) {
echo "First slug: $slug";
}
}
Problem
I can figure out what the maximum depth can be and then loop and append
out a string containing the "/:string" parameters but it don't look
that nice.
The get-function in the Page-class takes an unknown number of in
parameters. I can calculate the max depth from outside the function, but I need the function to know how many values to take.
Question
Is there an alternative way the the problem 1? Some regular expression maybe?
How can I make a function take an unkown number of in parameters?
Maybe I try to solve this the wrong way and the first two questions are not relevant? Correct me if that is.
In order for your action to receive all parameters, you need to capture them in your regex. You capture a value in regular expressions using parentheses. :string is just an alias for ([a-zA-Z]+). You could apply a wildcard after the first segment, like this:
"/product/(.*?)" => "Page"
However, this means that you need to parse the URL by yourself in your action, which is not very clean either.
If you want to make this particular case more clean, an option would be to use str_repeat:
Toro::serve(array(
"/" => "Home",
"/" . str_repeat(":string/", 6) => "Page"
));
ToroPHP is a very simple library, it should not be that hard to fork it and bend it to your will. Ideally, how would you like to define routes like this? Maybe a route like /:string*6?
You can always pass more or fewer parameters than defined to a PHP function. Use func_get_args to get all passed parameters and func_num_args to get the number of passed parameters.
In response to question 2, can you possibly format the GET parameters into an array and then pass in arrays rather than individual values?
Maybe like:
$allSlugs = array($slug, $slug2, $slug3, $slug4, $slug5, $slug6);
// Pass $allSlugs into your instance of Page::get($allSlugs);
class Page {
function get($getValues) {
echo isset($getValues[0]) ? "First slug: ".$getValues[0] : '';
}
}
Related
I'm trying to paginate the search results returned by the query. I have the following URL:
blog/search?query=post/5
Where I am trying to get the value of $start=5 from the URL using:
$start = $this->uri->segment(3);
It is not returning anything.
Where removing ?query=post, i.e, blog/search/5 works fine. But I want to keep the query parameter and read the value.
That's because of the ? character in the URI. CodeIgniter URI parser (and any other standard URI parser) does not recognize what you have in mind. After the ? character, it's all query string, not URI segments. See the output of PHP's parse_url():
parse_url('blog/search?query=post/5')
[
"path" => "blog/search",
"query" => "query=post/5",
]
See? The first segment is blog, the second is search and the rest is the querystring.
You need to change your URI design in an standard way. For example:
blog/search/5?query=post
So that the call to $this->uri->segment(3) will return what you have in mind.
Speaking of CodeIgniter pagination library, see reuse_query_string and page_query_string configs in the documentation.
I'm building a small restful api and I'm asking if it's possible to seperate the url to php file and the end of the url.
E.g. www.mydomain.com/api/parameter/1/2/
In this case the php file is adressed with www.mydomain.com/api/ or www.mydomain.com/api/index.php and parameter/1/2/ is the parameter.
I want a CRUD interface so that GET without parameter gets a list of all data. To achieve this I need to check if a parameter is attached and to extract the parameter.
Other example
www.mydomain.com/topics/ => gets all topics
www.mydomain.com/topics/1/posts/ => gets all posts of topic 1,
www.mydomain.com/topics/1/posts/2/ => gets post 2 of topic 1
My question is: Is it possible and how?
You would probably have to read the request URI from the end of the URL using $_SERVER['request_uri']. This would return /api/parameter/1/2. You could then substring it if the length is reliable, or use a regex with preg_match to get just the parameter section. e.g.
preg_match("parameter\/.*", $_SERVER['request_uri'], $matches)
would return either the string parameter/1/2 in the $matches variable, or false if no match was found
But yeah like others are saying, you're probably better using GET parameters if you can, and just do a check using isset() to see if there are any parameters.
I have a few routes that takes a couple of UUIDs as parameters:
Route::get('/foo/{uuid1}/{uuid2}', 'Controller#action');
I want to be able to verify that those parameters are the correct format before passing control off to the action:
Route::pattern('uuid1', '^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$');
This works fine. However, I really don't want to repeat that pattern so many times (in the real case I have it repeated 8 times for 8 different UUID route parameters).
I can't do this:
Route::get('/foo/{uuid}/{uuid}', 'Controller#action');
Because that produces an error:
Route pattern "/foo/{uuid}/{uuid}" cannot reference variable name "uuid" more than once.
I can lump them all into a single function call since I discovered Route::patterns:
Route::patterns([
'uuid1' => '^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$',
'uuid2' => '^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$',
]);
But that is still repetitious. Is there a way I can bind multiple pattern keys to a single regular expression?
Ideally I'd like to find a way that avoids something like this:
$pattern = 'uuid regex';
Route::patterns([
'uuid1' => $pattern,
'uuid2' => $pattern,
]);
There's no built in way to handle this, and I actually think the solution you found is pretty nice. Maybe a bit more elegant would be this:
Route::patterns(array_fill_keys(['uuid1', 'uuid2'], '/uuid regex/'));
Regular expressions have never been one of my strong points, and this one has me stumped. As part of a project, I want to develop an SEO link class in PHP. Handling the mod_rewrite through Apache is fairly straightforward for me, and that works great.
However, I'd like to create a function which is able to generate the SEO link based on a dynamic URL I pass in as the first (and only) parameter to the function.
For example, this would be the function call in PHP:
Blog Post Title
The function CreateLink would then analyse the string passed in, and output something like this:
blog/blog-post-title
The URL stub of the blog post is stored in the Database already. I think the best way to achieve this is to analyse the dynamic URL string passed in, and generate an associative array to be analysed. My question is, what would the Regular Expression be to take the URL and produce the following associative array in PHP?
link_pieces['page_type'] = 'blog/post';
link_pieces['post'] = 123;
link_pieces['category'] = 5;
Where page_type is the base directory and request page without extension, and the other array values are the request vars?
You can just use parse_url and parse_str, no need for regexes.
Use parse_url to break the URL into parts:
This function parses a URL and returns an associative array containing any of the various components of the URL that are present.
Then use parse_str to break down the querystring part of the URL.
$i = 0;
$suggestion = 'page';
$suggestions = array();
while ($arg = arg($i++)) {
$arg = str_replace(array("/", "\\", "\0"), '', $arg);
$suggestions[] = $suggestion . '-' . $arg;
if (!is_numeric($arg)) {
$suggestion .= '-' . $arg;
}
}
i am a newbie of drupal,i can't follow the above code well, hope someone can explain it to me.i know the first line is assign the 0 to $i,then assign 'page' to an array. and i know arg is an array in drupal.
for example, now the url is example.com/node/1. how to use this url to use the above code.
It looks like its purpose is to generate ID strings (probably for a CSS class) depending on paths and excludes numeric components of the path out of the generated ID.
For example, 'my/123/article' produces the ID "page-my-article".
It seems this comes from a function (because the loop reads parameters using arg()) and that it expects Drupal paths such as "node/123/edit".
So the function would be called something like that:
mystery_function("my/123/article", "even/better/article");
Variables:
$i is the variable that stores the loop index
$suggestion is a String that store the generated ID. It is initialized to "page" because the ID is meant to have the syntax "page-SOMETHING".
$arg comes from the while loop: it reads the parameters passed to the mystery function one by one
$suggestions is an array that contains the generated IDs, one per argument passed to the mystery function.
In the loop:
The "$arg = str_replace..." line removes unwanted characters like "\" (however that line could definitely be improved).
The "$suggestions[] = ..." line adds the ID to the array of results.
The "if (!is_numeric($arg)..." line excludes numbers from the generated ID (e.g. "my/123/article" is probably supposed to produce "my-article")
The "$suggestion .= ..." line appends the value of "$arg" to the value of "$suggestion" and stores it in "$suggestion"
But honestly, I wouldn't advise to use that code: I doubt it works as intended given $suggestion isn't reinitialized at each loop so the value of the first path will get attached to the second, and to the third, and so on, and I doubt that is intentional.
Most likely this code is located in a theme's template.php in the preprocess_page hook. If that is the case, it's used to create template suggestions based on an argument supplied like the node id, to make it possible to create a page template per node.
What this code does, is that it loops though all the arguments in the drupal url, This could be user/3, node/3, taxonomy/term/3 or any custom url.
It first does some cleanup in the argument, to make sure that no weird symbols is added. This is not needed for most urls, but is probably there as a safety to avoid needing to have to create weird template names in some cases. This is done with str_replace
Next it adds the a suggestion to the list, based on the arg.
If the arg isn't numeric it adds that to the suggestion so it will be used in the next loop.
The idea is that you with the above urls will get added some template suggestions that look like this:
page
page-user
page-user-3
And
page
page-taxonomy
page-taxonomy-term
page-taxonomy-term-3
In this list drupal will use the last one possible, so if page-user-3.tpl.php exists, that will be used as page template for user/3, if not page-user.tpl.php will be used and so on.
This can be desired if you want to create customize page templates for the users page, or the nodes page while being able to create customized page templates for specific users.
This is not, however, a strategy I would want to employ. If you do this, you will end of with lots of different versions of a page template, and it will end up creating the maintenance nightmare that CMS systems was supposed to eliminate. If you truly need this many different page templates, you should instead look at context or panels, and put some logic into this instead.