Tag: zend

If you’re coding for the web, you almost certainly have encountered frameworks that make use of the Dependency Injection Container. Incredibly useful – but what is it?

In the most simplistic way – it’s just a great big bag of stuff. That’s it. There’s nothing magical about the container, it’s simply an object that stores references to other objects. Combined with a liberal use of Interfaces, this allows for a high level of abstraction and therefore also aids in unit testing smaller code parts.

For example, if you’re injecting the entire DIC into a component, you are metaphorically handing that component a great big bag of stuff and saying “here’s what we have to work with. Ask for it by name.” The component may then access the container and all configured dependencies.

You may well now be saying “well that sounds a bit like code soup” – and you’d be right. Normally, you’d only inject the dependencies that a component requires (and not the whole bag). The major frameworks (e.g. Laravel, Symfony, Zend) feature Dependency Injection Containers and an associated service locator and dependency manager. These are no longer simply “great big bags of stuff“, but true DI systems that allow for a high level of abstraction.

For a super simple Dependency Injection Container, see Pimple (by Sensio Labs). This is a great place to get started with understanding how a system will utilise a DIC. It is super simple, and forces you to understand how things are bootstrapped and provided for your system.

For more detailed information on dependency injection, see these links:

I don’t normally plug work that I do in my daily grind, but this one is for super-great cause. Instead of our usual advertising selves, we’re using our powers for good and completely upgrading the National Breast Cancer Foundation‘s Pink Ribbon Breakfast site. Their goal is to have 0 deaths by 2030, which is a pretty nice goal all-round.

Are you using Zend? Do you have only a core controller and don’t need extraneous URL parameters? Try this.

Most of the time, I am using Zend Framework to its (mostly) full capacity. Models, Controllers, View Helpers – the whole box-and-dice. However, there has been several occasions where I’ve only needed a single controller serving up mostly static pages, or pages leveraging an external service.

The biggest problem that arises in this case when using the default Zend Router, is that action names are treated as controller names. I don’t know about you, but I personally hate seeing http://example.com/index/my-action when what I actually want to see is http://example.com/my-action.

Here’s a nice way to completely tidy up all your actions, serving them from a single controller. (I use a Bootstrap file to initialise my application):

PHP

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

/**

* Set up routers for the system

*

* @return void

**/

protectedfunction_initRouters()

{

$router=Zend_Controller_Front::getInstance()->getRouter();

$route=newZend_Controller_Router_Route(

':action/*',

array(

'controller'=>'index',

'action'=>'index'

)

);

$router->addRoute('default',$route);

}

This basically says that my first parameter is always going to be an action name, and everything else is to be parsed as normal. I set request defaults in the array. In this case, the default controller is “index”. This allows everything to be passed straight through to my IndexController.

Addtionally, if you are using modules and want to retain routing for these also (for example, a one-controller site with an admin module), you can add this route rule to your system:

PHP

1

2

3

4

5

6

7

8

$route=newZend_Controller_Router_Route(

'admin/*',

array(

'module'=>'admin'

)

);

$router->addRoute('admin',$route);

This says that anything starting with “admin” needs to be routed to the admin module, and the rest of the URL is to be parsed as normal.

That’s it! This will allow you to route all requests to a single controller for the front-end, and still maintain a complete module for the administration on the back-end.

Hopefully this cleared up some things for others, as I found the Zend Framework documentation to be quite dismal.

Probably one of the more useful things you can do with memcache is drop it into Zend Framework. Here’s how I did that.

Following on from the previous post, here is an example of how you can set up memcache to serve as a cache for your Zend project.

I like to use the method style of bootstrapping my application, so here’s the function that builds the cache for me.

PHP

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

/**

* Set up caching using memcache

*

* @return void

**/

protectedfunction_initMemcache()

{

if(extension_loaded('memcache'))

{

// Configure caching backend strategy

$cacheBackend=newZend_Cache_Backend_Memcached(

array(

'servers'=>array(

array(

'host'=>'127.0.0.1',

'port'=>'11211'

)

// Other servers here

),

'compression'=>true,

'compatibility'=>true

)

);

// Configure caching frontend strategy

$cacheFrontend=newZend_Cache_Core(

array(

'caching'=>true,

'cache_id_prefix'=>'MyApp_',

'write_control'=>true,

'automatic_serialization'=>true,

'ignore_user_abort'=>true

)

);

// Build a caching object

$memcache=Zend_Cache::factory($cacheFrontend,$cacheBackend);

Zend_Registry::set('cache',$memcache);

}else{

// Handle a non-existent extension here

}

}

