home | contact us
» Archive by category "zend framework"

category: zend framework


I have recently been working on a Magento project that required a custom API integration with Zen Desk.

Magento is based on Zend Framework which is nice because it means we can use the Zend_Rest_Client object to handle the API integration which provides a nice layer of abstraction and sorts out a lot of the heavy lifting required.

However I came across a terminal issue trying to get it working properly with HTTP Basic Authentication which the Zen Desk API uses.

I found some instructions which recommended creating a Zend_Uri_Http object and then setting the username and password against this. However as Zen Desk uses the email address as the username component, this failed completely.

In the end the solution I found was to grab the static HTTP client object that the REST client is built upon and call the public setAuth method on this. This way the Authorisation header is correctly created, encoded and appended to the headers.

Logically it feels like a dirty way to do things, grabbing the HTTP client statically to do this, but it works and I can’t see how else you would do it.

For info here is the code:

/**
     * @return Zend_Rest_Client 
     */
    protected function getClient() {
        if (null === $this->_client) {
            $url = $this->getApiUrl();
            $uri = Zend_Uri_Http::fromString($url);
            $this->_client = new Zend_Rest_Client($uri);
            Zend_Service_Abstract::getHttpClient()->setAuth($this->getUsername(),$this->getPassword());
        }
        return $this->_client;
    }

 

If you encounter the error :

Invalid bind-variable name xxxxxx

When trying to use named bound parameters with Zend Framework, then you are probably using the Mysqli adapter. Unfortunately this doesn’t actually support named parameters, but the Exception message isn’t really clear on that, despite being thrown in this block of code:

 } else if ($val[0] == ':') {
	if ($this->_adapter->supportsParameters('named') === false) {
		/**
		 * @see Zend_Db_Statement_Exception
		 */
		require_once 'Zend/Db/Statement/Exception.php';
		throw new Zend_Db_Statement_Exception("Invalid bind-variable name '$val'");
	}
}

The Exception should really say:

You are trying to use named parameters with an adapter that doesn’t support them

The solution is easy, just switch your adapter from Mysqli to Pdo_Mysql


 

If you use Zend_Db_Statements directly as well as using the Zend_Db_Table family of classes for Active Record et al then you might find the following little tip useful.

By default, if you run a query using something like

 public function query($sql, $params=false) {
	if(empty($params)) {
		$stmt = $this->getAdapter()->query($sql);
	}else {
		$stmt = $this->getAdapter()->query($sql, $params);
	}
	return $stmt;
}

then every time you call your query method, you will be preparing the statement again.

Of course that’s not really a good idea if you are repeating the same query multiple times simply changing the parameters to be passed in.

In that kind of scenario you can do something like this:

$stmt = $db->query($sql, $params);
$result1 = $stmt->fetch();
$stmt->execute($params2);
$result2 = $stmt->fetch();

Heres an example of a chunk of code that is working out a category path from an ecommerce system for a particular category id.

