Dec 15 2008

Keeping database.yml dry

That would be dry as in Don’t Repeat Yourself

defaults: &defaults
adapter: mysql
encoding: utf8
username: root
password: root
#Wherever mysqld.sock is located
socket: /opt/local/var/run/mysql5/mysqld.sock

development:
database: blog_development
<<: *defaults

test:
database: blog_test
<<: *defaults

production:
database: blog_production
<<: *defaults


Dec 13 2008

Caveat Emptor

So there is this new site on the internet called swoopo that is essentially a combination of ebay and a slot machine [1]. It seems harmless enough to begin with, until you actually go and look at how it works. But first, lets look at some previous bids that have taken place.

swoopo

If you dont want to click on that, some of the interesting things that you might see are:

Wii Fit | Nintendo WiiFit + Balance Board Original Price:  89.99 Auction Price: 80.40 Saving: 0%

Asus Eee PC 1000 10”… Original Price: 699.99 Auction Price: 338.85 Saving: 14%

You may be wondering if their math is wrong… no it isn’t, and no I did not make these numbers up, nor did I photoshop them into the picture, you can go look for yourself if you want. You may now be wondering how a 700 dollar item, sold for less than half of what it is worth gives you a 14% saving. Well, that is because of the way that their site works:

  1. Bidding on our auctions starts at just 15c, with no reserve prices.
  2. The price only goes up by 15c with each bid placed.
  3. If a bid gets placed in the final moments, we extend the auction by up to 20 seconds.
  4. There’s a small charge [75 cents] for each bid placed: this helps us offer you such amazing bargains.

 

Amazing bargins indeed. The problem is that they only appear to be such amazing bargins at the time, until you see how much you actually spent on an item. If each bid costs you 75 cents, they only need for there to be 933.32 bids to break even… well if they were giving the item away for free. That is generally not the case, so it is in reality an 85 cent bid, which means that they only need to get 823.5 bids to break even. Which would put the price of the item at around: 123.52. So, on the 700 dollar item they actually made quite a bit of money, 1333.11 dollars (or there abouts). The other problem with this is that every time that someone bids, the ‘auction’ gets an additional 10-20 seconds added on to its time, this gives everyone else extra time to outbid you, meaning more money for swoopo.

The only way to beat them it seems, is not to play.

0807argames


Oct 22 2008

Making isset Recursive

At work I was told to add in the magic method __isset() (which is technically done by overloading the function…). Essentially it lets you call isset() on private and protected variables in your classes:

 
/**  As of PHP 5.1.0  */
 
class MyClass{
 
private $private;
 
public $public;
 
protected $protected;
 
public function __isset($name) {
        echo "Is '$name' set? ";
        return isset($this->name);
    }
 
}
 
$myClass = new MyClass();
 
echo isset($myClass->private); #Is 'private' set? false
 
echo isset($myClass->protected); #Is 'protected' set? false
 
echo isset($myClass->public); #false

This function will be called whenever the variable is unreachable by a normal isset call (private and protected variables)

Nice and easy if you know exactly what you want. Unfortunately sometimes people have the habit of adding underscores to the start of their variables, but not always. So to make this work, I decided it would be a good idea to make it check to see if the variable was there, or if maybe there should have been an underscore at the begining. So it became:

 
/**  As of PHP 5.1.0  */
 
class MyClass{
 
private $_private;
 
public $public;
 
protected $protected;
 
public function __isset($name) {
    if(isset($this-&gt;$name)){
        return true;
    }
 
    $name = "_".$name;
        return isset($this->$name);
    }
 
}
 
$myClass = new MyClass();
 
echo isset($myClass->_private); #Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 134136 bytes) in isset_r.php on line 20

Curious, so I changed it a bit to see what was actually happening in there…

__private___private____private_____private______private_______private________private_________private

__________private___________private____________private_____________private______________private___

____________private________________private_________________private__________________private______

_____________private____________________private_____________________private______________________

private_______________________private________________________private_________________________priv

