How to build a login-registration system using Symfony – A PHP Framework – Part 2

Hello again,

In the last tutorial we saw a very basic implementation which will simply print “Hello World” on your browser screen. For those who have landed up here straight here, you may want to go through this blog post. Getting started with Symfony – A PHP Framework – Part 1 By now if you have decided to go ahead with symfony and use it for your site development, this is what you will be looking for next.

You can download the code for this tutorial from google code base.

svn checkout http://abhinavsingh.googlecode.com/svn/trunk/PHP/
Frameworks/Symfony/Authentication abhinavsingh-read-only

A Registration-Login-Logout System for your site
This is mostly the first thing you end up building for your site. To be frank, I myself haven’t made this application. I will make it as I write this blog, and note down all my steps here, so that I don’t miss any detail.

  1. We will name our project as Authentication
  2. Create a folder called Authentication under the Symfony directory we made in the last tutorial. For me its here C:WorkspaceSymfonyAuthentication
  3. Open your command line and point it to the above created folder
  4. Type “symfony init-project Authentication” and it will create same directory structure that we discussed in last tutotial.
  5. Lets create an application inside this, we will name it as Auth
  6. Type “symfony init-app Auth” and it will create an application named Auth under the apps folder. (C:WorkspaceSymfonyAuthenticationappsAuth)
  7. First we need a module called Registration, to allow our users to register.
  8. Type “symfony init-module Auth Registration” and it will tell symfony to create a module named Registration inside our application Auth
  9. As told in last tutorial copy the C:php5peardatasymfonywebsf folder to C:WorkspaceSymfonyAuthenticationwebsf. At the end of this part, we will learn how can we skip this copying again and again
  10. Open C:WorkspaceSymfonyAuthenticationappsAuthmodulesRegistrationactionsactions.class.php and comment out the forwarding as discussed in last tutorial.
  11. Go to your command line and type “symfony clear-cache“. Read why we do this in the last tutorial.
  12. Open http://localhost/Symfony/Authentication/web/ in your browser and you must get something like this.


Figure 1

OOPS! Did we missed something? Yes we did and intentionally. We could have gone to C:WorkspaceSymfonyAuthenticationappsAuthconfigrouting.yml and redirected our Authentication application to our Registration Module by default. In that case we would have seen an empty page since indexSuccess.php file inside C:WorkspaceSymfonyAuthenticationappsAuthmodulesRegistrationtemplates is empty. But since we didn’t modified the routing.yml file, it took us to the default module of symfony.

So how do we access our Registration module without modifying routing.yml file??
http://localhost/Symfony/Authentication/web/Registration/index is the answer 🙂

As a convention
http://localhost/Symfony/Authentication/web/<Module>/<ModuleFile>
this is the standard for symfony.

Hence it went to Registration module and then indexSuccess.php page inside that. Cool so we actually just followed up from our last tutorial till here. Lets now do the actual development.

