The Wiki Weekend Part 3: The Storage

Back to HTML WARDen.
-
The Wiki Weekend Part 1: Motivation and Other Wikis
-
The Wiki Weekend Part 2: The Page Editor Idea
-
The Wiki Weekend Part 3
You are here
-
The Wiki Weekend Part 4: Users, Locking
-
The Wiki Weekend Part 5: Finishing Touches, Conclusion
What do all three of the wikis mentioned in Part 1 have in common? They’re all written in PHP.
I tell anyone who will listen: Modern PHP is the best kind of boring software. In this era of bonkers complex web environments, PHP just works. I’m basically not interested in anything else on the server-side for making web sites at this point and I’m not kidding.
So that’s the language sorted.
Now how about data storage?
SQLite
SQLite is great software. Legendary stability. Available everywhere. Simple. Well-documented.
(SQLite is also one of the DB backends supported by MedaWiki.)
I was convinced that using SQLite would help me avoid all sorts of hard problems like file locking and storing metadata for my pages, etc.
Plus, I already had all of the scaffolding for making a simple site with SQLite and PHP in the form of my "family site" mini-social media thingy: Famsite (repo).
Also, I really like relational databases.
Great! So I got about halfway into Saturday evening with a single-table SQLite DB and just…ran out of steam.
Sigh.
I totally understand why people turn to ORMs (object–relational mappers) to manage a SQL DB from software. The sheer tedium of keeping the programmatic model of data in sync with the relational model, especially during the initial rapid development phase, is so bad. Who wouldn’t want to avoid that pain?
The problem with building with an ORM is that now you’re stuck with an ORM and, it’s kind of like what I was saying about WYSIWYG rich text editing (in Part 2), the extra layer is always going to let you down when things get complicated. ORMs often make easy things easy and hard things…really, really hard.
It’s a classic "now you have two problems" thing.
Anyway, every time I made a change to the schema, I had to change it in three places and wipe my DB and start over. Grrrr.
Of course, I could have made tooling to automate this, but then I’m making that, rather than this tiny wiki project. After all of my rapid progress, I was suddenly not having fun anymore.
And that’s with just one table!
I kept thinking, "If I were just writing files to disk, I would be done with this."
And then I remembered what my mission was: a tiny, purpose-build wiki for a specific use case. There isn’t going to be any file locking issues because the chances of two people editing the same page at the same time on this wiki are essentially zero. And even if that did somehow happen, a simple version-archiving scheme would save both copies.
That did it.
Text files win again!
Reluctantly at first, I stripped the DB code out. What a shame. A third of my time that day had been spent on the database.
But then I implemented saving a page as an HTML file and suddenly I wasn’t so sad anymore.
$ok = file_put_contents($fname, $page_body);
One line. ONE LINE!
Here’s the error handling:
if(!$ok){ return_error(500, 'Sorry, there was an error saving the page.'); }
Let’s add version archiving.
Here’s the entirety of that, error handling and all:
$ts = time(); # unix timestamp $archival_fname = "pages/archive/${ts}_${page_name}.html"; if(file_exists($fname)){ $ok = rename($fname, $archival_fname); if(!$ok){ return_error(500, 'Sorry, there was an error archiving the page.'); } }

Sorry, SQLite. You’re out. Defining my simple one-table schema alone was more work than that. Connecting to the DB with PHP’s PDO, preparing a statement, executing the statement, checking for errors. That stuff is pages of code. There’s just no comparison.
Plus, now I can just use diff
on the command line to compare versions of
pages. (I have no desire to build this functionality in the wiki interface
itself and my non-technical users would not use it even if I did.)
As an added bonus, now that my pages are HTML snippets stored as plain text
with a .html
extension, you can totally just open them up in the browser or a
text editor like any other static page. (It’s not completely valid, being a
snippet, but browsers are incredible at making a best guess.)
Rendering the page from a file is trivial in PHP:
$fname = "pages/${page_name}.html"; if(file_exists($fname)){ include $fname; }
Question: But what did you do about storing metadata along with the page body?
Answer: HTML is already structured data. As you’ll see in Part 4, I store stuff in the HTML document and it’s fine.
Onward, to The Wiki Weekend Part 4: Users, Locking!