Cogito, ergo sum

Here's hoping my musings can help you out!

Archive for June, 2009

Zend Framework URL helper

Posted by mnshankar on June 28, 2009

There are two URL helpers in the Zend Framework that help generate URLs from action and controller names:

  1. Action helper: This has the signature url($action, $controller = null, $module = null, array $params = null)
  2. View Helper: Signature url(array $urlOptions = array(), $name = null, $reset = false, $encode = true)

While using the Action helper, use the following code:

$url = $this->_helper->url(‘auth’,'login’);

Note that the controller and action are strings.

and, when using the View Helper function,

$url = $this->view->url(array(‘controller’=>’auth’,’action’=>’login’));

It is easy to mix up the syntax (And, if you do mixup, you will get an additional “/Array” at the end of the url .. voice of experience :-) )

Posted in Zend Framework | Tagged: , , | Leave a Comment »

Visual Studio 2005 on Windows Vista

Posted by mnshankar on June 27, 2009

The increased security constraints imposed by windows Vista make it almost impossible to accomplish anything running Visual Studio in the user mode. In fact, when you open visual studio in user mode, a message is displayed informing you that running VS as admin is a preferred approach (for full functionality).

There is a simple enough way to accomplish this. Right click on the Visual Studio icon, select properties, then the compatibility tab and click on the “Run this program as administrator” option.

image

Now, each time you try to launch visual studio, the little UAC box requests privilege escalation and finally opens up Studio with full permissions.

However, this is not how most users open up VS.. They click on the Solution file (.sln) or Project file and expect it to open VS. However, this does not work as expected (in fact, nothing happens when you attempt to launch a solution file!).

When you right click on a solution file and select the “Open with” option, you will see that it is set to open with “Microsoft Visual Studio Version Selector”

image

The VS Version selector is another executable located in:

C:\Program Files\Common Files\microsoft shared\MSEnv\VSLauncher.exe

My best guess is that this executable has a bug that prevents it from opening VS when devenv.exe is set to run with admin privileges. I also tried setting vslauncher.exe to run as admin. It just refuses to work.

So, I resorted to the next feasible option – change the”open with” to devenv.exe instead of vslauncher.exe- This works ok as long as you do not have to work with code written using other versions.. for example, to open up a solution written in vs2003.

Any other workaround for this annoying problem? Anybody?

Posted in .NET | Tagged: , , , , , | Leave a Comment »

Zend Paginator

Posted by mnshankar on June 12, 2009

The Zend Framework provides an extremely flexible component named Zend_Paginator to handle paginating your data to acceptable chunks. This class is capable of working with literally any collection.

The Zend_Paginator class provides a function named ‘factory’ that discovers the adapter type that it needs to invoke.. A few lines from the Paginator.php file are reproduced below:

