PHP vs. Node.js

TL;DR: PHP is not going to disappear immediately, but its positions are undermined even further by the nascent Node.js.

When the Internet exploded in the 2000s, PHP was a thing all the cool kids did. It was extremely revolutionary, because:

  • It was an interpreted language unlike C++ or Java which require the source code compilation
  • It had the ability to be used directly with HTML by mixing within its template files with a <%php ... %> markup tags
  • It had cheap shared hosting providers on Apache servers with a Linux, Apache, MySQL and PHP (LAMP) stack
  • It had a functional nature which is easier to learn than the object-oriented programming

Over the years, PHP and its apps became a monstrous technology vulnerable to security threats (e.g., SQL injections), lack of a centralized packaging registry (was Composer inspired by Node Package Manager?), inconsistent API and subpar performance. There are many better alternatives to PHP, e.g., Ruby on Rails and Django, however nothing is as approachable as Node.js.

For those of you who aren’t familiar with Node.js, or who have heard of it but can’t quite grasp the concept, here is my analogy:

Node.js is functionally similar to the PHP + Apache or ASP + IIS stacks.

Nowadays, Node.js is gaining momentum. The platform uses JavaScript. It’s functional, and its non-blocking I/O mechanism allows for a better performance. Node.js comes with a robust Node Package Manager solution and the specification, i.e., ECMAScript.

Because Node.js is a lower-level technology, it is not comparable to complex frameworks like Struts, Rails or Django directly.

Therefore, many people, whether software engineers or entrepreneurs, are often faced with the decision of “What tech stack to use” In this article PHP vs. Node.js, we’ll compare apples-to-apples approaching the question from different angles, such as:

  • Syntax
  • Context switch
  • Modules
  • Ecosystem
  • Frameworks
  • Real-time apps
  • Database apps
  • Third-party services apps
  • Web servers
  • Hosting
  • Performance

Continue reading “PHP vs. Node.js”

openList.co – Ad Classified Website Application

With openList.co you could have your own ad classified website set up in minutes. It comes with minimalistic Cragislist.org-like theme which provides unobstructive UI/UX.

Download

Quick Look

openList Home Page
openList Home Page
openList.co Category View
openList.co Category View

Features

  • Custom fields for ad categories like real estate, for sale etc.
  • Email verification and ad manager for deletion/editing
  • Ad flagging ie spam, like, violation, etc
  • Minimalistic design and use of templates ease customization
  • HTML filter, Captcha and WYSIWYG editor
  • clean URLs
  • photo upload
  • nested categories

Requirements

PHP5 or higher with GD support for Captcha, MySQL, access to .htaccess file.

Installation

  1. Download application as zip package or clone from GitHub repo (azat-co/openlist).

  2. Start your favorite local web server (e.g. MAMP) and MySQL database. Point localhost to your folder or change class/config.php file with a new host name, aka SITE_URL, more info below.

  3. Modify class/systemconsts.class.php file with your database parameters. By default they’re:

    const DB='test',
    HOST='localhost',
    DSN='mysql:dbname=test;host=localhost',
    USERNAME='root',
    PASSWORD='root';
    
  4. OPTIONAL: modify class/config.php file such parameters as language (English or Russian), numbers of ads/posts per page, number of days after which ad/post will expire, photo size limit, website URL, path to templates, etc.

  5. Run install.php by going to SITE_URL/install.php or localhost/install.php.

  6. View application at localhost or your custom host name (it will be pre-populated with data).