Originally, I was getting the “Memcache::addServer function expects at most 6 parameters, 8 given” warning. To force Zend to play nice with memcache (and send the right parameter count), you need to make sure you have the compatibility option set to true in the backend options array.

Here’s an example on how to use:

PHP

1

2

3

4

5

6

7

8

$cache=Zend_Registry::get('cache');

if(!$request=$cache->load('dataset')){

$request=LargeQueryOrDataset();

$cache->save($request,'dataset');

}

var_dump($request);

Hope this helps in getting started with Zend_Cache (even on a technology as old as memcache).

Getting Zend to return JSON data can be tricky at times. The JSON helper likes to send the ‘official’ JSON header (application/json), and most browsers are treating that as a download link, resulting in no data to the client and an unfortunate download box.

To bypass this default behaviour, you’ll need to tell the controller how to serve your JSON data:

PHP

1

2

3

4

5

6

7

8

9

10

11

12

// In your controller

publicfunctionoutputAsJSON()

{

$content=$some_var;

$this->getResponse()

->setHeader('Content-Type','text/html')

->setBody(json_encode($content))

->sendResponse();

exit;

}

The key part of this stub is the exit; line. It prevents the view renderer from sending anything, keeping your JSON data intact. Note: json_encode and json_decode only works from PHP version 5.2.1

To output all of your view’s variables in this way, replace $some_var; with:

PHP

1

json_encode($this->view->getVars());

Hopefully this saved someone a headache or two when dealing with Zend’s puzzling JSON implementation.

What this snippet does is initialise two related caches – a core cache, and a page cache. The core cache (in this instance) is attached to our database table abstract class, which allows results to be stored as serialized strings. The page cache is invoked whenever template output is due to occur, and saves pre-rendered HTML for immediate output.

I had a Zend project in which we had to use the Apache module mod_rewrite to “toggle” our secure connection depending on what pages the user landed on. The requirements were something like:

User visits any administration or account pages, and SSL is off, switch it on

User visits a page that is not an administration or account page, and SSL is on switch it off

As it was a Zend MVC project, we also had a rewrite rule that routed everything to /index.php in the document root.

This is Zend’s recommended .htaccess rule for routing:

1

2

3

4

5

6

RewriteEngineOn

RewriteCond%{REQUEST_FILENAME}-s[OR]

RewriteCond%{REQUEST_FILENAME}-l[OR]

RewriteCond%{REQUEST_FILENAME}-d

RewriteRule^.*$-[NC,L]

RewriteRule^.*$index.php[NC,L]

For the uninitiated, the block says: If the request is a valid file that exists, or it is a directory, don’t rewrite the URL, otherwise, rewrite the whole string to read “index.php.” The framework will generally just read the query string server variable and go from there.

So on to my additions for toggling SSL.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

#SSL Redirection

RewriteCond%{HTTPS}on

RewriteCond%{REQUEST_URI}!/(account|admin)[NC]

RewriteCond%{HTTP_HOST}^secure\.domain\.com$[NC]

RewriteRule^(.*)$http://domain.com/$1 [R,L]

RewriteCond%{HTTPS}off

RewriteCond%{REQUEST_URI}/(account|admin)[NC]

RewriteCond%{HTTP_HOST}^domain\.com$[NC]

RewriteRule^(.*)$https://secure.domain.com/$1 [R,L]

# Zend routing

RewriteCond%{REQUEST_FILENAME}-s[OR]

RewriteCond%{REQUEST_FILENAME}-l[OR]

RewriteCond%{REQUEST_FILENAME}-d

RewriteRule^.*$-[NC,L]

RewriteRule^.*$index.php[NC,L]

The above code checks the secure protocol, and then checks the requested path (in this case, /admin or /account). In finding that, it toggles the SSL accordingly.

Here’s the problem: because the two toggling rules only work if triggered as a redirect, the server’s request URL is rewritten twice, meaning that any “toggling” will result in a flat redirect to /index.php, breaking the application.

After hours of testing, rewriting, and Google-fu, I came up with this fix:

1

RewriteRule^.*$index.php[NC,L]

becomes:

1

RewriteRule^(.*)$index.php/$1[NC,L]

This means that the request is reattached to the end of the query all the time. This is hidden from the user (i.e. no ugly index.php/admin/login/ or what-have-you), and is successfully passed onto Zend to trigger the appropriate dispatcher. This works for any number of redirects.