public static function factory($data, $adapter = self::INTERNAL_ADAPTER,
                                   array $prefixPaths = null)
    {
        if ($adapter == self::INTERNAL_ADAPTER) {
            if (is_array($data)) {
                $adapter = ‘Array’;
            } else if ($data instanceof Zend_Db_Table_Select) {
                $adapter = ‘DbTableSelect’;
            } else if ($data instanceof Zend_Db_Select) {
                $adapter = ‘DbSelect’;
            } else if ($data instanceof Iterator) {
                $adapter = ‘Iterator’;
            } else if (is_integer($data)) {
                $adapter = ‘Null’;
            } else {
                $type = (is_object($data)) ? get_class($data) : gettype($data);
                /**
                 * @see Zend_Paginator_Exception
                 */
                require_once ‘Zend/Paginator/Exception.php’;
                throw new Zend_Paginator_Exception(‘No adapter for type ‘ . $type);
            }
        }

 

The basic syntax for using the zend_paginator component is

$paginator = Zend_Paginator::factory($collection);
$paginator->setCurrentPageNumber($this->_getParam(‘page’));
$paginator->setItemCountPerPage(10);
$this->view->paginator =$paginator;

The most common use of the paginator is in conjunction with data tables. Proper use of this component requires that you pass in a ’select’ object AND NOT THE COMPLETE DATASET. Please reread the previous sentence one more time if it did not sink in.. it really is the most critical aspect of using Zend_Paginator with database tables.

WRONG:

$users = new Users;
$data = $users->fetchAll();
$paginator = Zend_Paginator::factory($data);

Line 2 in the above code allocates memory for array $data and then initializes the paginator. So, if the Users table contains lots of rows, this will make your code extremely inefficient.

CORRECT:

$users = new Users;
$select = $users->select();
$paginator = Zend_Paginator::factory($select);

Here’s what my controller looks like:

<?php
class IndexController extends BaseController
{
   public function indexAction()
    {
        $users = new Users();
        $select = $users->select();
        $paginator = Zend_Paginator::factory($select);
        $paginator->setCurrentPageNumber($this->_getParam(‘page’));
        $paginator->setItemCountPerPage(10);
        $this->view->paginator =$paginator;
    }
}

?>

The view then takes the paginator object that is passed to it and renders the data – index.phtml:

<html>
<head>
  <meta http-equiv=”Content-Type” content=”text/html; charset=iso-8859-1″ />
  <title>ZendFramework Sample File</title>
<table border=”1″>
    <?php echo $this->partialLoop(‘partial-loops/user_display.phtml’, $this->paginator) ?>
</table>
<?php echo $this->paginationControl($this->paginator, ‘Sliding’, ‘pagination.phtml’); ?>
</head>
<body>
Welcome!
</body>
</html>

partialLoop is a view helper that is provided by the framework specifically for handling repetitive data. It takes the paginator object and properly formats the contents. The ‘views/scripts/partial-loops/user_display.phtml’ is really simple and looks like:

<tr>
<td><?php echo $this->username?></td>
<td><?php echo $this->user_type?></td>
</tr>

Note that $this in the context of the partialLoop is the collection/array itself.

The final piece of code is setting up the control that actually displays the page numbers with links at the bottom of the screen. This is done by the line

<?php echo $this->paginationControl($this->paginator, ‘Sliding’, ‘pagination.phtml’); ?>

The ‘views/scripts/pagination.phtml’ is as shown below:

<?php
//handle parameters during paging..
if ($this->pageCount)
{
    $params = Zend_Controller_Front::getInstance()->getRequest()->getParams();
    //remove the system params
    unset($params['module']);
    unset($params['controller']);
    unset($params['action']);
}
?>
<div id=”pagination-digg”>
<ul>
    <!– Previous page link –>
    <?php if (isset($this->previous)): ?>
    <li class=”previous”><a href=”<?php echo $this->url(array_merge($params,array(‘page’ => $this->previous))); ?>”>&lt; Previous</a></li>
    <?php else: ?>
        <li class=”previous-off”>&lt; Previous</li>
    <?php endif; ?>
    <!– Numbered page links –>
    <?php foreach ($this->pagesInRange as $page): ?>
        <?php if ($page != $this->current): ?>
    <li ><a href=”<?php echo $this->url(array_merge($params,array(‘page’ => $page))); ?>”><?php echo $page; ?></a></li>
        <?php else: ?>
            <?php echo “<li class=’active’>”.$page.”</li>”; ?>
        <?php endif; ?>
    <?php endforeach; ?>
    <!– Next page link –>
    <?php if (isset($this->next)): ?>
    <li class=”next”><a href=”<?php echo $this->url(array_merge($params,array(‘page’ => $this->next))); ?>”>Next &gt;</a></li>
    <?php else: ?>
    <li class=”next-off”>Next &gt;</li>
    <?php endif; ?>
</ul>
</div>

Notice the use of the $params variable to gather parameters being passed to the page. This approach allows you to share your pagination code throughout your application (as against passing the 4th ‘options’ parameter while invoking paginationControl). The parameters are then appended to the url using the array_merge() function. Simple enough..

Styling id’s are inserted at appropriate locations while generating the HTML.

Finally, the style sheet used to format the page links to look like those used on digg.com is listed below (pagination-digg.css):

#pagination-digg li{

border:0; margin:0; padding:0;
font-size:11px;
list-style:none;
margin-right:2px;

}
#pagination-digg a{

