Awful code I’ve written today
$row = $table->tr();
if(!($amIAltOrNot = !$amIAltOrNot))
{
$row->class = "alt";
}
// Edit: Much better now
$row = $table->tr();
$row->class = ($amIAltOrNot = !$amIAltOrNot) ? "" : "alt";
$row = $table->tr();
if(!($amIAltOrNot = !$amIAltOrNot))
{
$row->class = "alt";
}
// Edit: Much better now
$row = $table->tr();
$row->class = ($amIAltOrNot = !$amIAltOrNot) ? "" : "alt";
This website is now hosted on Slicehost (along with section99.net). It’s a little early to know how it will turn out, but so far I’m loving having not only a shell, but root access.
Signing up was completely painless and the the VPS was provisioned within minutes with several different operating system options (though I’m aware that this can sometimes take weeks depending on current capacity). While I run the bleeding edge version of Ubuntu at work, I opted for the slightly safer option, Ubuntu 6.06 LTS.
Setting up Lighty / PHP and Mysql took mere minutes thanks to apt-get and Debian’s sane default configuration. WordPress took a tiny bit of fiddling in Mysql so I could test it on another domain name, but aside from that, everything has been very painless.
I’m hoping that this gives me the chance to play with some webpy and even (maybe) some rails applications.
The only problem I’ve had (except for screwing up the DNS) is editing my crontab when loged in as a normal user. I’m unable to edit it due to a weird permission error. While it’s not a huge problem (root can edit anybodies crontab easily) but it’s odd that the only real information I can find is related to an old Debian bug.
Code
<?php
/*
PHP implementation of a common programming problem:
Reversing a singly linked list
*/
error_reporting(E_ALL | E_STRICT);
// This is our basic node
class WordNode
{
public $word;
public $nextNode;
public function __construct($word = null)
{
$this->word = $word;
}
// Print all content of this node, and linked nodes
public function __toString($separator = '')
{
$buffer = '';
$current = $this;
do
{
// Append the separator as long as there is a next node
$buffer .= $current->word . (($current->nextNode !== null) ? $separator : '');
}
while(($current = $current->nextNode) !== null);
return $buffer;
}
}
// Takes an array and turns it into a linked list
// (Remember this is purely an academic exercise :-)
function buildWordNodeList($sourceArray)
{
// First step create the linked list
$firstNode = new WordNode($sourceArray[0]);
$lastNode = $firstNode;
foreach(array_slice($sourceArray, 1) as $word)
{
$thisNode = new WordNode($word);
$lastNode->nextNode = $thisNode;
$lastNode = $thisNode;
}
return $firstNode;
}
// Inplace reverse
function reverseWordNodeListInplace(WordNode &$head)
{
// Init the loop by separating the top node, and
// keeping track of what is left ($tail)
$tail = $head->nextNode;
// This is set to null as it will end up being the
// last node and shouldn't point anywhere
$head->nextNode = null;
while($tail !== null)
{
// Take the next node, and seperate it, and again
// keep track of what's left
$next = $tail;
$tail = $next->nextNode;
// Now make this node the parent of the previous top node
$next->nextNode = $head;
// This node is now at the top
$head = $next;
}
}
$list = buildWordNodeList(array("a","b","c","d","e","f","g","h", "i", "j", "k"));
echo $list . "\n";
reverseWordNodeListInplace($list);
echo $list . "\n";
reverseWordNodeListInplace($list);
echo $list . "\n";
echo $list->__toString(" ") . "\n";
?>
Output
abcdefghijk
kjihgfedcba
abcdefghijk
a b c d e f g h i j k
I’m not allowed to complain about raiding any more.
Went to Zul’Aman a couple of weeks back, after a few tries took down the first boss, and then a couple of tries on the second boss, but things didn’t go so well (I kinda wiped the raid). Also did a Kara run with 7 guildies to one shot everything up to Curator (and then called it without attempting). Was pretty happy then about the guilds progress, alot of it is thanks to a > Kara geared tank who been organizing the guild raids.
This week after a fairly epic Kara run (just over six hours):
Just a little bit of an improvement over last time :-)
Can’t have a post about PHP at the top of the page for more that an couple of days. So on with the WoW gloating and moaning.
Stats are looking pretty good. Hit is suffering a little though (says someone who can count his Kara raids on one hand :-(
Overall, very happy with my mage… Just running out of things to aim for, there is one more item I want for badges, but I’m only 5 / 60 so far. I would really like to run Kara on a regular basis with a group of dedicated people, I don’t think it’s possible with this guild, and who on earth wants a Mage for Kara :-(
<?php
/*
Some hacked up code for Very Simple (Pretend) SQL Paramaters
-- For when you don't have PDO, or just can't be bothered
Examples:
>>> SQL("SELECT * FROM users WHERE id=? AND name LIKE ?", 123, '"123\"');
SELECT * FROM users WHERE id=123 AND name LIKE "\"123\\\""
>>> SQL("INSERT INTO user (nameFirst, nameLast) VALUES (?, ?)", "Fred", "Nurk");
INSERT INTO user (nameFirst, nameLast) VALUES ("Fred", "Nurk")
*/
function SQL($sql)
{
$params = func_get_args();
$params = array_map('mysql_real_escape_string', $params);
$sql = explode('?', $sql);
if(count($params) != (count($sql)-1))
{
throw new Exception(sprintf("Incorrect number of paramaters. Expected %d got %d", count($sql)-1, count($params)));
}
$newSql = '';
for($i = 0; $i < count($params); $i++)
{
$newSql .= $sql[$i] . (is_numeric($params[$i]) ? $params[$i] : '"' . $params[$i] . '"');
}
return $newSql . $sql[$i];
}
?>
Update: This is not only the wrong way to escaping, but introduces more bugs. Don’t ever use.
PHP version of the Python script located at http://decenturl.com/tools#api.
Update: Thanks to a quick update by Ben, DecentURL now returns valid JSON, so the quote workaround is no longer needed.
<?php
/*
PHP interface for the DecentUrl service
by Matthew D (project-2501.net)
Based on the Python script by Ben Hoyt
See http://decenturl.com/tools#api
Example:
<?php
require_once("decenturl_interface.php");
// returns: "youtube/medieval-helpdesk-with-english"
DecentUrl::Get('http://youtube.com/watch?v=pQHX-SjgQvQ');
// returns: "http://youtube.com/watch?v=pQHX-SjgQvQ"
DecentUrl::Resolve('youtube/medieval-helpdesk-with-english');
// returns: array("DecentURL - Making ugly URLs decent", "making-ugly-urls-decent")
DecentUrl::Title('http://decenturl.com/');
// returns: "brush.co.nz"
DecentUrl::Domain('http://brush.co.nz');
// throws a DecentUrlException("resolve request failed: notfound")
DecentUrl::Resolve('baddy');
?>
*/
class DecentUrlException extends Exception {}
class DecentUrl
{
const BASE_URL = 'http://decenturl.com/api-';
// Create or get decent URL from given ugly one and return it
public static function Get($url, $title="")
{
$response = self::Request("get", array("u" => $url, "t" => $title), 2);
return $response[0];
}
// Resolve decent URL and return ugly original
public static function Resolve($decentUrl)
{
$response = self::Request("resolve", array("d" => $decentUrl), 2);
return $response[0];
}
// Return tuple of full <title> and decent title for given URL
public static function Title($url, $maxLength = 1000)
{
return self::Request("title", array("u" => $url, "l" => $maxLength), 2);
}
// Return URL's base domain
public static function Domain($url, $maxLength = 1000)
{
$response = self::Request("domain", array("u" => $url, "l" => $maxLength), 1);
return $response[0];
}
// Call generic DecentUul API function, throw DecentUrlException if not ok
private static function Request($type, $parameters, $expectedResponseSize = false)
{
// Take a key value pair, and join them together, making sure to
// urlencode the value
foreach($parameters as $key => $value)
{
$parameters[$key] = sprintf("%s=%s", $key, urlencode($value));
}
$queryString = implode("&", array_values($parameters));
$url = sprintf("%s%s?%s", self::BASE_URL, $type, $queryString);
$contents = file_get_contents($url);
$response = json_decode($contents);
if($response == null)
{
throw new DecentUrlException("Response was not valid JSON");
}
if($response[0] != "ok")
{
throw new DecentUrlException("{$type} request failed: {$response[0]}");
}
// Remove the first element (which we proved was 'ok' above)
$trimedResponse = array_slice($response, 1);
// If requested, we check to see that the response is the correct
// size.
if(($expectedResponseSize !== false) && (count($trimedResponse) != $expectedResponseSize))
{
throw new DecentUrlException("{$type} request failed: expected {$expectedResponseSize} fields, got " . count($trimedResponse));
}
return $trimedResponse;
}
}
?>
Yep, another WoW post.
Future Upgrades
November 21st Update
I’m not even going to mention Kara today. As good as my current guild is, I’m seriously thinking about moving (but then again, no one really wants a level 70 mage)
Articles on why PHP sucks are fairly common (PHP is a really easy target). So rather than repeat what’s already been said (lack of namespaces, function naming, and argument positions, etc), I though I’d try and come up some more obscure ‘features’ and ‘bugs’ in PHP that I hate.
// Actually creates a new named function, in the global namespace every
// time it's called, even if it's called with the exact same arguments.
// Syntax is pretty bad too, need to pay close attention to quoting strings
$args = '$r';
$body = 'return $r;'
$f1 = create_function($args, $body);
$f2 = create_function($args, $body);
// Displays false
var_dump($f1 == $f2);
Automatic creation of class members
// This should throw a E_NOTICE, or E_STRICT (though I do believe that PHP needs a
// way to add members, as it is sometimes is useful. Maybe allow it on stdclass,
// and not user defined classes?)
// Completely valid code
$foo = new stdClass();
$foo->bar = "abc"
// You can take this one step further (still valid PHP)
$bar->xyzzy = "abc";
echo $bar->xyzzy;
Scope, wonderful scope
$numbers = array(1,2,3);
foreach($numbers as $number)
{
echo $number . "\n";
}
// This should throw a error notice of Undefined variable
// instead is prints 3
echo $number . "\n";
extract() works in a similar method to register.globals, while it’s safer (you can make sure it never overwrites existing variables) it still is a really bad idea.
class aParent
{
static $phrase = "Goodbye";
public static function SayHello()
{
printf("%s %s from class %s\n", self::$phrase, self::GetWorld(), get_class());
}
public static function GetWorld()
{
return "Universe";
}
}
class aChild extends aParent
{
static $phrase = "Hello";
public static function GetWorld()
{
return "World";
}
}
// All good here...
// Displays: 'Goodbye Universe from class aParent'
// Should display: 'Goodbye Universe from class aParent'
aParent::SayHello();
// Not so good here though...
// Displays: 'Goodbye Universe from class aParent'
// Should display: 'Hello World from class aChild'
aChild::SayHello();
Wow, almost two weeks since my last WoW post. In short: