modrewrite for smart URL's | multiple variables? - .htaccess

What is the best way to accomplish that?
Im planning to do some kind of smart modrewrite + a function to grab variable name from the URL.
For example:
A URL like:
domain.com/page-blog/id-5/title-a_blog_title/date-2011_08_05
Would return:
$urlvariable = page-blog/id-5/title-a_blog_title/date-2011_08_05
Than, I will run a function that will parse the $urlvariable and return
$urlvariable['page'] = blog
$urlvariable['id'] = 5
$urlvariable['title'] = a_blog_title
$urlvariable['date'] = 2011_08_05
But the rewrite should be able to handle smaller or bigger urls like:
domain.com/page-blog/id-5/
returning:
$urlvariable = page-blog/id-5/
or also:
domain.com/page-blog/id-5/title-a_blog_title/date-2011_08_05/var1-foo/var2-bar/var3-xpto/var4-xyz etc ...
$urlvariable = page-blog/id-5/title-a_blog_title/date-2011_08_05/var1-foo/var2-bar/var3-xpto/var4-xyz
Any way to do that? What would be the expression for rewrite?
Thanks,

As for me, the best way is to route all request to your php/another_language script and then use something like this:
for($i=1,$arr=explode('/',$_SERVER['REQUEST_URI']),$s=count($arr);$i<$s;++$i){ //avoid 0(empty part) and 1(script name)
$tmp=explode(' ',$arr[$i]);
$get[$tmp[0]]=$tmp[1];
}

RiaD has the right idea, using explode rather than regexps (since regexps are slower).
However, you might want to use regular expressions anyway to "normalize" the URL. But after that you can still use explode for a tiny speed gain, or do something like this
$url = "page-blog/id-5/blank-/title-a_blog_title/date-2011_08_05/var1-foo/var2-bar/var3-xpto/var4-xyz";
$url = preg_replace("~//+~", '/', $url); // remove multiple consequtive slashes
$params = array();
if( preg_match_all("~(\w+)-([^/]*)~", $url, $params) ) {
$params = array_combine($params[1], $params[2]);
print_r($params);
}
That will print:
Array(
[page] => blog
[id] => 5
[blank] =>
[title] => a_blog_title
[date] => 2011_08_05
[var1] => foo
[var2] => bar
[var3] => xpto
[var4] => xyz
)

Related

ModX Revo getimagelist snippet. How can I search for a string in the field?