border:solid 1px #9aafe5;
margin-right:2px;
}
#pagination-digg .previous-off,
#pagination-digg .next-off {

border:solid 1px #DEDEDE;
color:#888888;
display:block;
float:left;
font-weight:bold;
margin-right:2px;
padding:3px 4px;
}
#pagination-digg .next a,
#pagination-digg .previous a {

font-weight:bold;
}
#pagination-digg .active{

background:#2e6ab1;
color:#FFFFFF;
font-weight:bold;
display:block;
float:left;
padding:4px 6px;
}
#pagination-digg a:link,
#pagination-digg a:visited {
color:#0e509e;
display:block;
float:left;
padding:3px 6px;
text-decoration:none;
}
#pagination-digg a:hover{

border:solid 1px #0e509e}

That’s pretty much all there is to it!

Posted in Zend Framework | Tagged: , , , , , | 1 Comment »

Using FlashMessenger

Posted by mnshankar on June 11, 2009

The Zend Framework offers us a scratchpad of sorts for passing messages to and from different controllers/actions. It is implemented as an action helper. It can be accessed by follows:

$flash = $this->_helper->getHelper(‘FlashMessenger’);

OR

$flash = $this->_helper->FlashMessenger;

Presented below is a structured approach to using FlashMessenger as an efficient “status message reporting system” on the beginning section of each page.

I invariably use a Base controller class which ALL my other action controllers extend. I find this to be an extremely slick way to enforce structure and reduce complexity. Moreover, it is recommended OOP.

Presenting basecontroller.php:

<?php

class BaseController extends Zend_Controller_Action {

    protected $db;
    protected $auth;
    protected $messenger;
    protected $logger;
    public function init()
    {
        $this->db=Zend_Db_Table::getDefaultAdapter();
        $this->view->baseUrl=Zend_Controller_Front::getInstance()->getBaseUrl();
        $this->auth=Zend_Auth::getInstance();
        $this->logger=Zend_Registry::get(‘logger’);
        $this->logger->setEventItem(‘username’, $this->auth->getIdentity());
       $this->messenger=$this->_helper->FlashMessenger;       
    }
   public function postDispatch()
    {
        $this->view->messages = $this->messenger->getCurrentMessages();
    }
}

?>

The sections used to initialize and use the flashmessenger object are indicated in bold.

In the init() function, a reference to the flashmessenger object is retrieved and assigned to the $messenger variable. By virtue of this being the base class, all the inherited classes now have access to this variable using $this->messenger.

When an action completes or when there is an event occurrence that you want displayed to the user, you can simply add that message onto the flashmessenger object like so:

$this->messenger->addMessage(‘Authentication Failed’);

Very Very Important : The getCurrentMessages() function on the messenger object is invoked in the postDispatch() method of the action controller. This is because you want the action method to execute, add the required messages onto the FlashMessenger and THEN display the messages when the view is displayed… got it? Gathering messages in the preDispatch() loop will not work as expected!

Once again, I cannot emphasize enough that understanding the Zend Framework flow is key to proper implementation.

Here is my loginAction script (in AuthController class)

class AuthController extends BaseController 
{

……

……

public function loginAction()
    {
        $request = $this->getRequest();
        if ($request->isPost())
        {
                $result = $this->auth->authenticate($authAdapter);
                if ($result->isValid())
                {
                    //Authenticated successfully
                    //Do what needs to be done
                    $this->_redirect($redirect);
                }
                else
                {
                    $this->messenger->addMessage(‘Login Failed..’);
                }
        }
        //Fall through and display the login.phtml page
    }

}

