Migrating from WordPress to CakePHP
Posted by Felix Geisendörfer, on Sep 24, 2007 - in PHP & CakePHP » Other
Hey folks,
I'm currently working on migrating my blog from WordPress to a light-weight CakePHP replacement that I hope to enhance and customize to my liking easily in future. Its not like WordPress has treated me badly, if it wasn't around I'd probably never have started this blog and never gotten to where I am right now. While I'm giving out kudos, I'd also like to mention that you, the readers of this blog have been an amazingly good audience by sharing your knowledge and opinions on PHP programming with me, while also being very encouraging about the whole thing. I really feel bad when I don't get to blog, so time to do it again : ).
In this post I'm simply going to throw out some snippets to show how I'm currently approaching the whole process in order to give both my insight into what works and what doesn't, while also hoping to get some people to share their insight into migrating legacy apps to CakePHP.
So one of the first things I started was to do a new layout and come up with the visual screen elements that I want to integrate. The next thing I did (and still am doing) is to start a little migration script using the new Cake 1.2 console to get my data moved in the new db schema. I haven't finalized the new schema yet and kind of make it up as I go, run a migration and then implement the functionality to show the data currently available. So far I've been working on migrating the wp_posts and wp_comments table. The first thing that hit me was that WordPress is not good about conventions. For example the primary key on my wp_posts table is 'ID' while it is 'comment_ID' on the comments table. I soon realized that one of the biggest tasks would be to map old Wp table fields to ones that have different names in my new CakePHP blog. But before I go in too much detail, I'll paste the migration script I currently have and then explain it a little further:
-
-
uses('model'.DS.'model');
-
class WpMigrationShell extends Shell {
-
'WpPost'
-
, 'WpComment'
-
);
-
-
-
function initialize() {
-
parent::initialize();
-
}
-
-
function main() {
-
$this->out('Migrating WordPress posts ...');
-
$this->WpPost->migrate();
-
$this->out('Migrating WordPress comments ...');
-
$this->WpComment->migrate();
-
-
$this->out('Populating WordPress posts counter cache ...');
-
$this->WpPost->populateCounterCache();
-
-
-
-
$this->hr();
-
$this->out('Migration took '.$duration.' seconds.');
-
}
-
}
-
-
class WpMigrationModel extends Model{
-
var $useDbConfig = 'wordpress';
-
var $newModel = null;
-
-
function migrate() {
-
}
-
-
loadModel($this->newModel);
-
$Model = new $this->newModel();
-
$Model->execute('TRUNCATE '.$Model->table);
-
-
$idKey = $keys[0];
-
-
$oldEntries = $this->findAll(null, $keys);
-
foreach ($oldEntries as $oldEntry) {
-
if (!$this->filter($oldEntry[$this->name])) {
-
continue;
-
}
-
$id = $oldEntry[$this->name][$idKey];
-
$Model->create();
-
foreach ($this->map as $oldField => $newField) {
-
$value = $oldEntry[$this->name][$oldField];
-
$migrateFct = 'migrate'.Inflector::camelize($newField);
-
$value = $this->{$migrateFct}($value);
-
}
-
$Model->set($newField, $value);
-
}
-
if (!$Model->save()) {
-
}
-
}
-
}
-
-
function filter() {
-
return true;
-
}
-
-
function migrateText($text) {
-
}
-
}
-
-
class WpPost extends WpMigrationModel{
-
var $useTable = 'posts';
-
'ID' => 'id'
-
, 'post_title' => 'title'
-
, 'post_content' => 'text'
-
, 'post_status' => 'published'
-
);
-
-
function populateCounterCache() {
-
$Post = new Post();
-
$Post->recursive = -1;
-
$Post->Comment->recursive = -1;
-
-
foreach ($posts as $post) {
-
$Post->set($post);
-
if ($comment_count) {
-
$Post->save();
-
}
-
}
-
}
-
-
function filter($item) {
-
return false;
-
}
-
return true;
-
}
-
-
function migratePublished($value) {
-
if ($value == 'publish') {
-
return true;
-
}
-
-
return false;
-
}
-
}
-
-
class WpComment extends WpMigrationModel{
-
var $useTable = 'comments';
-
'comment_ID' => 'id'
-
, 'comment_post_ID' => 'post_id'
-
, 'comment_author' => 'author_name'
-
, 'comment_author_email' => 'author_email'
-
, 'comment_author_url' => 'author_url'
-
, 'comment_content' => 'text'
-
);
-
-
function filter($item) {
-
static $Post;
-
$Post = new Post();
-
}
-
-
$Post->set('id', $item['comment_post_ID']);
-
return $Post->exists();
-
}
-
-
function migrateAuthorName($name){
-
}
-
}
-
Alright there is quite some stuff going on here so let me begin with the basics. I've decided to give all WordPress tables their own model which I prefix with 'Wp' to not overlap with the models I'm using in the new CakePHP application. Those 'Wp' models all extend a common base model which I call the WpMigrationModel. This is because I found that a lot of functionality is shared across them, especially things like mapping old 'Wp' fields to new fields for my CakePHP models as well as filtering out items I'm not interested anymore. All of this is happening in the WpMigrationModel::migrate. Another neat thing I built in is that while the algorithm loops through the fields of my new cake models, it also looks for a function
Anyway, this of course is just the beginning, but its already most of the data I'm really interested in migrating - I don't mind loosing a couple meta / whatever fields. In a next post I'll show how to replicate some legacy WordPress logic in my new cake blog. For now I've got to stop as my plane to San Francisco from the Atlanta airport is boarding ; ).
-- Felix Geisendörfer aka the_undefined
PS: Typos may be corrected when I get wifi again ; ).