$output = $modx->runSnippet('getImageList',array(
'tvname' => 'workOrders',
'where' => $_GET['search'] ,
'tpl' => 'workOrdersList',
'docid' => 3
));
One of the fields is a string with parameters. How can I check whether my search string is a part of that field? I have looked up how to use "where" parameter to accomplish this task but I am still stuck.
If you just use this extra (getUrlParam), you can call this instead of refering to the GET directly:
So your call could look like this:
$output = $modx->runSnippet('getImageList', array(
'tvname' => 'workOrders',
'where' => $modx->runSnippet('getUrlParam', array('name' => 'search`)),
'tpl' => 'workOrdersList',
'docid' => 3
));
This also takes care of malicious url parameters.
Where needs to be formatted as a JSON value, so you would need to define which field you are querying against and format as JSON. E.g. 'where' => $modx->toJSON(array('pagetitle'=>$_GET['search']))

Case insensitive hash keys perl

Problem
I have a hash/array structure, some of the hash keys are not in the same case though.
I would like to know if there is a way to handle this case without manually checking the keys of every hash.
In the example below i would like all ID/iD/id/Id fields to be printed.
Example code
use warnings;
use strict;
my $Hash = {
Server => [
{
Id=>123
},
{
iD=>456
},
{
ID=>789
}
]
};
for (#{$Hash->{Server}}){
print "$_->{ID}\n"
#This is the problematic part
}
Other
perl version: v5.10.0
This data is recieved from elsewhere and must remain the same case, the example above is minimal and i cannot just simply change them all to the same case.
Any more info needed let me know.
Well, it depends a little bit on your source of information. This looks like you've parsed something, so there may be a better solution.
However, with what we've got here, I'd do it like this:
for my $entry (#{$Hash->{Server}}){
#grep, find first match. Dupes discarded.
my ( $key ) = grep { /^id$/i } keys %$entry;
print "$key => ",$entry -> {$key},"\n";
}
This works by using grep with an i regex for case insensitive on keys, and grabbing whatever comes out first. So if you have multiple matches for /id/i then it'll be random which one you get. (sort could help with that though)
Given you're working with XML though, I'd probably backtrack a bit, throw out XML::Simple and do it like this instead:
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
my $twig = XML::Twig -> new ( twig_handlers => { '_all_' => sub { $_ -> lc_attnames }} );
$twig -> parse ( \*DATA );
print "XML looks like:\n";
$twig -> set_pretty_print ( 'indented_a');
$twig -> print;
print "Output:\n";
foreach my $server ( $twig -> get_xpath('//Server') ) {
print $server -> att('id'),"\n";
}
__DATA__
<XML>
<Server ID="123" />
<Server Id="456" />
<Server id="789" />
</XML>
Or you can just:
foreach my $server ( $twig -> get_xpath('//Server') ) {
$server -> lc_attnames;
print $server -> att('id'),"\n";
}
in lieu of doing it in the twig handlers. The first answer will 'fix' all of your XML to having lower case attributes, which might not be what you want. But then, it might be useful for other scenarios, which is why I've given two examples.
There is no built-in way to do that. What you could do is use List::Util's first to at least get less checks, and then still try until one fits for each of the keys.
use strict;
use warnings;
use feature 'say';
use List::Util 'first';
my $Hash = {
Server => [
{
Id => 123
},
{
iD => 456
},
{
ID => 789
}
]
};
foreach my $thing ( #{ $Hash->{Server} } ) {
# this returns the first match in the list, like grep
# so we need to use it here to return the actual value
say $thing->{ first { $thing->{$_} } qw/id ID iD Id/ };
}
If there are a lot of other keys in the data structure, this is cheaper than looking at all the keys, because you at max look up all possible id keys plus one, and at best two.
If you want the list of possible keys to auto-generate and the uppercase and lowercase letters can be arbitrarily mixed, take a look at this answer.
I would suggest you to use regex to ignore case of keys using i flag.
for my $item ( # { $Hash->{Server} }) {
for(keys %{$item}) {
print $item -> {$_},"\n" if /^ID$/i;
}
}

Cakephp 3 - Remove empty post from pagination

I'm working on multi language website.
In the English version of the website all works properly, because I entered translations.
$blogPosts = $this->BlogPosts->find('all')->where(['BlogPosts.active' => 1]);
$this->set('blogPosts',$this->paginate($blogPosts));
If I changed the language of website I would like to remove all the posts whose translation of the title is not entered.
I tried this, but it does not work:
$blogPosts = $this->BlogPosts->find('all')->where(['BlogPosts.active' => 1,'BlogPosts.title IS NOT' => null]);
$this->set('blogPosts',$this->paginate($blogPosts));
Still printed posts without titles.
How to solve this problem?
Try this conditions:
public function index()
{
$this->paginate['conditions'] = ['BlogPosts.active' => true , 'BlogPosts.title IS NOT' => null, 'BlogPosts.title !=' => ' '];
$this->paginate['order'] = ['BlogPosts.id' => 'desc'];
$this->paginate['limit'] = 4;
$blogPosts = $this->paginate($this->BlogPosts);
$this->set(compact('blogPosts'));
$this->set('_serialize', ['blogPosts']);
}
Query:
SELECT *
FROM blogPosts BlogPosts
WHERE (
BlogPosts.active = 1
AND BlogPosts.title IS NOT NULL
AND BlogPosts.title != ''
)
ORDER BY BlogPosts.id desc
LIMIT 4 OFFSET 0
I think faced with simmilar issue before. The pagination didn't worked as I excepted when I set order, limit together with custom where condition.
Try this:
$this->paginate['order'] = ['BlogPosts.id' => 'desc'];
$this->paginate['limit'] = 4;
$query = $this->BlogPost->find()
->select(['id', 'title', 'active'])
->where(['BlogPost.active' => true, 'BlogPost.title IS NOT' => null, 'BlogPost.id !=' => ''])
$data = $this->paginate($query);
$this->set('BlogPost', $data);

How do I fix SEO urls with lighttpd?

I want to rewrite my URL from ?p=pagename to a SEO friendly URL like this: /pagename
How does url.rewrite works?
I have seen an example like this but haven't figured how it works yet.
url.rewrite = (
"^/(data|install|js|styles)/(.*)$" => "$0",
"^/(.*\.php)(.*)$" => "$0",
"^/.*(\?.*)" => "/index.php$1",
"" => "/index.php"
)
The query string is not part of the URL matched by rewrite rules. You can match against the query string separately:
$HTTP["querystring"] =~ "^p=([^&]+)" {
url.rewrite = (
"/%1"
)
}

Kohana - $this->request->uri($params) alternative in 3.2

Is there any alternative for getting uri with changed parameter as $this->request->uri($params) in KO 3.2?
Example:
//Kohana 3.1 ; current uri = articles/show/10 (<controller>/<action>/<id>)
$this->request->uri(array('id' => 11)); // return 'articles/show/11'
Thanks
Since 3.2 there is no "short" way for this, because now $this->request->uri() returns current URI. Use $this->request->route()->uri() with all params you need:
$params = array('id' => 11); // what params you want to change
$params += $this->request->param(); // current request params
$params += array(
// note that $this->request->param() doesnt contain directory/controller/action values!
'directory' => $this->request->directory(),
'controller' => $this->request->controller(),
'action' => $this->request->action(),
);
$uri = $this->request->route()->uri($params);
Of course, you can create a special method for this (something like $this->request->old_uri(array('id' => 11))).
Here is an issue link for that API change.

Resources