So, after loginAction() is executed, if the user supplied credentials are incorrect, the messenger contains the message “Login Failed..”

Ok.. onto the next step.. the Layout file. If you are not using Zend_Layout in your MVC app, you are missing a BIG service provided by the framework.. I strongly urge you to adapt a layout file.. It will make your apps so much easier. Also, it is trivial really to incorporate it in your project.

We will process ALL our messages in the layout so that messaging within the app becomes completely automated.. If you want to raise a message in any action, go ahead and use $this->messenger->addMessage() and when the view is displayed, messages are automatically displayed to the user.

Layout.phtml:

<div id=”mainContainer”>
<div id=”content”>
<h2 id=”secHeader” title=”Template Title”><span></span>Template Image</h2>
<ul>
<?php
foreach($this->messages as $msg)
{
    echo “<li>$msg</li>”;
}
?>
</ul>
<?php echo $this->layout()->content ?>

</div>
</div>

Our postDispatch() process copies all current messages onto a messages array in the view.. so simply iterate over that collection and display as a list (as there may be multiple messages)

That’s all there to it! Please feel free to drop me a line if you have any questions.

Posted in Zend Framework | Tagged: , , , , | Leave a Comment »

Excellent PHP IDE for Windows

Posted by mnshankar on June 8, 2009

I spend quite a lot of time coding in PHP using a windows (XP) workstation and am always on the lookout for better and faster IDE’s.. I was really excited when I learnt about VS.PHP – an IDE that integrates into VISUAL STUDIO!

This is beyond superb for me as I also do quite a bit of .NET programming with VS 2005! (VS.PHP also offers a ’stand alone’ version for folks who do not use Visual Studio)

I was really VERY impressed by my trial run of VS.PHP today.. It has everything that VS 2005 currently offers for .NET -Intellisense (YES!), Outlining, Snippets,Debugging.. and all in true visual studio style!

The software is free to try (30 days).. Beyond that, it costs $99 for a license… quite steep…The problem is that businesses (and individuals) don’t like to pay for IDE software these days, particularly if they’re using open source technologies like PHP.

Here are a couple of screen shots to give you an idea (I downloaded a trial version of VS.PHP 2.6) :

1. Creating a new project (Support for Zend MVC projects.. Yeah!)

image

2. The default code that gets generated for MVC projects

image

These files,  folders and contents can be easily customized too..

Navigate to the C:\Program Files\Jcx.Software\VS.Php\2005\2.6\ProjectTemplates\zend_mvc_files folder

The contents of this are copied verbatim when you create a new Zend_MVC project.. Go ahead and change these files as required! One of the first things I did was move the ‘config.ini’ file from the ‘html’ folder into the ‘application’ folder and change references accordingly in index.php (config files MUST NEVER be in a public facing folder)

3. Intellisense in action. Classes referenced by the require_once directive (underlined in fig) show automatically up in the drop down…Also, when you reference a ZF class in your file without including the file explicitly, VS.Php will find the file and provide intellisense support (i.e. you wont have intellisense for the first line in which you reference the ZF class.. but will in subsequent lines).

image

4. Debug is as simple as hitting F5

image

Tutorials and ample documentation are available on their web site.. but seriously, if you are familiar with the visual studio interface and its controls/shortcuts, you should be all set. They even supply a copy of apache with the software so the debug process works right out of the box! Absolutely no configuration required, No setting up virtual directories, no messing with .INI files.. Just hit the Run or Debug button on Visual Studio and it handles the rest..  really awesome!

So far, I have been using the Eclipse PDT IDE.. but I think VS.PHP has enough great features to make me switch… And, did I mention it runs from within Visual Studio?

Posted in Zend Framework | Tagged: , , , , , | 1 Comment »

Custom query on Microsoft SMS Server

Posted by mnshankar on June 8, 2009

