Setting up an Ubuntu server for PHP

Install the required packages

It's good practice to ensure that the system is up to date.

sudo apt-get update
sudo apt-get dist-upgrade
sudo reboot
sudo apt-get install apache2 mysql-server php5 libapache2-mod-php5 php5-gd php5-mysql php5-curl postfix
sudo a2enmod vhost_alias rewrite
sudo service apache2 restart

(Optional) Add ServerName yourhostname to /etc/apache2/httpd.conf

6 months ago

Correctness and reliability

A function is something that takes inputs and returns a result. Functions should be simple, do one thing, and do that one thing well.

Let's write a function in JavaScript that computes the area of a rectangle.

function getArea(width, height) {
    return width * height;
}

This code will work for us, however if we didn't write this code it will probably be not obvious what kind of area does this compute. We could add comments explaining what the code does, however that does not help us when we are reading a code that uses this function. The best thing to do is give the function a good name that makes it's purpose obvious to the reader.

function getRectangleArea(width, height) {
    return width * height;
}

Now we have a simple and readable function that returns the correct results for correct input, which is wonderful, however what happens when the inputs are not correct?

What happens when the width and/or the height are not numbers? What happens when the width and/or the height are invalid numbers?

Java programmers and other static-typing-language programmers would quickly point out that they don't have to worry about this because the compiler checks the types, so that could never go wrong. This is true to some extent however static typing doesn't always ensure that the oder of the arguments is correct and some have problems with Null values.

interface Greet {
       void sayHello(String firstName, String lastName)
   }

   class PrintGreeter implements Greet {
       public void sayHello(String lastName, String firstName) {
           ...
       }
   }
public class Test {

    public static void whatever(Integer foo) {

    }

    public static void main(String[] args) {
        whatever(null); // The compiler will not complain.
    }
}

Static typing also has negative effects, because it can give false confidence to developers: http://programmers.stackexchange.com/questions/221615/why-do-dynamic-languages-make-it-more-difficult-to-maintain-large-codebases/221658#221658

Some developers just go out and assume that static typing will save them from all bugs and don't bother to write tests and make sure that their code is reliable(more on this later).

Even if we ignore the shortcomings of static type systems listed above, we are still faced with another type of issue: valid type, invalid value.

The above code will happily expect negative values as rectangle width/heights which is invalid and static typing would not catch this error(the invalid values), because they are valid numbers.

Relevant links:

http://www.youtube.com/watch?v=ILkT_HV9DVU

http://www.infoq.com/presentations/Robert-C.-Martin-Bad-Code

http://reprog.wordpress.com/2010/06/05/we-cant-afford-to-write-safe-software/

7 months ago

Macports updating

Update the Macports database.

sudo port selfupdate

Update the installed packages.

sudo port upgrade outdated

Clean up old versions.

sudo port uninstall leaves
sudo port uninstall inactive
7 months ago

PHP Sessions in redis

Storing session data in files can be a bottleneck in PHP, also it can be tedious to manage. Luckily there is an easy way to store the session data in memory in Redis.

First step is we install redis and php-redis.

sudo apt-get install redis-server php-pear
sudo pecl install redis

We need to enable the php-redis extension in php.ini.

extension=redis.so

We also need to tell PHP to use redis for sessions.

; Handler used to store/retrieve data.
; http://php.net/session.save-handler
session.save_handler = redis
session.save_path = "tcp://localhost?weight=1"

We also might want to set the session lifetime to what we desire.

session.cookie_lifetime = 2764800
session.gc_maxlifetime = 2764800

After we configured everything an apache restart is required.

sudo service apache2 restart

Reference: https://github.com/nicolasff/phpredis

7 months ago

Installing NodeJS on Ubuntu

Install tools required for compiling Node.

sudo apt-get update
sudo apt-get install build-essential openssl libssl-dev pkg-config

Download build and install Node.

cd ~
wget http://nodejs.org/dist/v0.10.25/node-v0.10.25.tar.gz
tar xvf node-v0.10.25.tar.gz
cd node-v0.10.25
./configure
make
sudo make install

Clean up.

rm node-v0.10.25.tar.gz
rm -fr node-v0.10.25
7 months ago

Advanced Git deploys

Deploying with git makes sense for various reasons:

Install git

sudo apt-get install git-core

Create user

sudo adduser \
   --system \
   --shell /bin/bash \
   --gecos 'git version control' \
   --group \
   --disabled-password \
   --home /home/git git

Gitolite setup

su git
cd ~
git clone git://github.com/sitaramc/gitolite
mkdir -p $HOME/bin echo "PATH=$HOME/bin:$PATH" > ~/.bashrc gitolite/install -to $HOME/bin
exit
su git
cd ~
gitolite setup -pk YourName.pub
/home/git/.gitolite.rc

$REPO_UMASK, octal, default 0077 The default UMASK that gitolite uses makes all the repos and their contents have rwx------permissions. People who want to run gitweb realise that this will not do. The correct way to deal with this is to give this variable a value like 0027 (note the syntax: the leading 0 is required), and then make the user running the webserver (apache, www-data, whatever) a member of the 'git' group.