Defining a layout for our website
Before we do any backend stuff, lets atleast get our site out of that blank page (http://localhost/Symfony/Authentication/web/Registration/index). However, If you view the source of that blank page, you will actually find that there are already some header, css, body tags in the source code. How is this coming? when we have an empty indexSuccess.php file.

From our last tutorial we saw the flow which symfony follows to finally display a page on the browser. But then I actually skipped a step to ease down the tutorial. In symfony we follow the Decorator Design Patterns (I hope i m not wrong here) , to get the front end stuff. Essentially Decorator Design Pattern consists of a Layout and a Content page.

In symfony our layout file is located under at C:WorkspaceSymfonyAuthenticationappsAuthtemplateslayout.php. Open it up and you will know the answer to “How are those meta tags, head tags and body tags coming”.

Cool enough. Lets go back to our indexSuccess.php file of Registration module and design our website. With a little CSS and HTML, I came up with this design page for our site. Mostly inspired and stolen from my new site Gtalkbots.com


Figure 2

We will shift a bit of code from this page to our layout.php page later on so that we need now write the same modules again and again. Download all the code, from the my google code vault location given at the beginning and end of this tutorial.

Designing the backend database:
Now we need  a databases schema which will save our registered user’s data.  Lets create our database structure.

As talked about in last tutorial, symfony follows ORM programming technique. For this, they provide a method through which you actually need not go to your database and create tables. Symfony will do that for you. Not only this, Symfony will also allow you to skip most of the SQL queries. Lets see how.

  1. Open C:WorkspaceSymfonyAuthenticationconfigschema.yml . From extension we know that symfony follows YAML structures which is similar to XML, but a bit easy to write. We will define our table structures in this file.
  2. Type the following in the schema.yml file:
    Propel:
      users:
        id:        { type: integer, primaryKey: true, autoIncrement: true }
        username:  varchar(100)
        emailid:   varchar(100)
        password:  varchar(100)
    
  3. Note the indentation, it is very very important when you are using YAML. Indentation actually decides how the YAML parsers will read and interpret the information you want to write in .yml files. In our case we have a very simple schema.yml file having only one table. We will learn about what that “Propel” is all about later, but lets focus from line 2.
  4. We are trying to make a table called users having fields like id, username, emailid and password
  5. Now before Symfony makes this table for you, we need to tell symfony the database username and password. For this we have a configuration file called propel.ini, located at C:WorkspaceSymfonyyahooconfigpropel.ini
  6. Open it and change the lines as below:
    propel.database.createUrl  = mysql://root@localhost/
    propel.database.url        = mysql://root:password@localhost/authentication
    

    Now go to your mysql database and create a database named authentication, which symfony will use from now on.

  7. Type “symfony propel-build-all” in your command line. This command will happily create a table named “users” in youy MySQL database “authentication”. Some of the possible errors which I got in the past are:
    • Your PHP must be compiled with XSLT, hence enable it by going in your php.ini file
    • In schema.yml file never use TABS. The YAML parsers don’t understand TABS. User SPACES intead of that.
  8. To cross verify check your database, if the table has been created. Now a bit about Propel.

Propel is nothing but a third-party-vendor plugin which Symfony use. It helps in parsing the YAML files, creating and executing the whole ORM module including parsing of schema.yml , creating tables, creating ORM data objects. We will slowly and gradually learn a lot more about ORM.

A look at the model layer
Another thing which the propel command did was, it created the whole ORM module. If you go to C:WorkspaceSymfonyAuthenticationlibmodel you can see 2 folders being created and a few files too.

For every table, propel build 5 files under the model folder. These files are basically the class files, which will provide use with a database object which we can use to select or insert data in the database.

C:WorkspaceSymfonyAuthenticationlibmodelomBaseUsers.php &
C:WorkspaceSymfonyAuthenticationlibmodelomBaseUsersPeer.php are the only 2 files which will be re-created when you run the propel command again.

The file positioned at
C:WorkspaceSymfonyAuthenticationlibmodelUsers.php &
C:WorkspaceSymfonyAuthenticationlibmodelUsersPeer.php will be as it is from this point in time. If you write your own methods in them, they will remain as it is even when you re-create your database schema.

We will use these created ORM files to insert, delete, select data from the databases. In symfony we can actually skip writing a SQL query (though we can always write a direct query too)

Writing the backend Code:
With UI and database in shape, its time to write our backend code which will handle the registration form submission. If you notice the source code of our form, the action field is set as :

<form id=”registration” action=”<?php echo url_for(“Registration/index”); ?>” method=”POST”>

In symfony we have a lot of helper functions which we can use. In this case we users url_for helper function, which helps in generating a url with <module>/<modulefile> being passed as parameter.

So we have our form being submitted to indexSuccess.php itself, i.e. SELF.
Hence lets go to executeIndex() method in action.class.php and write the code which will handle the submitted form.

Copy the modified action.class.php file from the vault location. I have documented every line inside the code, which will walk you through the code. Understand the flow and continue reading.

However before we insert any data in the database, we need to give the database parameters. Go to
C:WorkspaceSymfonyAuthenticationconfigdatabases.yml
and uncomment the lines of code in there. Finally it should be of the following structure:

all:
  propel:
    class:          sfPropelDatabase
    param:
      dsn:          mysql://root:password@localhost/authentication

Lastly open:
C:WorkspaceSymfonyAuthenticationappsAuthconfigsettings.yml
and go to the last line of the file. You will find
# compat_10    off
being commented out
Uncomment it and then turn on compat_10 i.e.
compat_10    on

Clear your cache, before submitting the form (symfony clear-cache) and then try to register.

If you have followed everything, you will be able to successfully able to register and visit mainSuccess.php of the module.

I have documented all the code which you can download from the vault location. Read it, try it, play with it.

PS: The best documentation is available at symfony-project website. This tutorial was intended to
build a real life scenario application using Symfony. Though I must admit that I still haven’t used 100% possible symfony
for this application, just to make it simple but still give you a feel of how things flow in symfony.

Leave a comment if you have any doubt or difficulty in implementing the code.
Do leave a comment even if you like the code 😉

Getting started with Symfony – A PHP Framework – Part 1

Hello Friends,

Since past few weeks I have been pushed into something which I have never favored i.e. using a framework for my development. Using a framework can become even more harder if you know all the actual HTML, CSS, JS, PHP coding. Then you just wonder WHY? WHY? WHY?

Anyways I had to do it using Symfony PHP framework and there was no way out. As I couldn’t find much help outside http://symfony-project.com , it made even more difficult for me to implement and understand symfony.  So I thought of writing a tutorial, which can help many others like me out there and also act as a reference for me in future. Here instead of giving a theory lecture straight up, we will learn along with little hands-on developments.

Installation:
Before installing Symfony I assume we already have Apache, PHP 5 and MySQL installed on your system. If you don’t have them already installed, read this post of mine on how to configure WAMP on your windows. How to Install Apache, PHP 5 and MySQL on Windows?

This method works equally on Windows and Unix systems. On windows open your command line and on Unix open a terminal window.

  1. Go to My Computer -> Right Click -> Click on Properties -> Advanced Tab -> Environment Variables -> Create a PATH variable if it doesn’t already exists -> Add C:PHP as the PATH variable value.
  2. Go to Start -> Run -> Type cmd -> Type C:> pear channel-discover pear.symfony-project.com
  3. Type C:> pear install symfony/symfony-1.0.18 , it will install symfony latest stable version for you. (1.0 at the time of writing this tutorial)
  4. If you are having trouble installing, post a message here or refer http://www.symfony-project.org/installation/1_0 for more details.

So now you have symfony framework installed and we will learn how to build our first project in symfony.

My first Project:
Before we go ahead in making our first php project using symfony, just a little theory without which its impossible to understand the flow. Symfony projects are designed as follows:

       My First Project –> Application 1 —-> Module 1
                                  |                              |
                                  |                              –> Module 2
                                  |
                                  -> Application 2 —-> Module 1
                                  |                              |
                                  |                              –> Module 2
                                  |                              |

                                  |                              –> Module 3
                                  |
                                  -> Application 3 —-> Module 1

So in your Project your can have multiple Applications and inside every application you can have multiple Modules.

  1. Go to your Apache Web Folder (Document Root) which in my case is C:Workspace.
  2. Create a folder called Symfony. We will keep all our symfony related development work in this folder.
  3. Go inside the folder C:WorkspaceSymfony and create another folder for our 1st project. Lets name it HelloWorld
  4. Open your command line and go to the above folder path i.e. type ‘cd C:WorkspaceSymfonyHelloWorld’ on your command line.
  5. Type ‘symfony init-project HelloWorld’ and press enter. This will automatically create the project directory structure for you. Don’t be afraid if you see some 10 folders being create by the last command.

Don’t close the command line window, we will need that throughout.

So by now we have our first symfony project folder ready (structurally). But to view this on your browser we need atleast 1 application and atleast 1 module in that application. Lets create them quickly.

  1. Type ‘symfony init-app HelloWorld’ and press enter. This will create an application folder C:WorkspaceSymfonyHelloWorldappsHelloWorld. Now lets create a module inside this application
  2. Type ‘symfony init-module HelloWorld HelloWorld’ and press enter. This command means, create a module named HelloWorld inside application HelloWorld. Generic level syntax is ‘symfony init-module [application] [module]’

So we have our first symfony project ready. Type http://localhost/Symfony/HelloWorld/web in your browser window and press enter. You will see a page like this:


Figure 1

But this is not what it should be. If you read the page, it says “If you see no image in this page, you may need to configure your web server so that it gains access to the symfony_data/web/sf directory”.

So all you need is to copy folder C:php5peardatasymfonywebsf (in my case) to C:WorkspaceSymfonyHelloWorldwebsf. If you don’t find sf folder at the specified place, kindly search for it on your system. It was created when we were installing symfony.

After copying the folder refresh your web page again and see if you see any difference. For me it looks like:


Figure 2

Well Congratulations ! You just made your first symfony project. But unfortunately you know 0% of what did. Right? Lets understand what exactly is going in the background.

A bit about MVC Architecture:
Symfony follows MVC (Model-Viewer-Controller) Architecture to the core. If you haven’t worked with MVC architectural frameworks before, it can really take sometime to get a feel of it. I took about a week to actually understand what goes in the background.

MVC Architecture is nothing but breaking your whole page code into three parts namely Model (Database) , Viewer (Frontend HTML Pages) and Controller (Which fetches data from Model i.e. database and provide it in required format to Viewer i.e. what we finally see on our browsers). This is a very layman definition which I have given. We will slowly and gradually see each aspect of MVC in Symfony.

A bit about ORM (Object Relational Mapping):
This is yet another programming technique which you will find in each and every framework. In layman language, ORM provides you an object to handle your database. You need not write a SQL Query in actual at any point in your project. You will access all your database rows using this ORM Object.

Strange it may seem at first, but consider a big project running on MySQL with a lot of INSERT queries. Now at some point in time when database size reaches > 50 Gb or so and you are finding MySQL not efficient enough to handle such a large database, you would want to change to a database like Oracle. In such a scenario, ORM takes all the headache off from you, as you need not care about the actual SQL queries that goes in the background. ORM automatically takes care of this stuff.

Understanding Symfony Directory Structure:
The Symfony directory structure of our first project will look like this:


Figure 3

Remember we still don’t have anything dealing with the databases, hence I can say that Model layer is still missing from the directory structure. But let us first complete our targeted “Hello World” application.

  1. Go to HelloWorld/apps/HelloWorld/config folder and open the file rounting.yml
  2. Change the 4th line in that file from – param: { module: default, action: index } to param: { module: HelloWorld, action: index }
  3. We will learn about all .yml files which you see, but as of now lets focus on what we just did. By default our Symfony project points to a default module created by Symfony. Thats why we see Figure 2 above. By changing the above piece of code, we are telling our HelloWorld application inside HelloWorld project that, by default point to my HelloWorld Module. Confusing! Read the last line again and continue reading 😉
  4. Go to HelloWorld/apps/HelloWorld/modules/HelloWorld/actions and open the file actions.class.php
  5. Comment the following php code $this->forward(‘default’, ‘module’); inside executeIndex() method.
  6. Go back to your command line and type: ‘symfony clear-cache’
  7. Type http://localhost/Symfony/HelloWorld/web in your browser window and press enter.

Bingo! You see a blank white page. Lets understand what we actually did. But before that just a few points on how a page is actually displayed in Symfony.

  1. When we type http://localhost/Symfony/HelloWorld/web in our browser, index.php in the web folder goes to routing.yml file
  2. Routing file then tells which module to follow by default. By following Step 2 above, we directed the flow to our HelloWorld module.
  3. Then flow goes to the actions.class.php file of the module provided by Routing file. Hence in our case it must have gone to actions.class.php file of HelloWorld module.
  4. It looks for executeIndex() method in the class file, executes it and
  5. Finally goes to indexSuccess.php file placed under the template folder of our HelloWorld Module.

But since our actions class method was already diverting the flow to the default module, flow won’t have come to step 5 above and would have gone to default symfony module. By commenting out the line in step 5 above, we actually skip this forwarding and the flow comes to indexSuccess.php file under templates module. And finally since indexSuccess.php file is a blank file, we see a blank page. 🙂

Read the above 2 point charts carefully. If you can understand this flow, you already conquered half the symfony.

Note: All this will go waste if you forget ‘symfony clear-cache’ in step 6 above. As a rule of thumb, always run this command when ever you make any changes to any of the .yml files.

My First Project “HelloWorld”
Open indexSuccess.php and type <h1>Hello World</h1> into it. Run http://localhost/Symfony/HelloWorld/web in our browser, and thats it 🙂 You will see a page like below.

And with that we completed our Part 1 of this Symfony tutorial series. In upcoming parts of the series we will learn how to manage databases and build a bit more complex application and modules. Post your doubts and comments if any.

Note: I am myself learning many parts in Symfony and I myself gather knowledge by experimentation and through various web sources. Hence if a Symfony expert is reading this and find anything wrong, kindly correct me.

How to create an upload meter in PHP? Explained

It was about 2 months back when I started hunting for an upload meter “How To?” guide on net. Came across a lot of links actually but I must say none of them actually gave me what I wanted to have. Some talked of some patched PHP version to achieve the same and some talked everything except an upload meter.

Finally I was able to come up with the trick involved (thanks to sources on net and some work on my side). Here I will explain in short how can we achieve this on windows and unix both:

  1. APC (Alternate PHP Cache) : Before we go on to develop an upload meter we will need to have this component configured. Without APC its almost impossible to have an upload tracking script working on your server in PHP. Basically, when we upload a file to a server (windows or linux) the file first goes to the /tmp folder (DEFAULT) and then using the php’s move_uploaded_file($FileTemp,$FileUploadLocation) command we move that file from /tmp folder to the location we finally want it to be.

    Now the only problem is that, the file name in the /tmp is quite nondeterministic. There is no way to predict the file name in /tmp. Hence by simple methods we cannot track the status of upload for that particular file. We need a handler to that file, through which we can track its upload progress.

    Although APC is not meant for this, but it does provide us a method to bind a unique name to this uploading file. Lets first see how to install APC on windows and unix.

  2. Installing APC on windows : On windows the installation process is quite simple. Simply download this zipped folder from here. Extract it and you will find, folders corresponding to each PHP version released. Identify your PHP version, copy the corresponding DLL file from that folder and place it under C:/PHP/ext and C:/Windows (if you have your php.ini file placed there).

    Now open your php.ini file, and add the following lines:

    extension=php_apc.dll
    apc.shm_segments=1
    apc.optimization=0
    apc.shm_size=128
    apc.ttl=7200
    apc.user_ttl=7200
    apc.num_files_hint=1024
    apc.mmap_file_mask=/tmp/apc.XXXXXX
    apc.enable_cli=1
    apc.rfc1867=on
    apc.max_file_size=10M

    These lines must be placed after all the extension definition in the php.ini file. I won’t go into explaining the various parameters here, you can search for them and you will find plenty of documentation for that. As of now you can care only about apc.rfc1867=on (without this file upload meter won’t work, this tells APC to track file uploading) and apc.max_file_size=10M (this specifies max file size to cache which is otherwise 1Mb by default).

    Now simply restart your apache server, and see your php information i.e. phpinfo(). You must see a section APC in the phpinfo(). If you can see that section, Congratulations APC installation is done for you 🙂

  3. Installing APC on unix (Debian or Ubuntu) : I have done this on debian and ubuntu, but similar must be the process for other OS too. Simply install the following modules:
    • apt-get install apache2-dev,apache2-threaded-dev,php-pear,php5-dev,make
    • ln -s /usr/bin/apxs2 /usr/bin/apxs (APC won’t install without this symlink)
    • pecl install apc (input Yes if prompted)
    • Add extension=apc.so in php.ini
    • /etc/init.d/apache2 restart
    • pecl upgrade apc
    • /etc/init.d/apache2 restart
    • Add apc.rfc1867=on in php.ini for tracking file upload
  4. Coding your Upload meter (index.php): So we are almost there. Just a few lines of code and we have our upload tracker ready. Let us first create an html form.
    <html>
      <head>
        <script type=”text/javascript” src=”upload.js”></script>
      </head>
      <body>
        <form id=”upload” name=”upload” target=”frame” action=”utility.php” method=”POST” enctype=”multipart/form-data”>
         
          <!– Setting this enables apc upload tracking –>
          <input type=”hidden” name=”APC_UPLOAD_PROGRESS” id=”fileKey” value=”<?php echo md5(uniqid(rand(),true)); ?>”/>
         
          <!– Hidden field for the upload form –>
          <input type=”hidden” id=”uploadfile” name=”uploadfile” value=”uploadfile”/>
         
          <!– DIV containing the file chooser box, it will be replaced by the filename after upload –>
          <div id=”attachment”>
            <input id=”fileloc” name=”fileloc” size=”30″ type=”file” onchange=”getProgress();document.upload.submit();return false;”/>
          </div>
         
          <!– DIV showing the upload progress bar –>
          <div id=”showProgress” style=”margin-top:5px;width:205px;height:15px;border:1px solid #93B9D9;display:none”>
            <div id=”currentStatus” style=”width:0px;height:15px;background-color:#B2D281″></div>
          </div>
         
          <!– iframe handling all the upload –>
          <iframe name=”frame” style=”display:none”></iframe>
         
          <!– DIV which catches all the error and other messages –>
          <div id=”upload-note”></div>
        </form>
      </body>
    </html>

    The code is self explainatory 😛 , if not I have put in some comments in there. Here is a short explaination again:

    • upload.js file will handle the ajax calls later on and also will take care of incrementing the upload status bar.
    • <input type=”hidden” name=”APC_UPLOAD_PROGRESS” id=”fileKey” value=”<?php echo md5(uniqid(rand(),true)); ?>”/> , this is the factor which allows us to keep a track of our file. This must always be declared before the file uploading input box. Basically it tells APC to associate value=”[SPECIFIED_ABOVE]” with the uploading file. This values serves as a key and using this key we will later on track the file.
    • The form submits into an iframe. To understand more on this one read through one of my previous post on Gmail Type Attachment – How to make one? .
    • <div id=”attachment”></div> contains the file chooser input box, which submits the form as soon as it receives a file to upload.
    • id=”showProgress” and name=”frame” are self explanatory. I have used <div id=”upload-note”></div> to post upload error messages in case of an error.
  5. Coding your Upload meter (utility.php): utility.php is the file which handles the file uploading process. The form submits into this file through the iframe.
    <?php

      if((isset($_POST[‘uploadfile’])) && ($_POST[‘uploadfile’] == “uploadfile”)) {
       
        // Gather File data (name,size,mimetype,tmp_name)
        $FileName = $_FILES[‘fileloc’][‘name’];
        $FileSize = round($_FILES[‘fileloc’][‘size’]/1024);
        $FileType = $_FILES[‘fileloc’][‘type’];
        $FileTemp = $_FILES[‘fileloc’][‘tmp_name’];
       
       
        // Get file extension
        $extension = strtolower(substr($FileName,strrpos($FileName,’.’)+1));
       
        // If filename is blank, exit with a message
        if($FileName == “”) {
          echo “<script type=’text/javascript’>”;
          echo “parent.document.getElementById(‘upload-note’).innerHTML = ‘<font size=2 color=#990000>Kindly choose a file to upload</font>'”;
          echo “</script>”;
          exit;
        }
       
        // If filesize is > 10 Mb, exit with a message
        if($FileSize >= “10240”) {
          echo “<script type=’text/javascript’>”;
          echo “parent.document.getElementById(‘upload-note’).innerHTML = ‘<font size=2 color=#990000>OOPS! The file exceeds the maximum limit of 10 Mb</font>'”;
          echo “</script>”;
          exit;
        }
       
        // Exit if file’s extension is not jpg
        if($extension != “jpg”) {
          echo “<script type=’text/javascript’>”;
          echo “parent.document.getElementById(‘upload-note’).innerHTML = ‘<font size=2 color=#990000>OOPS! Only jpg file formats are supported</font>'”;
          echo “</script>”;
          exit;
        }
       
        // Choose a final upload location
        $FileUploadLocation = “upload/”.$FileName.”.”.strtolower($extension);
       
        // Move the uploaded file from temp to final upload location
        if(move_uploaded_file($FileTemp,$FileUploadLocation)) {
          echo “<script type=’text/javascript’>”;
          echo “parent.document.getElementById(‘upload-note’).style.display=’none’;”;
          echo “parent.document.getElementById(‘attachment’).innerHTML = ‘<input CHECKED type=”checkbox”><font color=#003399 size=2><b>”.$FileName.”</b> (“.$FileType.”) “.$FileSize.” Kb</font>’;”;
          echo “</script>”;
        }
        else {
          echo “<script type=’text/javascript’>”;
          echo “parent.document.getElementById(‘upload-note’).innerHTML = ‘<font size=2 color=#990000>OOPS! An error occurred, please try again</font>'”;
          echo “</script>”;
        }
       
      }
     
    ?>

    I have tried to include enough comments to make this code self explanatory. If you find any thing which is not self explainable kindly drop a comment and I shall reply to it.

    In short this file takes the file size, file name, file tmp url. Check for the file, if its valid and within constraints. i.e. Max file size 10 Mb, File format jpg etc etc…..

  6. Coding your Progress Status script (progress.php): progress.php is the script to which we will make all the ajax calls, passing it the “filekey” defined in index.php above. Using that filekey it will return the upload status of the file associated with that key.

    Essentially, it returns 3 things. Done, Current, Total i.e. Done (meaning if the upload is complete), Current (meaning how much has been uploaded already), Total (meaning whats the total size expected).

    Hence using these 3 params we will make over upload meter progress bar. Lets see the javascript function doing all these ajax requests and maintaining the progress bar.

  7. Coding the JavaScript (upload.js): As soon as the form gets submitted, it calls the getProgress() function inside this javascript function. This function starts making calls to progress.php. And then depending upon what it returns, it manages the progress bar. Here is the javascript doing the same:
    function getProgress() {
      var xmlhttp = false;
      var id = document.getElementById(‘fileKey’).value;
      var url = “http://localhost/FileUploadMeter/progress.php?id=” + id + “&nc=” + (Math.random()*100000);
      try {
        xmlhttp = new ActiveXObject(“Msxml2.XMLHTTP”);
      }
      catch(e) {
        try {
          xmlhttp = new ActiveXObject(“Microsoft.XMLHTTP”);
        }
        catch(oc) {
          xmlhttp = null;
        }
      }

      if (!xmlhttp && typeof XMLHttpRequest != “undefined”) {
        xmlhttp = new XMLHttpRequest();
      }
      if(!xmlhttp) {
        document.getElementById(‘xmlhttp-note’).style.display = ‘inline’;
        return false;
      }
      xmlhttp.onreadystatechange = function() {
        if(xmlhttp.readyState!=4) {
        }
        if ((xmlhttp.readyState==4)&&(xmlhttp.status == 200)) {
          var response = xmlhttp.responseText;
          if(response != “”) {
            if(response != “Success”) {
              var d = eval(“(” + response + “)”);
              // Update Progress Bar
              if(d.total != 0 && d.current != 0) {
                document.getElementById(‘showProgress’).style.display = ‘block’;
                var percentDone = (d.current/d.total)*100;
                // Calculate the length of the uploaded file
                var percentLength = parseInt(document.getElementById(‘showProgress’).style.width)*percentDone/100;
                // Update the length of uploaded file
                document.getElementById(‘currentStatus’).style.width = Math.round(percentLength) + ‘px’;
                if(d.current < d.total) {
                  setTimeout(“getProgress();”,1000);
                }
                else {
                  document.getElementById(‘showProgress’).style.display = ‘none’;
                }
              }
            }
            else {
              document.getElementById(‘showProgress’).style.display = ‘none’;
            }
          }
          else {
            if(document.getElementById(‘upload-note’).innerHTML == ”) {
              setTimeout(“getProgress();”,1000);
            }
          }
        }
      }
      xmlhttp.open(‘GET’,url,true);
      xmlhttp.send(null);
    }

    In the middle we can see that it checks for the returned response. If response == “”, it means we made an ajax call even before the upload started. If response != “” AND response != “Success”, it means that the upload is in progress and we need to show the appropriate progress bar.

    Progress bar is calculated based on the statistics returned. I hope its quite a simple one and again self explainatory.

    The links which I found on internet were using hell lot of unnecessary things, just to make this progress bar. Some were using Yahoo’s YUI library, some JQuery and what not and I thought may be I should make it as simple as possible.

So thats it. Here you have your upload meter ready and running.

Download the source code from google code repository

svn checkout http://abhinavsingh.googlecode.com/svn/trunk/ abhinavsingh-read-only

Feel free to post a comment or suggestion for improvement. Or if in case the scripts doesn’t work for you.

Unfortunately I couldn’t provide a web demo as always for this one, as this site of mine is still on shared hosting and I was refused to install the apc package on the shared hosting. Anyways I have tested a enough on my VPS servers and it just works perfectly.

Enjoy and Thanks for reading till here 😉

My Interview with Yahoo-Inc! (Part 1)

Hello Friends,

Last month I was interviewed by Yahoo-Inc! for a job as software engineer. Here I would like to point out the discussions and various question/answer sessions I went through before I got my confirmation letter 🙂 Probably someone looking to join yahoo can take some tips from here.

In total I went through 7 rounds of interview (1 telephonic, 1 HR, 1 with Manager, 3 technical, 1 general aptitude). I will try my best to recall and summarize all of them for you all. But before I go ahead, I would like to thank my good friend Rajib Das for forwarding my resume in Yahoo and providing me with an opportunity to have a crack at it. Here I go:

  • Telephonic Interview: As it happens with all multinational firms, you go through a telephonic screening before you are actually called for a face-to-face interview. One good thing which happened for me even before the interview started was that, the interviewer already went through my CV thoroughly before interviewing me & he also checked my website Altertunes before interviewing me. You can be unlucky at times, if the interviewer comes with an open mind and try to test you in areas where you lack deep knowledge.

    My telephonic interview started early in the morning around 10 o’clock. It started with general about me questions. With my experiences I have learnt that these about me  sessions decide to a certain extent where your interview will head to. Hence, I always try to attract interviewer’s attention on my strong areas i.e. Audio Processing and web development.

    Next luckily for me he started discussing about Altertunes and various technologies used in developing the same. He specifically asked me questions like:

    1. How have you build the spell checker algorithm for Altertunes ?
    2. From where are you playing all the mp3 files ? Are they on your server ?
    3. If you have to, how will you implement the Orkut’s people connection algorithm ? i.e. If User A visits User C’s profile where User C is not a direct connection of User A, then Orkut shows a possible shortest connection. Something like this User A -> User B -> User C.
    4. What considerations have you taken while building the auto-suggest feature for Altertunes ?

    Though in my opinion a concrete answer do not exist for any of the above questions. There can be many possible solutions for every question he asked me. Here are my answers to his questions.

    1. I have used the spell checking algorithm as described by Peter Norvig, the director of research at Google in his post here. Many say, the 20 lines of code written by him in python is pure genius, and truly without any doubt it is one of the shortest and most efficient code that one can ever see. However for Altertunes, I have used a tweaked version of the same coded in PHP. For me the 20 lines code in python took 74 lines in PHP, however the results are just excellent for Altertunes. My spell checker for Altertunes gives over 90% accuracy for single word artists and over 80% accuracy for multiple word artists.
      Another simple but less accurate approach which I tried earlier was by using PHP’s inbuild function SOUNDEX, which is a phonetic algorithm for indexing names as sound, as pronounced in english. Read more about SOUNDEX here. However, the spell checker using SOUNDEX is not as accurate as the algorithm described by Peter Norvig.

    2. The answer to this question lies in one work Crawlers. I wrote crawlers in PERL which crawls the web for mp3 files and index them in the Altertunes database. However this answer didn’t satisfied the interviewer and he asked me Can you explain the architecture which you follow for developing crawlers? Probably he wanted to hear the word resolver from me, because as soon as I started telling him about resolvers he stopped me in between and proceeded to the next question. For more hint on how have I used PHP to develop web crawlers for Altertunes read here.
    3. Answer to the third question was probably hidden in the question itself. Shortest Path, is what we want hence we will obviously use one of the shortest path algorithm. As I didn’t had much knowledge on shortest path algorithms then, I suggested Dijkstra algorithm as the most appropriate for this task. However when I later discussed this problem with one of my friend, he told me probably Breath First Search (BFS) will be best suited for this problem.
    4. Here actually he asked me How have you developed the auto-suggest feature for Altertunes? For which I replied in one work AJAX. However, probably he wanted some more technical stuff on this topic and hence the next question he fired was What considerations have you taken while building the auto-suggest feature for Altertunes ? I still don’t really know what exactly was he looking for. My reply to him was, ‘I am sending each and every word typed in the input box to the server and getting response to all requests. However before sending the next request I wait for the previous response to come as I wanted my users to experience an incremental search.’

    I thought this was all that he will ask me for the telephonic interview, but ailaaa ! He started firing some questions from general algorithm and aptitude. A few questions which he further asked me were:

    • Given a tree, how will you create a mirror image of the tree? What algorithm will you use? What traversal will you prefer? 🙂
    • There is a link list, which contains a closed loop in it. How will you determine that closed loop in the link list? 🙂
    • Given a few numbers, how will you push them into a stack such that whenever I pop the top most element from that stack, I get the minimum number from the bunch. Also he wanted me to tell the pop push algorithm such that the order of insertion and popping should be O(1). 🙁
    • Given two log of wood which burns completely in 1 hour each. How will you determine 45 minutes.

    Hopefully this was all which I was asked in my telephonic interview. Within 10 minutes of the interview I received a call from the HR, asking me to come for a face-to-face interview which I scheduled for a week later. As I already got a feel of what all will be coming in the face-to-face interview, I didn’t wanted to go under prepared.

  • Face-to-Face Round 1: Before going for the in person interview, I tried my best to make myself familiar with the mother of all algorithm books by Cormen. You can download an e-copy of the same from here, size is about 10 Mb. Alternately you can search for -inurl:htm -inurl:html intitle:”index of” +(“/ebooks”|”/book”) +(chm|pdf|zip) +”cormenin google and get loads of sources for the same. You may change the search string to find other books from different formats. Anyways coming back to the interview.

    Just like my telephonic interview, the 1st round started at sharp 10 o’clock. The interviewer seemed liked a mixed bag to me. He tried to ask me questions ranging from C++, PERL, PHP, Java, Client-Server Model, Probability and even general aptitude. Here are a few questions which I can recall that were asked from me:

    1. Given a HTML page, how will you represent the same in XML format ?
    2. What are the advantages of Hidden Markov Model over other pattern recognition algorithms ?
    3. Yahoo is organizing an online programming competition and I am the head. There will be over a few million programmers participating in this contest. I have a set of 10 programming questions with me, which I give to each programmer one by one. As the programmer submits the solutions I check it, and if found perfect I give him the next question. Who-so-ever completes the 10 programming questions first is the winner. You have to award top 10 programmers. How will you go about developing such a system ? What all precautions will you take while developing such a system ? How many CPU will be required for such a system ? How will you protect the system from going down, in cases when a programmer tries to submit a virus as a solution ? etc etc
    4. Whats the probability that, my and your birthday lies on the same date and same day of the year ? (There were about 3-4 probability questions that he asked me)
    5. Draw and explain the whole client-server model ?
    6. Explain in detail, what all happens from the moment one submit a URL in the browser till the user sees the requested page on the browser?
    7. Write algorithms for Breath First Search (BFS) and Depth First Search (DFS) ? Which one is preferred over the other and why ?

    Then like the telephonic interview he fired almost the same set of questions over Altertunes. Probably there were a few more which I can’t recall at this point. Possibly the ones which I wasn’t able to reply. 😉 And that was it.

  • Face-to-Face Round 2: This was a complete session on aptitude level questions, which just kept coming one after the another. Some questions over which you can probably spend the whole day and say ‘This can be done the other way round too‘. Here are a few that I remember as of now:
    1. You have to weight all the weights between 1 and 100. Tell minimum number of weights required to do the same? (Probably the answer I gave was, weights which are a power of 2 i.e. 1,2,4,8,16,32 and 64)
    2. You have to weight all the weights between 1 and 100. Tell minimum number of weights required to do the same, however in this case you can use both pans to measure a particular weight ? For eg. If we need to weight 2 Kgs we can have 3 Kg weigh on one side and a 1 Kg + 2 Kg weight on the other side. (Probably the answer I gave was, weights which are a power of 3 i.e. 1,3,9,27…)
    3. You have a few eggs and there is a 100 level building. Determine the minimum number of attempts required to detect the floor from which, if we drop the egg it will break ? (Always consider the worst case that the egg will break at the top floor and for minimum attempts proceed from lower floor to top floor in non-uniform steps. Probably I was able to do this in 14 tries. Check if you can do the same :P)
    4. There is a huge string containing letters. Now in the string there are a lots and lots of palindromes. You need to find out the palindrome of the longest length. How will you do the same ? (Note: When I was reached the solution using stacks and queues, to complicate things he told me that a palindrome can further have a palindrome within it for eg. PALINDROMEDALADXYXDALADEMORDNILAP , hence we see the string has DALAD as a palindrome which is hidden in the full string which is a palindrome of bigger size.)
    5. There is a link list which have a lot of circular loops into it. How will you find the longest loop in the link list ?
    6. You have a very very large text file containing words. Consider that you can’t read it fully in the memory at once. How will you go about finding a word in the text file ?
    7. You have a very very large text file containing numbers. Consider that you can’t read it fully in the memory at once. How will you go about arranging the numbers in ascending or descending order ?
    8. A few questions on probability were discussed.

    There were a lot more which he asked from me. I guess there are easily 7-8 questions more that he asked from me. However this was the most interesting round that I had over the whole interview.

Probably thats enough for the first post. I will continue to write about my other rounds in upcoming posts. Till then if you have any questions or comments feel free to post them here.