Here is the SQL server custom query that I use to list UserName, Model, Manufacturer, Serial Number, Mac Address and IP_Address of all workstations (that have the sms client installed) :

SELECT     SIS.ResourceID, SYS.User_Name0, SYS.Name0, CS.Model0, CS.Manufacturer0, PB.SerialNumber0, SIS.SMS_Installed_Sites0, MAC.MAC_Addresses0, IP.IP_Addresses0
FROM         dbo.v_RA_System_SMSInstalledSites AS SIS INNER JOIN
                      dbo.v_R_System AS SYS ON SIS.ResourceID = SYS.ResourceID INNER JOIN
                      dbo.v_GS_COMPUTER_SYSTEM AS CS ON CS.ResourceID = SIS.ResourceID INNER JOIN
                      dbo.v_GS_PC_BIOS AS PB ON PB.ResourceID = SIS.ResourceID INNER JOIN
                      dbo.v_RA_System_IPAddresses AS IP ON IP.ResourceID = SIS.ResourceID INNER JOIN
                      dbo.v_RA_System_MACAddresses AS MAC ON SIS.ResourceID = MAC.ResourceID
WHERE     (SYS.Client_Type0 = 1) AND (SYS.Active0 = 1) AND (NOT (IP.IP_Addresses0 LIKE ‘192.168%’)) AND (NOT (IP.IP_Addresses0 LIKE ‘0.0%’))

Posted in Database | Tagged: , , | Leave a Comment »

Logging in Zend Framework (Zend_Log & Zend_Log_Writer_Db)

Posted by mnshankar on June 6, 2009

Adding logging capability to your application is an important step towards enhanced security and efficient troubleshooting. The Zend framework makes it really easy to incorporate logging.

The main class for Logging is the Zend_Log class. In order to accomplish the ‘actual writing’ to log, you need to make use of a ‘writer’ class. The writer class encapsulates algorithms to write to different destinations. For example,

  1. Zend_Log_Writer_Stream - Write to flat file
  2. Zend_Log_Writer_Db - Write to a database table
  3. Zend_Log_Writer_Firebug - Write to firebug console
  4. Zend_Log_Writer_Mail - Send out emails using the Zend_Mail component

This concept is akin to using different adapters for Zend_Auth.

My personal preference is to use Zend_Log_Writer_Db. This is mainly because a database table offers much greater flexibility in searching (querying) for events of importance than a flat file. Also, when using files for logging, the webserver must have write permissions on the folder housing the log file(s).

Step1 : Create the database table to hold log entries

