Posts Tagged ‘PHP’

How to Setup MongoDB PHP Extension on Shared Hosting

Wednesday, July 7th, 2010 by Phillip Napieralski

Want to use MongoDB but don’t want to switch to a more expensive hosting plan? This is a great alternative that I got working on Dreamhost in less than an hour!

Setup your external MongoDB

I use MongoHQ to host my database (your first 16MB database is free). Make sure to take note of your connection string for later.

Custom PHP.ini

This part is somewhat tricky. Luckily, if you are using dreamhost, it is well documented on their wiki. Thus, I won’t go into detail of that here. Follow the directions and proceed to the next step (or leave a comment asking for help if you have issues).

After setting up your custom ini file for your domain, add the following lines to the very end of your php.ini:

extension_dir = "/home/YOUR_USERNAME/bin"
extension =

NOTE: This step loads the MongoDB extension but, we don’t have it yet! The next steps will fix that.

Compile MongoDB: Part 1

Using SSH, cd into your home folder (/home/YOUR_USERNAME) and type the following:

mkdir bin
cd bin/
tar zxvf mongodb-mongo-php-driver-1.0.6-0-gd261d7a.tar.gz
cd mongodb-mongo-php-driver-gd261d7a/

If you receive the error Cannot find autoconf after running the command phpize, follow the next section. Otherwise, skip it!

Compile/install autoconf

tar -zvxf autoconf-2.66.tar.gz
cd autoconf-2.66/
./configure "--prefix=$HOME" 
make install

The configure line will tell make install to put the library (.so) file into our home/bin directory (eg, /home/YOUR_USERNAME/bin). Quickly check that you have a few autoconf folders in your bin directory and continue on.

IMPORTANT: You must now tell linux to look for libraries in your home/bin directory. To do this, you must change the PATH as follows:


Compile MongoDB: Part 2

Remember that phpize function? Yea, try it again:

cd $HOME/bin/mongodb-mongo-php-driver-gd261d7a/

This time, you should not receive an autoconf error. Now, we actually compile the extension.

./configure "--prefix=$HOME"

And, for some reason, the make install commands ignores our prefix… so we can just manually copy the needed (.so) file to our bin folder:

cp modules/ $HOME/bin/

