Release vlualogger 1.1
TweetWed, Jan 12, 2011 01:38 PM
Also see my original post about vlualogger.
query = *( pchar / "/" / "?" )where pchar is defined as:
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"and finally, sub-delims is defined as:
sub-delims = "!" / "$" / "&" / "'" / "(" / ")" /That is RFC talk for "A query string can have an un-encoded comma in it as a delimiter." So, in Phorum we have URLs like http://www.phorum.org/phorum5/read.php?61,145041,145045. That is the post in Phorum talking about Facebook's problem. It is a valid URL. The commas do not need to be escaped. They are delimiters much like an & would be in a traditional URL. So, what happens when you share this URL on Facebook? Well, a share link would look like http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.phorum.org%2Fphorum5%2Fread.php%3F61%2C146887%2C146887. If I go to that share page and then look in my Apache logs I see this:
"*" / "+" / "," / ";" / "="
66.220.149.247 - - [18/Nov/2010:00:47:51 -0600] "GET /phorum5/read.php?61%2C146887%2C146887 HTTP/1.1" 302 26 "-" "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)"Facebook sent %2C instead of comma? It decoded the other stuff in the URL. The slashes, the question mark, all of it. So, what is their deal with commas? Well, maybe I can hack Facebook and not send an encoded URL to the share page. Nope, same thing. So, they are proactively encoding commas in URL's query strings.
$res = $db->query($sql, MYSQLI_USE_RESULT);But, I quickly found out that this does not work. For some reason, this is not supported. fetch_all only works with the default which is MYSQLI_STORE_RESULT. I filed a bug which was marked bogus. Which I put back to new because I really don't see a reason this should not work other than a complete oversight by the mysqlnd developers. So, I started doing some tests in hopes I could show the developers how much faster using MYSQLI_USE_RESULT could be. What happened next was not expected. I ended up benchmarking several different options for fetching all the rows of a result into an array.
$rows = $res->fetch_all(MYSQLI_ASSOC);
<?phpThe above code should generate:
$mc = new Memcached();
$mc->addServer("localhost", 11211);
$mc->set(123, "yes!");
var_dump($mc->getMulti(array(123)));
?>
array(1) {But, in reality, it generates:
[123]=>
string(4) "yes!"
}
bool(false)The set succeeds, but the getMulti fails. Again, this is being fixed in GitHub, but is not available for release on PECL.
<?phpNow you can include the publications.php file and have a global variable named $PUBLICATIONS that holds the publication settings. But, how do we load a single publication without knowing numeric ids? Well, you could make some constants.
$sql = "select * from publications";
$res = $mysqli->query($sql);
while($row = $res->fetch_assoc()){
$pubs[$row["publication_id"]] = $row;
}
$pubs_ser = str_replace("'", "\\'", serialize($pubs));
$php_code = "<?php global \$PUBLICATIONS; \$PUBLICATIONS = unserialize('$pubs_ser'); ?>";
file_put_contents("/some/path/publications.php", $php_code);
?>
<?phpSo, now, we have constants. We can do stuff like:
$sql = "select * from publications";
$res = $mysqli->query($sql);
while($row = $res->fetch_assoc()){
$pubs[$row["publication_id"]] = $row;
$constants[$row["publication_id"]] = strtoupper($row["name"]);
}
$pubs_ser = str_replace("'", "\\'", serialize($pubs));
$php_code = "<?php\n";
$php_code.= "global \$PUBLICATIONS;\n";
$php_code.= "\$PUBLICATIONS = unserialize('$pubs_ser');\n";
foreach($constants as $id=>$const){
$php_code.= "define('$const', $id);\n";
}
$php_code.= "?>";
file_put_contents("/some/path/publications.php", $php_code);
?>
<?phpBut, how about autoloading? It would be nice if I could just autoload the constants.
//load a publication
require_once "publications.php";
echo $PUBLICATIONS[DEALNEWS]["name"];
?>
<?phpThen we create a class in our autoloading directory that extends that object.
$sql = "select * from publications";
$res = $mysqli->query($sql);
while($row = $res->fetch_assoc()){
$pubs[$row["publication_id"]] = $row;
$constants[$row["publication_id"]] = strtoupper($row["name"]);
}
$pubs_ser = str_replace("'", "\\'", serialize($pubs));
$php_code = "<?php\n";
$php_code.= "class PUB_DATA {\n";
foreach($constants as $id=>$const){
$php_code.= " const $const = $id;\n";
}
$php_code.= " protected \$pubs_ser = '$pubs_ser';\n";
$php_code.= "}";
$php_code.= "?>";
file_put_contents("/some/path/pub_data.php", $php_code);
?>
<?phpGreat, now we can do things like:
require_once "pub_data.php";
class Publication extends PUB_DATA {
private $pub;
public function __construct($pub_id) {
$pubs = unserialize($this->pubs_ser);
$this->pub = $pubs[$pub_id];
}
public function __get($var) {
if(isset($this->pub[$var])){
return $this->pub[$var];
} else {
// Exception
}
}
}
?>
$pub = new Publication(Publication::DEALNEWS);The only problem that remains is dealing with getting the generated code to all your servers. We use rsync. It works quite well. You may have a different solution for your team. Back when we ran our own in house ad server we did all the ad work this way. None of the ad calls ever hit the database to get ads. We stored stats on disk in logs and processed them on a schedule. It was a very solid solution.
echo $pub->name;