CREATE TABLE `log_table` (
`priority` varchar(50) default NULL,
`message` varchar(100) default NULL,
`timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
`username` varchar(40) default NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1

Whenever a log event is raised, the following keys are made available to us automagically by the framework: timestamp, message, priority, and priorityName.

Of course custom fields may be added to the default array.. In this example, I have added the username field.

Step2: Add the required initialization lines in the bootstrapper file (index.php)

The basic syntax is to first create a Zend_Log_Writer_Db object :
$writer = new Zend_Log_Writer_Db($db, ‘log_table’, $columnMapping);

Then, pass that writer object to a Zend_Log instance like so:
$logger = new Zend_Log($writer);

Note the use of a $columnMapping parameter. This is an array that maps table column names to fields in the event array. In our case, we could define it as:

$columnMapping = array(‘priority’ => ‘priority’, ‘message’ => ‘message’,
‘timestamp’ => ‘timestamp’, ‘username’ => ‘username’
);

The setEventItem() method of the Zend_Log object is used to add custom fields into the event array.
The final code in index.php is :

// Set up the logging system and put it in the Zend Registry.
$columnMapping = array(‘priority’ => ‘priority’, ‘message’ => ‘message’,
‘timestamp’ => ‘timestamp’, ‘username’ => ‘username’
);
$logger = new Zend_Log(new Zend_Log_Writer_Db($db, ‘log_table’, $columnMapping));
Zend_Registry::set(‘logger’,$logger);

Note that the setEventItem() function can be invoked at a later time when the data is actually available. I use the following code to assign the username in my base action controller

$this->logger->setEventItem(‘username’, $this->auth->getIdentity());

Step 3: Isolating common code

Those of you who have read my earlier posts, know that I prefer isolating all common code into a base controller for global use. Continuing with that philosophy, the base controller is now modified as :

<?php
class BaseController extends Zend_Controller_Action
{
protected $db;
protected $auth;
protected $messenger;
protected $logger;
public function init()
{
$this->db = Zend_Db_Table::getDefaultAdapter();
$this->view->baseUrl = Zend_Controller_Front::getInstance()->getBaseUrl();
$this->auth=Zend_Auth::getInstance();
$this->logger=Zend_Registry::get(‘logger’);
$this->logger->setEventItem(‘username’, $this->auth->getIdentity());

$this->messenger=$this->_helper->FlashMessenger;
}
public function postDispatch()
{
$this->view->messages = $this->messenger->getCurrentMessages();
}
}
?>

Simple enough.. The logger object is retrieved from the Zend_Registry and the ‘username’ field is assigned a value from the instance of Zend_Auth. The logger object is also available in every controller that inherits from the Base_Controller using $this->logger

Step 4: Writing a log entry

The final step is to actually record data in our log_table. This is as easy as adding the following line at any point in your action script:

$this->logger->info(‘Login Successful’);

This is what log_table looks like after a successful log entry:

image

As always, please feel free to leave comments or any questions that you may have. Also, take a look at the Zend frame work documentation for additional information regarding logging.

Posted in Zend Framework | Tagged: , , , | Leave a Comment »

Moving on From Live Spaces

Posted by mnshankar on June 2, 2009

I have been using Windows Spaces for almost a year now and have been waiting patiently for several feature improvements.. Most notably

  1. Ability for anonymous users to leave comments
  2. Better statistics reporting
  3. Greater degree of support from Non IE browsers

Today, I decided that it is time to move on to a better service. After lots of searching, I finally landed on “WordPress”. I thought I would have a hard time exporting my posts from spaces(live.com).. but this website has very good information on porting blogs out of Live Spaces.

1. Go into your Spaces account – General settings and change the default date format to mm/dd/yy like so:

untitled

2. Download the ‘live-space-mover’ application. This contains the python file that emits XML for our import process

3. Download Python 2.6.2 Windows installer. Accept the default settings and install Python on your computer. The python interpreter is required to execute .py files. It installed to C:\Python26 on my computer. This directory location is important!

4. Download the ‘BeautifulSoup’ python parser. This is a library that is invoked from live-space-mover to actually go to the spaces site and download blogs (the XML file just contains hyperlinks). I used version 3.0.6 and it worked perfectly!

5. Now, Move the BeautifulSoup file and the ‘Line-Space-Mover.py’ file into the C:\Python26 folder like so:

image

6. Open a command window (start->run->cmd) and navigate to C:\Python26. Then, type in the following command:

python live-space-mover.py -s http://yourid.spaces.live.com/

If the process ran correctly, you will get a ‘success’ message and an XML file will be created in the directory C:\Python26. (If there was an error message regarding the date/time format, please make sure you executed Step 1 correctly.

7. Once you have the XML file, you are ready to have WordPress import your Spaces blogs. Create an account at WordPress.com

8. After logging in to to your account, in the dashboard, click on Tools->Import

image

9. Click on ‘WordPress’. Then Click on the ‘Browse’ button and point to the newly created XML file (from step6)

image

10. Click on ‘Upload file and Import’ button.. All your blog postings will be transferred over!

If you are looking for an awesome client to help manage your blogs, look no further.. download Windows Live Writer. It is capable of interacting with various blogging services and WordPress is one of them. Happy blogging!

Posted in Personal | Tagged: , , , , | Leave a Comment »