Implementing Iterator in PHP 5

Double quote marks There's a good article on sharepoint about implementing Iterator in PHP 5. Double quote marks

There’s a good article on sharepoint about implementing Iterator in PHP 5: http://www.sitepoint.com/article/php5-standard-library/1. I’ve used it a couple of times now and it’s a great way to treat objects as collections.

More info about the Standard PHP Library can be found here..

MySQL load data infile and foreign key constraints

Double quote marks I’ve been up against a(nother) MySQL 4/PHP 5 ‘not doing all I want it to’ type problem. This time, it involved trying to do a bulk update on potentially tens of thousands of lines. Now, I don’t want to do an INSERT for each line and I’ve already written some classes to handle outputting data objects into csv files [...] Double quote marks

I’ve been up against a(nother) MySQL 4/PHP 5 ‘not doing all I want it
to’ type problem. This time, it involved trying to do a bulk update on
potentially tens of thousands of lines. Now, I don’t want to do an
INSERT for each line and I’ve already written some classes to handle
outputting data objects into csv files which handles all of the primary
keys. There’s an option with LOAD DATA INFILE to REPLACE values where
primary key conflicts would occur so I thought if I used that with
existing rows then I should be okay.

What I have found, though, is that LOAD DATA INFILE with REPLACE appears
to try to delete the row and then re-insert it. This breaks other
foreign constraints and so the database engine won’t let it. Fair
enough, but it would have been nice if the manual mentioned it.

So: next step is to disable the foreign keys temporarily with SET
FOREIGN_KEY_CHECKS=0. From the command line this works fine, but it
seems that within PHP the foreign key checks are re-enabled
automatically after each command is run, which means the net result of
running SET FOREIGN_KEY_CHECKS=0 is absolutely nothing. So when I try
and to the LOAD DATA INFILE the constraints are still there and it
doesn’t work.

If we trusted MySQL 5 fully yet (and wanted to go through the pain of
installing it) I could probably write a stored procedure, with whatever
headaches that would bring, but as it is I’m stuck with MySQL 4 for the
moment. The solution I’ve come up with is to write the SQL query to a
text file and then use an exec() command from within PHP to execute the
commands in the file. I don’t like it, and it doesn’t feel very
portable, but it seems to work. In fact, it seems so handy that I’ve
created a static method so I can do it with any batch of SQL queries.

The handy class follows (with constants in place of the database
names/connection values/temporary folder):

public static function multipleDbQueries($sql)
{
 $file = fopen(TEMP_CSV_LOCATION .
  "temp_query.sql","a+");
 fwrite($file,$sql);
 fclose($file);
 exec("mysql -u " . DB_USERNAME .
  " --password=='" . DB_PASSWORD .
  "' " . DB_NAME . " < "
  . TEMP_CSV_LOCATION . "temp_query.sql");
}

PHP 5 garbage collection

Double quote marks The object-oriented features of PHP 5 are a really positive step forward for the language. One of the biggest improvements, to my mind, is that you no longer have to choose to pass things around by reference with a liberal smattering of '&' symbols: references are now the default way of passing objects. Double quote marks

The object-oriented features of PHP 5 are a really positive step forward for the language. One of the biggest improvements, to my mind, is that you no longer have to choose to pass things around by reference with a liberal smattering of ‘&’ symbols: references are now the default way of passing objects. One problem I have come across, though, is that the reference counting feature of PHP’s garbage collection (http://www.zend.com/zend/art/ref-count.php) means that objects with mutual references are not deleted even when I thought the object was out of existence. E.g:

class ParentObject()
{
protected $childObject;

function __construct()
{
$this->childObject = new ChildObject($this);
}
}

class ChildObject()
{
protected $parentObject;

//Pass in a reference to the parent
//object and store it internally
function __construct($parentObject)
{
$this->parentObject = $parentObject;
}
}

Then if I call $foo = new ParentObject(); then it automatically creates a child object with a reference to the parent. The parent also keeps a reference to its child. If I then unset($foo); the two objects are still referencing each other and so are not deleted. The only way I’ve found to clear this is to create a new method (which I call destroy()) to delete references to the child. Calling destroy() on the parent first calls destroy() on its child, which dereferences the parent, and then the parent dereferences the child. So the classes are now:

class ParentObject()
{
protected $childObject;

function __construct()
{
$this->childObject = new ChildObject($this);
}

public function destroy()
{
$this->childObject->destroy();
unset($this->childObject);
}
}

class ChildObject()
{
protected $parentObject;

//Pass in a reference to the parent object
//and store it internally
function __construct($parentObject)
{
$this->parentObject = $parentObject;
}

public function destroy()
{
unset($this->parentObject);
}
}

And I have to call

$foo->destroy();
unset($foo);

To clear the thing out completely. This can cause a number of problems which I won’t go into in detail here (they occur in more complex design patterns), but suffice to say that there are a number of occassions where I don’t necessarily want to destroy a child at the same time as a parent, or vice-versa. E.g. a child references multiple parents. The end result is that I’m writing code to deal with garbage collection where it is having a big effect on memory and just leaving it out where it doesn’t seem to make as much difference. This suffices for a known set of data but doesn’t feel very satisfactory in terms of future-proofing. I would appreciate it if anyone else has a better way of doing things.