Usage of Zend_Http_Client is pretty straight-forward:

$client = new Zend_Http_Client($uri);
$client->request(Zend_Http_Client::HEAD); // HTTP HEAD request

However, today, on my Ubuntu box I had real problems as HTTP client constantly ended in segmentation fault (SIGTERM in apache logs). When debugging, I noticed that it does so only if $uri contains so called «unwise» characters, such as spaces, «{«, «}», «^» etc.

Going deeper, I reviewed the source code of Zend_Http_Client::setUri($uri) method, only to discover that it relies on Zend_Uri::factory($uri), to initialize the URLs. From there it was pretty simple. Zend_Uri is aware of «unwise» chars problem and disallows them by default (why exception thrown by Zend_Uri ended in SIGTERM is yet to discover, however). In order to allow such a characters:

Zend_Uri::setConfig(array('allow_unwise' => true));
$client = new Zend_Http_Client($uri); // $uri may contain unwise chars now

After issuing above instruction Zend_Uri accepts those unwisely formed URIs. Plus, you have to URL-encode white-spaces (i.e. make sure that white-spaces in query string, or actually in URI part after the host name are replaced with «%20″ char) to make them acceptable.

Further info available in offical documentation.

Please note, that I still think that having unreliable chars in URI is really bad practice. If you work with some system that already gone far on this path, it’s nice to have a method to actually consume such a wildly formed URIs. Kudos to Zend_Uri maintainers!

,

I have used ZF in several projects, and think is is quite safe to use svn:externals to attach Zend and ZendX as external dependency. It might not be the good idea for other projects, but when it comes to ZF – what is in trunk is pretty stable.

So, go into folder which stores ZF, and safely remove the library. Then just add ZF as external dependency (which would be updated every time you update the working copy):

svn pe svn:externals .

in and editor opened, enter the dependencies:

Zend http://framework.zend.com/svn/framework/standard/trunk/library/Zend
ZendX http://framework.zend.com/svn/framework/extras/trunk/library/ZendX

finally commit everything and obtain.

svn ci -m 'ZF set as external dep'
svn up

The beauty of this approach – you always have up to date version of ZF.
The danger of this approach – you always have up to date version of ZF!

Word of caution:
Sometimes this may break things (when backward-compatibility is broken in ZF trunk), but actually if you have unit tests which check your build before deploying, you are pretty safe – you spot the problem, you resolve it.

NB: This approach supposes that you tag your releases, so that when new release is coming out, you create a tag, export everything into newly created tag (thus freezing the code), and checkout from tag on production server.

,

I have finally completed proposal for Authorize.net CIM API. Hopefully, this API gets included into ZF (in one form or another), as ANet is one of the best services to work with user payment profiles, let alone CC processing. On proposal page you can review use cases, and if you are interested in internals feel free to download fully-working component’s prototype (it is still a prototype as most probably it would be updated in accordance with peer review on ZF wiki).

Let me know your suggestions on how the component can be improved.

,

Rendering view script for particular controller action is really easy. Indeed, thanks to (enabled by default) ViewRenderer helper, scripts are auto-loaded: renderer searches script directory(ies) for a view script called CONTROLLER_NAME/ACTION_NAME.SCRIPT_EXTENSION once found, view is auto-rendered.

However, sometimes it’s not what you want, instead you need to render some other view depending on some internal criteria. For example, you may want to render some custom error displaying view. So, if we are positive on what we want, let me show you how to do it:

class TestController extends Zend_Controller_Action
{
    /**
     * test/index.phtml would be rendered by default
     * @return void
     */
    public function indexAction()
    {
        // render test/foo.phtml
        $this->_helper->viewRenderer('foo');

        // render bar/foo.phtml to the default response segment, without using a
        // controller view script subdirectory ("test" in this case):
        // so you may use scripts from other controllers
        $this->_helper->viewRenderer('bar/foo', null, true);

        // now render the script, as previous calls do not render anything,
        // they are just used so that default script is swapped and not rendered:
        $this->render('foo');
        // OR
        $this->render('bar/foo', null, true);
    }
}

Please, note that you do not need to provide view extension (foo but not foo.phtml or any extension you happen to use for your views) – what renderer expects is action name, and we simply swapping the current action. Internally, direct() method is called when you update view renderer, which in turn is proxy for setRender():

// allows you to set any of scriptAction, responseSegment,
// and noController in one pass.
setRender($action = null, $name = null, $noController = false)

So, you may use

$this->_helper->viewRenderer->setRender('foo');

to change current view, but this form is less common, as it requires more typing :)
NB: If you need more info on ViewRenderer there’s no better place but ZF Manual.

Zend Framework (ZF) is the MVC framework. Of course you can use its components in a non-MVC way (and I actually do so in my WP UMapper plugin), but in that case, I suppose, you do not have to worry about models auto-loading.

Frameworks make our coding life easier, and ZF is not an exception – you need very little code to get your application skeleton working. And when it comes to MVC, ZF handles almost everything – your action controllers are triggered, your views are loaded, w/o you having to worry about them. Not the same with models. If you comply to directory layout advised by ZF, you have «models» folder, but framework doesn’t interact with it in any way.

Models are simply classes, containing application logic, and to initialize one of them you have to make sure that:
a) containing directory is withing include_path
b) you require_once the class file before using it

I wanted my models to be available without any additional hassle, so I decided to find a way to auto-load models from within my controller actions.

Read the rest of this entry

, ,