ate__________________________private___________________________private__________________________

__private_____________________________private______________________________private_______________

________________private________________________________private_________________________________

private__________________________________private___________________________________private______

______________________________private_____________________________________private______________

________________________private_______________________________________private__________________

______________________private_________________________________________private__________________

________________________private___________________________________________private______________

______________________________private_____________________________________________private______

________________________________________private_______________________________________________

private________________________________________________private

Fun stuf… the lesson is: name things a standard way and you are good to go, if you don’t it will screw things up royally (but it might make a pretty design).


Sep 28 2008

A look at PostgreSQL

Almost all last week at work I was working on adding Postgres to the database interfacing part of our php framework. The more I worked on it and did research to figure out why things were the way that they were and why certain things didn’t work the same way as I thought, because of my limited knowledge of databases other than MySQL and a bit of Oracle, they should, the more that I liked this database backend (side note: why doesn’t chrome have an add to dictionary option when right click on something you ‘misspelled’?). It is not that one is definitively better than the other, it is just a different way of tackling the same problems (well… in my case they are pretty much the same problems…).

For the most part, simple queries that you would write are the exact same:

SELECT * FROM my_table WHERE my_column = 'something'

This will of course return all of the things in the database where my_column = ’something’, nice and simple.

Problems sometimes arise however when you want to do more complex things. For example if you want to delete everything from two tables where one column is the same as the other:

In MySQL, easy:

DELETE table1.*, table2.* FROM table1, table2 WHERE table1.column1 = table2.column1

In Postgres, it is easy as well, but different:

(Downloading and installing Postgres so I don’t mess this up… that would be embarrassing…)

CREATE TEMPORARY TABLE mytmptable(column1 text);
INSERT INTO mytemptable(SELECT table1.column1 FROM table1, table2 WHERE table1.column1 = table2.column1);
DELETE FROM table1 WHERE table1.column1 IN (SELECT * FROM mytemptable);
DELETE FROM table2 WHERE table2.column1 IN (SELECT * FROM mytemptable);

You could do the delete in a similar way to that in MySQL, but you probably wouldn’t because the other way is simpler. It is more dangerous though because of the possibility to delete everything in your tables while you are testing by accident if you miswrite the query.

Fortunately not everything is more complicated in Postgres, for example you can do:

DELETE FROM table1 WHERE column1 IN (SELECT column1 FROM table2 WHERE column1 LIKE 'some text' LIMIT 10 OFFSET 2)

and it will have no trouble deleting things from your tables. In MySQL you cannot do this because of the way that MySQL queries the tables when it uses LIMIT and OFFSET (apparently). What you have to do is this:

CREATE TEMPORARY TABLE mytemptable(column1 text);
INSERT INTO mytemptable(SELECT column1 FROM table2 WHERE column1 LIKE 'some text' LIMIT 10 OFFSET 2);
DELETE FROM table1 WHERE column1 IN (SELECT column1 FROM mytemptable)

This makes postgres a more attractive option to me… if only it supported

CREATE TABLE IF NOT EXISTS ...


Sep 3 2008

For best viewing, use chrome

As you should know, Chrome was released last night at 12 am GMT. It was announced 2 days ago much to the surprise of most (though there were rumours, there was no actual proof of its existence). Many people have now taken the plunge, downloaded it, and tried it out.

My experiences have been almost completely without problem. There was a small problem on grooveshark.com where I could not use the spacebar in flash, but that could have been flash acting up instead of Chrome. I just tried it out again, I think it is Chrome, good thing there is a bug report link built in so I don’t forget to report it this time. ;)

Oh ya, and for websites that use a lot of javascript, there currently is nothing faster (could be because you [I] have extensions for firefox running, which need to be processed as the pages load). Oh… and the Wordpress backend is wicked fast now (thanks to Chromes speed and the new “Turbo” feature that uses google gears incorporated into Wordpress’ backend).

Sorry Gavin and co, it is only available for Windows for now :P