This is just a quick response to http://me.veekun.com/blog/2012/07/28/quick-doesnt-mean-dirty/. I won't bother to write a proper blog post for this, so a Gist will have to do ;)
When I read that article, one thing really striked me: If you want to quickly create a web app in PHP, you do exactly the same. I mean, exactly.
I never used the Silex microframework before, so I took this as a chance to see how it works. I'll just do the same as eevee did, only with a bit less commentary (this is a Gist after all!)
I hope that this will show you that PHP and Python are really similar to work with. Also this should show that just because you're using PHP, doesn't mean that you write dirty code. The similarity in the process and code is really incredible :)
First create the project:
curl -s https://getcomposer.org/installer | php
php composer.phar create-project fabpot/silex-skeleton guestbook
cd guestbook/
Run php -S localhost:8888 -t web/
to start the webserver. You'll find a friendly Hello World message if you visit localhost:8888/index_dev.php
in your browser.
Then create a git repo:
rm -rf .git
git init
git add -A
git commit -m "Initial commit"
There are already two templates in the templates/ folder, we just modify them a bit to match eevee's code:
vim templates/layout.html
<!DOCTYPE html>
<html>
<head>
<title>{% block title '' %} - My Awesome Site</title>
<link href="{{ app.request.basepath }}/css/main.css" rel="stylesheet" type="text/css" />
</head>
<body>
<section id="content">
{% block content %}{% endblock %}
</section>
<footer id="footer">
My awesome guestbook
</footer>
</body>
</html>
vim index.html
{% extends "layout.html" %}
{% block title %}Guestbook{% endblock %}
{% block content %}
<h1>Guestbook</h1>
<p>Welcome to my guestbook!</p>
<ul class="guests">
<li>...</li>
</ul>
{% endblock %}
That doesn't give us much yet, we need to create some kind of database. To save me the installation of mysql I'll use sqlite:
vim src/app.php (addition)
<?php
$app['db'] = $app->share(function() {
$pdo = new PDO('sqlite:' . __DIR__ . '/../db.sq3');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $pdo;
});
Also create a console task to create the table structure (there is already a skeleton in the file, so I don't even have to look at docs):
vim src/console.php (change)
<?php
$console
->register('create-db')
->setDescription('Create database tables')
->setCode(function (InputInterface $input, OutputInterface $output) use ($app) {
$app['db']->query(
"CREATE TABLE guestbook (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
name TEXT, message TEXT
);
CREATE INDEX timestamp_index ON guestbook (timestamp);"
);
$output->writeln('Created database!');
})
;
Now we can create the DB using ./console create-db
.
Oh, and yeah, I hate ORMs, I prefer raw SQL.
Next let's modify the template to actually display something:
vim templates/index.html (change)
<ul class="guests">
{% for entry in entries %}
<li>
<blockquote>{{ entry.message }}</blockquote>
<p> —<cite>{{ entry.name }}</cite>, <time>{{ entry.timestamp }}</time></p>
</li>
{% endfor %}
</ul>
And adjust the controller for this:
vim src/app.php
<?php
$app->get('/', function () use ($app) {
return $app['twig']->render('index.html', array(
'entries' => $app['db']->query(
'SELECT * FROM guestbook ORDER BY timestamp DESC'
)
));
})
Finally, let's add the code for adding new guestbook entries:
vim templates/index.html
<hr>
<form action="" method="POST">
<p>Name: <input type="text" name="name"></p>
<p>Message: <textarea name="message" rows="10" cols="40"></textarea></p>
<p><button>Sign</button></p>
</form>
vim src/controllers.php
<?php
$app->post('/', function (Request $req) use ($app) {
$app['db']->prepare(
'INSERT INTO guestbook (name, message) VALUES (?, ?)'
)->execute(array(
$req->request->get('name') ?: 'Some dummy who forgot to leave a name',
$req->request->get('message') ?: 'WOW THIS IS THE BEST WEBSITE EVER',
));
return $app->redirect('/');
});
Again, you can see the page using the php -S localhost:8888 -t web/
webserver. It is safe against XSS and SQLi, just like the Python code (the template engine does automatic escaping and we used prepared statements).
I won't bother with deployment here. You could obviously just deploy to Heroku, exactly as you did with Python. Or just upload it to some freespace via FTP. Whatever.
=====
Thanks for listening,
~nikic (http://nikic.github.com/, https://twitter.com/nikita_ppv)
@damilare thanks again for your input. I'd love to see what can be accomplished and have a sense of the available dev tools so that I compare with what I already have. Any recommendations?