$stmt = $db->query("select c.parent_id, cd.categories_name from categories c join categories_description cd using(categories_id) 
where categories_id = ?", array($categories_id));
while(false!==($r=$stmt->fetch())){
	$categoryString[]=$r['categories_name'];
	if($r['parent_id']==0){
		break;
	}
//Note this bit - we are just re executing the statement with some new parameters.
	$stmt->execute(array($r['parent_id']));
}

This tip alone can add a lot of speed if you are doing repetitive statements


 

Currently working on a big Zend Framework project so I though I would have a breather and do a little blog post targeted at anyone looking for a UK based Zend Framework developer.

I’ve built a few Zend Framework based systems and have found it a fun system to work with, especially on the more recent versions of the library. There have been a few hurdles along the way and I have definitely improved my object oriented PHP development skills a lot since I first had a go at the Zend Framework quick start way back when.

I chose to learn Zend Framework primarily because Magento is based on it, and Magento is the ecommerce platform that I have chosen to specialise in. Since then though I have found that Zend Framework has a definite place for me, especially when coding more heavy duty data processing applications.

For simple web sites I would tend more towards using Symfony or my own lightweight MVC framework for very simple sites. For me Zend Framework really shines when you need to do something a little different that doesn’t easily fit into the mold specified by the Symfony code creation tools.

So to conclude, if you are looking for a PHP web developer who specialises in Zend Framework and particularly if you would prefer a UK based Zend Framework specialist then get in touch with us today.


 

With some trepidation I decided that I really had to implement pagination into a Zend Framework project I am working on. Zend Framework is great, but some of the sections can be a little tricky to get your head around at first attempt.

However, less than an hour after first looking at it, I have now got my system spitting out results in a nicely paginated ten at a time. The documentation on the Zend Framework reference is a little sparse but suffice to say that if you are using Zend_Db then actually its pretty easy.

The only bit that is a little tricky is getting the actual page controls to display, as you are left to code your own (though they do supply some code).

One major irritation with the Zend Framework reference guide is that I seem to be unable to copy and paste the code examples, it ends up looking like this:

      <!--
   2.
      See http://developer.yahoo.com/ypatterns/pattern.php?pattern=searchpagination
   3.
      -->
   4.
       
   5.
      <?php if ($this->pageCount): ?>
   6.
      <div class="paginationControl">
   7.
      <!-- Previous page link -->
   8.
      <?php if (isset($this->previous)): ?>
   9.
        <a href="<?php echo $this->url(array('page' => $this->previous)); ?>">
  10.
          &lt; Previous
  11.
        </a> |
  12.

note the line numbers, great.

this tutorial was really useful though:

Here is some code snippets:

Controller

    public function viewAction(){        
        $this->view->input = $input = $this->_request->getPost('search');
        $paginator = $this->_model->tableSearchAllPaginator($input);
        $paginator->setCurrentPageNumber($this->_getParam('page'));
        $this->view->paginator = $paginator;
    }

Model


    public function tableSearchAllPaginator($input, $fields_to_select=null){
        $table = $this->getTable();
        $select = $table->select();
        $fields = $table->info(Zend_Db_Table_Abstract::COLS);
        if(!empty($input)) {
            foreach($fields as $field) {
                $select->orWhere("$field like ?", "%$input%");
            }
        }
        if(!empty($fields_to_select)) {
            $select->columns($fields_to_select);
        }
        $paginator = new Zend_Paginator(new Zend_Paginator_Adapter_DbTableSelect($select));
        return $paginator;
    }

View Script

echo $this->partial('_viewtable_page.phtml', array('paginator'=>$this->paginator, 'controller'=>'products'));

View Table Page Partial

if (count($this->paginator)) {
    echo '<h4>Found ' . count($this->paginator) . ' Results</h4>';
    echo '<table class="grid">';
    foreach($this->paginator as $k=>$row) {
        //EC_Debug::dump($k);
        $row = $row->toArray();
        //EC_Debug::diedump($row);
        if($k == 0) {
            echo '<tr>';
            foreach($row as $f=>$v) {
                echo "<th>$f</th>";
            }
            echo '</tr>';
        }
        echo '<tr>';
        foreach($row as $f=>$v) {
            $extra = '';
            if($f=='id') {
                $extra = '<a href="' . $this->url(array('controller'=>$this->controller, 'action'=>'edit', 'id'=>$v), null, true) . '"><img src="' . $this->baseUrl() . '/style/icons/application_edit.png" border="0" alt="edit"></a>';
                $extra .= ' <a href="' . $this->url(array('controller'=>$this->controller, 'action'=>'delete', 'id'=>$v), null, true) . '"><img src="' . $this->baseUrl() . '/style/icons/cancel.png" border="0" alt="delete"></a>';
            }
            echo "<td>$extra $v</td>";
        }
        echo '</tr>';
    }
    echo '</table>';
    echo $this->paginationControl($this->paginator, 'Sliding', '_paginator.php');
}else{
    echo 'no results...';
}

Pagination Controls Partial

<?php if ($this->pageCount): ?>
<div class="pagination">

<?php if (isset($this->previous)): ?>
  <a href="<?= $this->url(array('page' => $this->previous)); ?>">&laquo; PREV</a> -
<?php endif; ?>

<?php
    /* Page links */

    foreach ($this->pagesInRange as $page): ?>
    <a href="<?= $this->url(array('page' => $page)); ?>" <?php if($page == $this->current): ?>id="selected"><?php endif; ?><?= $page; ?></a>
<?php endforeach; ?>

<?php if (isset($this->next)): ?>
 - <a href="<?= $this->url(array('page' => $this->next)); ?>">Next &gt;</a>
<?php endif; ?>

</div>
<?php endif; ?>

 

If you develop using Zend Framework you will know that it is sometimes tricky to see exactly whats going on in terms of SQL queries. After trying a few different ideas including subclassing the database classes or other complex systems, the easiest I have found is this:

1. Edit your app.ini config file and add a line:

db_profiling_enabled = false

Then in your development section in your ini file, set the same value to true

2. Add the following lines to your bootstrap.php after the database adapter setup.

// DATABASE ADAPTER - Setup the database adapter
// Zend_Db implements a factory interface that allows developers to pass in an 
// adapter name and some parameters that will create an appropriate database 
// adapter object.  In this instance, we will be using the values found in the 
// "database" section of the configuration obj.
$dbAdapter = Zend_Db::factory($configuration->database);
//$dbAdapter = new EC_Db_Mysqli($configuration->database->params);


if($configuration->db_profiling_enabled){
    // create a new profiler
    $profiler = new Zend_Db_Profiler_Firebug('EdmondsCommerce DB Queries Debug');
    // enable profiling (this is only recommended in development mode, disable this in production mode)
    $profiler->setEnabled(true);
    // add the profiler to the database object
    $dbAdapter->setProfiler($profiler);
}

Note you may need to move this chunk above the database adapter section:

// CONFIGURATION - Setup the configuration object
// The Zend_Config_Ini component will parse the ini file, and resolve all of
// the values for the given section.  Here we will be using the section name
// that corresponds to the APP's Environment
$configuration = new Zend_Config_Ini(
    APPLICATION_PATH . '/config/app.ini', 
    APPLICATION_ENVIRONMENT
);

This is based on a modified quickstart layout for a project. If you have decided to use an alternative layout, you should be able to tell where the relevant code should be.

You will need to have the Firebug firefox extension to view this output. If you also install the FirePHP extension for firebug then there are even more cool things that you can do.


 

After losing an afternoon trying to get my extended Zend Dojo Form class to give me HTML array notation, I have finally found a solution that works. To celebrate I’ve decided to share it should anyone else suffer a similar problem.

Here is the method:

public function addSubFormEl($subFormName, $addElOptions){
        call_user_func_array(array($this,'addElement'), $addElOptions);
        $this->getElement($addElOptions[0])->setBelongsTo($subFormName);
    }

In one move, this creates the element and assigns it to a HTML array of the name $subFormName. Evidently I am using this with sub forms but there is no reason why you should have to do that.


 

Problem:
You are dutifully setting your size attribute in your Zend Form class and you input elements are being rendered with that size attribute. However if Javascript is enabled and you are using Dojo for your forms, the size attribute gets dropped.

Solution:
To set the width on dojo form elements you must use the width css operator. eg

$form->getElement('blah')->setAttrib('style'=>'width: 50em;');

So simple once you know how!

More…


 

If like me you kicked off your Zend Framework experience with the Quick Start and have kept the error controller system of the Quick Start for your other ZF projects, you might find this little snippet useful.

The Quick Start uses the Exception::getTraceAsString() method to give you the stack trace. Unfortunately this function seems to snip off a bit of useful info.. almost tantalising you with the info but not quite giving you enough to actually know what is going wrong!

To get a more detailed stack trace, I recommend changing this and using the Exception::getTrace() function which returns and array of the trace. You can then echo out all of this info in full.

For me (as I have xdebug for my dev environment, which is the only place you should be dumping stack traces anyway) I use the following chunk of code in my views/scripts/error/error.phtml

<? // application/views/scripts/error/error.phtml ?>

<h1>An error occurred</h1> 
<h2><?= $this->message ?></h2> 

<? if ('production' != $this->env): ?>
    <h3>Exception information:</h3> 
    <p> 
        <b>Message:</b> <?= $this->exception->getMessage() ?> 
    </p> 
    <h3>Request Parameters:</h3> 
    

		



    <h3>Stack Trace 2:</h3>
    <?php
    foreach($this->exception->getTrace() as $t){
        var_dump($t);
    }
    ?>
<? endif ?>


 

I have recently been messing around trying to figure out the best way of running long processes within a Zend Framework App.

Usually I would code in regular flush(); commands to make sure that the browser didnt time out and also that the user can see that something is happening.

However, the standard MVC structure of the default ZF application system wraps the entire response in an output buffer which is only flushed once everything is done. This has lots of advantages including allowing to add extra headers (FirePHP) on the fly throughout the application process.

For long running scripts though, it is important for me to flush output. My solution to this is twofold.

Firstly set up an ‘output’ action in my base controller. The output action is looking for an ‘act’ parameter in its view script. This act param is then used to generate a url string based on the current controller and the action as the act param. This url string is then used to create an iframe which will be used to output the flushing results of the long running script.

For the long running script action itself, I am going to disable layout and also disable view render. Its really important to switch both of these off.

The following needs to be declared at the top of any action that you intend to be viewed via the output iframe.

    // accessed via output action
    public function longrunningAction(){
        $this->_helper->layout->disableLayout();
        $this->_helper->viewRenderer->setNoRender(true);
        $this->_model->grabImages();
    }

Now I am free to echo out basic HTML and also call flush from within my model. To flush the output you need to call both ob_flush() and then flush(). To make this easier I set up a static method in my static Tools class

    public static function flush(){
        ob_flush();
        flush();
    }

One issue I have had though is that any time the ZF internals try to add a header, you will get a basically meaningless exception telling you that headers have already been sent. It doesn’t tell you what header was attempted to be added or why, so you can be left out in the cold a bit when trying to debug.

If anyone knows a good workaround for this, or can offer a better solution for handling these long running processes I would love to hear about it.

More…


 
rss icon