Customization

  • class/config.php – global constants.
  • class/systemconsts.class.php – database parameters.
  • install.php – initial data, e.g. cities, categories, custom fields, etc.
  • tpl/*.tpl.php – Savant3 templates (basically just PHP), aka “view” in MVC architecture.
  • class/model.class.php – “model” layer of MVC architecture, it uses PDO library.
  • class/service.class.php – business logic layer.
  • index.php and htaccess – “controller” layer of MVC architecture.

To change cities, categories and other data just modify SQL statements in install.php or edit your database with phpMyAdmin.

Libraries

Those dependencies are already included in the package/repository. You could use newer version at your own risk.

  • Slightly modified PHP template engine Savant3 – the backbone of application MVC architecture.
  • JavaScript and HTML WYSIWYG client-side editor TinyMCE for new rich text editor.
  • PHP HTML filter HTML Purifier for cleaning malicious user input.
  • PHP Captcha script Securimage

Deployment of Static Files to Heroku

If you use Ruby on Rails, Django or NodeJS frameworks on the same domains they have special folders, usually called static, public or assets. But what if you what deploy just “static” file which are usually not so static, by they way.

Heroku uses Cedar stack as an application creation tool and it doesn’t support flat-out deployment of static files such as HTML, CSS or JavaScript, unless they come with some server-side language, e.g, PHP, Ruby, Python. This might come in handy if you are using front-end applications build with jQuery or BackboneJS framework and services like Parse.com or Firebase.com or consume your own back-end deployed as a different application on different instance and/or domain.

There are multiple ways to trick Heroku and Cedar into thinking that your HTML, CSS and JavaScript files are PHP or Ruby on Rails, or any other legitimate Cedar stack, applications. Here is the simplest way is to create index.php file in your project folder, on the same level as your .git folder. You can do this in terminal with this command:

$ touch index.php

Then we turn off PHP with .htaccess directive. You can add line to .htaccess and create it with this terminal command:

$ echo 'php_flag engine off' > .htaccess

This two terminal command will create empty index.php file and .htaccess file which turns PHP off. This solution was discovered by Kenneth Reitz.

Another approach is less elegant but also involves PHP. Create file index.php on the same level as index.html in the project folder which you would like to publish/deploy to Heroku with the following content:

<?php echo file_get_contents('index.html'); ?>

Third way is to use Ruby and Ruby Bamboo stack. In this case, we would need the following structure:

 -project folder
    config.ru
   /public
      index.html
      /css
      app.js
      ...

The path in index.html to CSS and other assets should be relative. i.e. ‘css/style.css’. The config.ru file should contain the following code:

use Rack::Static, 
  :urls => ["/stylesheets", "/images"],
  :root => "public"

run lambda { |env|
  [
    200, 
    {
      'Content-Type'  => 'text/html', 
      'Cache-Control' => 'public, max-age=86400' 
    },
    File.open('public/index.html', File::RDONLY)
  ]
}

For more details, you could refer to official Bamboo Heroku documentation.

Last but not least, for Python and Django developers, you could add following to your urls.py:

urlpatterns += patterns(”, (r’^static/(?P.*)$’, ‘django.views.static.serve’, {‘document_root’: settings.STATIC_ROOT}),)

Or with this Procfile line:

web: python my_django_app/manage.py collectstatic --noinput; bin/gunicorn_django --workers=4 --bind=0.0.0.0:$PORT my_django_app/settings.py 

The full Django post is at Managing Django Static Files on Heroku.

If you use NodeJS, here is how to write your own server:

var http = require("http"),
url = require("url"),
path = require("path"),
fs = require("fs")
port = process.argv[2] || 8888;

http.createServer(function(request, response) {

  var uri = url.parse(request.url).pathname
    , filename = path.join(process.cwd(), uri);

  path.exists(filename, function(exists) {
    if(!exists) {
      response.writeHead(404, {"Content-Type": "text/plain"});
      response.write("404 Not Found\n");
      response.end();
      return;
    }

    if (fs.statSync(filename).isDirectory()) filename += '/index.html';

    fs.readFile(filename, "binary", function(err, file) {
      if(err) {        
        response.writeHead(500, {"Content-Type": "text/plain"});
        response.write(err + "\n");
        response.end();
        return;
      }

      response.writeHead(200);
      response.write(file, "binary");
      response.end();
    });
  });
}).listen(parseInt(port, 10));

console.log("Static file server running at\n  => http://localhost:" + port + "/\nCTRL + C to shutdown");

Force Download Dialog on XML (or any other) File Type

Strangely, but Chrome browser doesn’t have build-in support to display XML in a pretty and colored format with expandable and collapsible pluses and minuses and indentation the way it’s in FF and IE.
Of course there are plug-ins but for regular users opening link with XML file brings inconsistent results: in FF and IE they see nicely formatted XML and in Chrome they see just plain text.
One of the solution is to force download dialog on opening the link.

We can do it by:

  • adding rules to htaccess
  • creating intermediate PHP (or any other) script which reads and outputs content of out XML file

Continue reading “Force Download Dialog on XML (or any other) File Type”

How to use PDO and Parameter Binding

Parameter binding is essential for protecting your web application from SQL-injection. Pretty much all data which is going to be used in SQL statement needs binding. Binding simply saying is just a way to tell engine that a particular piece of data is a string, number, character and so on. By doing this special characters like quotes and double quotes, semi-colons, etc. won’t be interpreted as commands by the database.

Example:

public function dbSelect($table, $fieldname=null, $id=null)        {
$this->conn();
$sql = "SELECT * FROM `$table` WHERE `$fieldname`=:id";
$stmt = $this->db->prepare($sql);
$stmt->bindParam(':id', $id);
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

Continue reading “How to use PDO and Parameter Binding”