If you've already installed gitolite then existing files will have to be fixed up manually (for a umask or0027, that would be chmod -R g+rX). This is because umask only affects permissions on newly created files, not existing ones.

reference: https://github.com/sitaramc/gitolite

Web root directory

Create a directory that the git user is allowed to write to and apache is allowed to read from.

usermod -a -G git www-data
usermod -a -G www-data git
service apache2 restart
mkdir /www
chown www-data:www-data /www
sudo chmod 775 /www

Afterwards all you need to do is write a post-receive hook that puts the files into the /www directory.

7 months ago

Using package.json for dependencies

If you are working on a project that uses NodeJS, you have no reason not to use package.json for listing your dependencies, unless of course you are only using built-in node modules.

Getting started

You can use the following command to generate a package.json.

npm init

or create one yourself and start specifying your dependencies in the dependencies or devDependencies property. The modules are the keys and the version numbers are the values.

{
  "name": "test",
  "version": "0.0.0",
  "author": "You",
  "license": "BSD",
  "dependencies": {
    "awesomemodule1": "1.2"
  }
}

dependencies vs. devDependencies

Dependencies are usually modules you need to run your app, while devDependencies are modules you need to develop your app.

Usage

Once you set up a package.json, all you need to do is run npm install and it will fetch all the modules that you specified above.

7 months ago

Java weirdness

One does not equal one

System.out.println(new Integer(1) == new Integer(1)); //prints false

Explanation: the equality operator checks if you are comparing the same objects not the same value.

Same strings aren't always the same

System.out.println("a" == "a"); //true
String a = "a";
String b = "a";
System.out.println(a == b); //true
String c = new String("a");
String d = "a";
System.out.println(c == d); //false

Strongly typed language, except when it's not

Integer foo = 5;
int bar = 5;
System.out.println(foo == bar); //true

Interesting list to array conversion API

List<String> stringList = new ArrayList<String>();
stringList.add("Lorem");
stringList.add("Ipsum");
String[] stringArray = stringList.toArray(new String[stringList.size()]);  
8 months ago

The callback hell that never was

Let's talk about callbacks, people seem to get terrified by them, because they see something like this:

var mysql = require('mysql'),
    db = mysql.createClient({
        user: 'root',
        password: 'root'
    }),
    id = 1;

db.query('USE mydb', function (err) {
    //some code here
    db.query('SELECT * FROM whatever WHERE id=?', [id], function (err, foo) {
        if (foo) {
            //some other code
            db.query('UPDATE whatever SET bar=?', [foo.bar], function (err) {
                db.query('INSERT INTO someothertable (sometime) VALUES (NOW())', function () {
                    //some code
                    console.log("It's done");
                });
            });
        }
    });
    //more code
});

This has the potential to turn into hard to understand spaghetti code. But we don't have to write it like this, we don't have to inline every function we can simply name them instead.

var mysql = require('mysql'),
    db = mysql.createClient({
        user: 'root',
        password: 'root'
    }),
    id = 1;

function init(fn) {
    db.query('USE mydb', fn);
}

function fetch(id, fn) {
    db.query('SELECT * FROM whatever WHERE id=?', [id], fn);
}

function checker(err, foo) {
    if (foo) {
        //some other code
        update(foo.bar);
    }
}

function update(bar) {
    db.query('UPDATE whatever SET bar=?', [bar], function (err) {
        db.query('INSERT INTO someothertable (sometime) VALUES (NOW())', function () {
            //some code
            console.log("It's done");
        });
    });
}

init(function () {
    fetch(id, checker);
})

We could also put this in a module or wrap a (pseudo) class around it if we wanted to. The main point is that we don't have to nest inline callbacks to get the job done, we can name them.

8 months ago

How to write a CKEditor image uploader backend

CKEditor is an awesome piece of software, it's essential for good CMS-es that require WYSIWYG editing, the problem however that it doesn't have an image uploader by default and it's not a trivial task to write one because it's documentation is not very good on this subject I spent a lot of time googling for hints on how can I write a PHP backend for image uploads, luckily after some hard work I managed to gather enough info to create a working image upload backend.

  1. I have an ajax directory relative to the sites root, I will create an upload.php in this folder.

  2. I edit the config.js (inside CKEditor's directory) and append the following line:
    //this needs to be inside: CKEDITOR.editorConfig = function( config )
    config.filebrowserImageUploadUrl = 'ajax/upload.php?type=Images';
  3. This upload.php will have to deal with a HTTP Post Request of course and the file will be sent from an input named "upload", in PHP this means that we have to deal with $_FILES['upload']. Also we need to respond to CKEditor which is a little tricky, it involves ad-hoc JavaScripting(which was badly documented when I did this the first time). The following template solves the CKEditor specific issues:
<?php
//process $_FILES['upload']
//store uploaded images URL in $uploadedImageURL
?>
<script type="text/javascript">
window.parent.CKEDITOR.tools.callFunction( <?php echo $_GET['CKEditorFuncNum']?>, '<?php echo "$uploadedImageURL"?>' );
</script>

We normally want to resize the image at this point and tell CKEditor the URL of our resized image. This ad-hoc method is mainly for security.

There is also the option for using CKFinder for file uploads, but I prefer doing custom solutions so that I can have maximum control over my file uploads.

4 years ago