Now double check that exists in your home/bin directory (eg, /home/YOUR_USERNAME/bin/

Test it

Now, here’s a simple script to test if you can insert something into your external Mongo database.

   $db = $m->YOUR_DATABASE
   $collection = $db->YOUR_COLLECTION;

   $collection->insert(array('name' => 'super test 5000'));

There! You should have just inserted a new record into your database collection. Test by changing the insert line to the following:

$cursor = $collection->find();

echo $cursor->count() . ' documents found. <br/>';
foreach ($cursor as $obj) {
   echo '<br/>';

Now when you run that last script, you should see at least the one record you JUST added!


This is the approach I am currently using for one of my smaller pet projects. I’m going to be doing a lot of testing on my local machine using XAMPP, then going live with it using Dreamhost. It is also unfortunate that I’m forced to use an external DB. But, considering the first 16MB of database from MongoHQ is free, I’m totally satisfied with this for now.

User Account Class in PHP 2

Wednesday, February 10th, 2010 by Phillip Napieralski

I started up an account class in my previous post, but I left out a way for the user to authenticate! Let’s fix that…


	public function authenticate($group_id = 0) {
		$dbconn = @Database::grab();

		// They must have ALL three cookies set from the login function, otherwise something went wrong!
		if( !isset($_COOKIE['id']) && !isset($_COOKIE['cookie']) && !isset($_COOKIE['name']) )
			return false;

		// Sanitize
		$id = safe($dbconn, $_COOKIE['id']);
		$cookie = safe($dbconn, $_COOKIE['cookie']);
		$username = safe($dbconn, $_COOKIE['name']);

		// Make sure they have a valid cookie value first! (64 characters long in our case)
		if( strlen($cookie) > 63 )
			// Check the values in the DB with a quick query
			$query = "SELECT id, username, cookie, group_id FROM users WHERE
					id = ".$id." AND
					cookie = '".$cookie."' AND username = '".$username."' AND group_id >= $group_id LIMIT 1";
			$queryData = $dbconn->query($query);
		if( $queryData )
			if( $queryData->num_rows > 0) {
				$data = $queryData->fetch_object();
				$this->group_id = $data->group_id;
				$this->user_id = $data->id;
				$this->username = $data->username;
				return true;

		// They failed to authenticate! Wrong username/pass?
		return false;

There you have it. Basically, check to make sure they have all the cookies you set in your login function. If any are missing, fail. Then, we write a query to check the credentials from the cookies to see if they match what’s in the database. If not, clean up their cookies with $this->logout() and return false. That reminds me, here’s the code for logout:


	public function logout() {
		$dbconn = @Database::grab();
		if(isset($_COOKIE["id"]) && isset($_COOKIE["cookie"]))
			$id = safe($dbconn, $_COOKIE['id']);
			$cookie = safe($dbconn, $_COOKIE['cookie']);

			// Set the cookie to null in the database
			$query = "UPDATE users SET cookie = 0 WHERE id = ".$id." AND cookie = '".$cookie."'";
		// Expire our cookies by setting the time to 1 second after the EPOCH
		setcookie("hpname", "", 1, "/" );
		setcookie("hpid", "", 1,"/" );
		setcookie("hpcookie", "", 1,"/" );
		// Unset them immediately

There you go. What’s missing now? We just need a forgot password function and we’re good to go.

Lost on this tutorial? Try going back to part 1

User Account Class in PHP 1

Wednesday, February 3rd, 2010 by Phillip Napieralski

I’m going to describe the class I created to handle signup/login/authentication at

If you’d like a demo, create an account at Happy Polack 🙂.

The Database Structure

First, what is it going to look like in the database? Well, here’s what I used:

Generated using MySQL Workbench

Take note of the indexes used. I have a foreign key relating the users and the groups table (1-1 for now). I also have a unique index on the username to prevent the same username. Lastly, I have a regular index on the email address to make searching that field faster (useful if they forgot their password).

The other thing to note is that both password and cookie have a datatype of CHAR(64). This is because I encrypted the password using a SHA256 algorithm, which is WAY stronger than md5, before placing it in the database (this is PHPs hash(“sha256”,$unenc_password) function). For the cookie field, I use that algorithm on the uniq_id() function built into PHP. I’ll get to that in a minute.

The Class Structure

class AccountController {
        // Initialize variables to something arbitrary
	private $group_id = -1;
	private $user_id = -1;
	private $username = '';

	public function signup($username, $password, $email){...}
	public function login($username, $password){...}
	public function logout(){...}
	public function authenticate($group_id = 0){...}
	public function is_logged_in(){...}
	public function is_admin(){...}

Excellent! We got the basic functionality out of the way. We are able to signup/login/logout/authenticate. We can even pass a group_id to authenticate to make sure they are part of a specific group.


public function signup($username, $password, $email) {
	$dbconn = @Database::grab(); // This WILL be different for you. I use a simple MySQLi wrapper.

	$origpassword =  $password; // store original password to send to them
	$password = hash('sha256', $password);
		return false;
		// Send a nice email
		$message = '<b>Account Information:</b>';
		$message .= '<p>Username: '.$username;
		$message .= '</p><p>Password: '.$origpassword;
		$message .= '</p><p>Your profile:'.$username.'</p>;

		send_mail( $email, "Welcome to Happy Polack!", "Hello and Welcome to Happy Polack!", $message );
	return true;

There you have it! Now we can signup, well… except for the send_mail piece, let me give you the code for that:

function send_mail($to, $subject, $title, $msg)
	$headers = 'From: Happy Polack <>'. "\r\n".
			'Reply-To:' . "\r\n" .
			'X-Mailer: PHP/' .phpversion(). "\r\n";

	$headers .= 'MIME-Version: 1.0' . "\r\n";
	$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";

	$message =  '<h1>'. $title.'</h1>';
	$message .= $msg;

	mail( $to, $subject, $message, $headers);

Basically, this nifty function automatically sets up the headers so we can use HTML in our e-mails and it automatically formats various features (this implementation could be spruced up with some neat css too).


public function login($username, $password) {
	$dbconn = @Database::grab();

	$epassword = hash("sha256",$password); // Encrypt using SHA256. We could also "salt" the password before hashing for added security.

	$query = "SELECT id, group_id FROM users WHERE username = '$username' AND password = '$epassword' LIMIT 1";
	$qData = $dbconn->query($query) ;
	if( $qData->num_rows > 0 )
		$userData = $qData->fetch_array();
		$cookie = generate_token();
		$userID = $userData['id'];

		$query = "UPDATE users SET cookie = '$cookie' WHERE username = '$username' AND password = '$epassword'";

			$this->user_id = $userID;
			$this->group_id = $userData['group_id'];
			$expire_time = 60*60*24*7+time(); // About one week
			// When we create the cookies, we pass the cookie's name, the value, the expire time and what piece of the site the cookie is valid on. I specify "/" to allow it to be usable throughout the whole website.
			setcookie("id", $userID, $expire_time, "/");
			setcookie("cookie", $cookie, $expire_time, "/");
			setcookie("username", $username, $expire_time, "/");

			// This piece is so that the COOKIE values are set immediately. When I left this piece out, I noticed it would take an extra page load for the cookies to register. This is because the cookies are generally sent with everyday headers and *it seems* that they are not processed right away.
			$_COOKIE['id'] = $userID;
			$_COOKIE['cookie'] = $cookie;
			$_COOKIE['username'] = $username;

			return true; // SUCCESS, now logged in!
	return false; // Bummer!

What’s happening here? Well, let’s get a pretty picture to clarify the order a little bit:

Generated with yUML - Does this help?

In easier terms: Check if the user is in the database -> if he is, put a random value into his cookie field for later authentication and set his cookies.

That reminds me, here is one last function, generate_token(), that is pretty essential, and simple, to get a random string of length 64.

// Return a random string of length 64
function generate_token() {
	return hash('sha256', uniqid(mt_rand(), true));

Next Time

Wow! Progress has been made. But there’s more to be had. We still need an authenticate function as well as a way to logout!


Inline AJAX Editing

Saturday, January 23rd, 2010 by Phillip Napieralski is a joke site I created as a side project a little bit ago and it’s continually being enhanced. The latest feature I added was a way for admins to edit any joke (eg, fix typos), quickly and easily.

An Example

This weirdo typed “Your Mommy” instead of “Yo Mama.” How distracting! Let’s write some code so we can fix this.

If we click the edit link corresponding to the joke, we get something that looks like the following:

Great! We edited it, now we simply click submit and we can go on with reading jokes and being merry!

How it works

When the edit link is clicked, some simple javascript is called. Here is the PHP code for the edit hyperlink for any joke.

echo "<a id="joke&quot;.$joke_id.&quot;" href="javascript:edit_joke(&quot;.$joke_id.&quot;);">;edit</a>";

We start by assigning each link with a distinct ID (corresponding to the joke’s ID in the database) and, upon clicking, it calls the javascript function edit_joke.

The Javascript/jQuery Part

Inside the edit_joke function, I used jQuery selectors to find the link and text for the joke. I then used the wrapInner() method to place an editable <div> inside our joke text’s <p> tags (basically, we now have <p id=”123″><div>Your mommy joke hehe haha</div></p> instead of <p id=”joke123″>Your mommy joke hehe haha</p>). After that, change the edit link to submit/cancel using jQuery. Clicking submit will call the javascript function edit_joke_submit(..) and clicking cancel will call the javascript function edit_joke_cancel(..). I placed those links inside a <span> tag so I could easily reference them later. The magic in this code is the contenteditable=’true’ part of the div. Here’s the code:

function edit_joke(joke_id){
	this_link = $("a#joke"+joke_id);
	this_joke = $("p#joke"+joke_id);

	this_joke.wrapInner("<div contenteditable='true' class='editable_div'></div>");

	this_link.replaceWith("<span id='submitcancel'>"+
		"<a id='joke"+joke_id+"' href='javascript:edit_joke_submit("+joke_id+");'>submit</a>"+
		"<a id='joke"+joke_id+"' href='javascript:edit_joke_cancel("+joke_id+");'>/cancel</a>" );

The edit_joke_cancel function is relatively simple. I first found the corresponding submit/cancel link and the joke div using jQuery selectors. After that, I used the html() method to grab the new text that was typed in. I set the text inside the <p> tags equal to the new text so that it would look like <p id=”123″>Yo mama joke hehe haha<div>Yo mama joke hehe haha</div></p> instead of <p id=”joke123″>Yo mama joke hehe haha</p>. Then, simply remove the <div> tags (and, consequently, the text inside), and it’s back to normal.

function edit_joke_cancel(joke_id){
	this_link = $("span#submitcancel");
	this_joke = $("p#joke"+joke_id);
	this_joke_div = this_joke.find("div");

	joke_text = this_joke_div.html();

			"<a id='joke"+joke_id+"' href='javascript:edit_joke("+joke_id+");'>edit</a>"

To submit the joke changes, we need only send a post request to a server side php script with the joke id and the new joke text. Here’s the code:

function edit_joke_submit(joke_id){
	var this_joke = $("p#joke"+joke_id);
	var joke_text = this_joke.find("div").html();

				id: joke_id,
				text: joke_text

	edit_joke_cancel(joke_id); // remove edible div

The PHP Part

All we have to do now is send an update query to the database with the corresponding id and text. The only caveat: editable divs place <br>’s when you hit enter, so I added the str_replace(..) to turn those into newline characters capable of storage in the database. Check it out:

// Include needed files for account verification here.
// Get your database connection and store it in $dbconn HERE. I use mySQLi in my code.
if( $accounts->check_admin() )
	$id = $dbconn->escape_string($_POST['id']);    // Prevent sql injection
	$text = $dbconn->escape_string($_POST['text']);

	$text = str_replace("<br>","\r\n", $text);    // Swap's out <br>'s

	$query = "UPDATE joke_table SET text='".$text."' WHERE id = ".$id;
	$dbconn->query($query) or die(mysqli_error($dbconn));
	echo "The joke has been edited :)";
	echo 'Yea... okay buddy -_-';