PHP
Setting up Zend Framework from PEAR
0Alright, so I’ve just changed my VPS provider because 1&1 are shit and my buddy Andy runs a good hosting gig http://www.theserve.com/. We’re running our stuff one one of his VPS’s until September and will more than likely move to a dedicated server once we move office. Any way!
One of the teething issues I have with Zend Framework is that with every ZF project I put up on the server I’ve had to include a distro of ZF in the library folder, or constantly keep a centralised version up to date by downloading and overwriting… Until now… There’s an unofficial pear channel that will let you install and update ZF with 1 command… Here’s what you need to type in terminal…
pear channel-discover zend.googlecode.com/svn pear install zend/zend
That’s it, the Zend Framework will be installed and accessible from every website, as with PHP, make sure you only update to the latest version if you’re 100% sure that all of your web applications will work.
There has to be an easier way :(
0So I’m working on a project, and I want to find all of the rows that don’t have a row in it’s related table using Zend_Db_Table_Select… Simple right? Not really
. In theory this would be the query that I would write…
SELECT author.id FROM author LEFT JOIN project ON project.author_id = author.id WHERE project.author_id IS NULL ORDER BY RAND() LIMIT 1
After toying with Zend_Table for a while I’ve managed to figure out how to do it…
/**
* Fetches a random author who has not had a project assigned to them
* @return Ambigous <Zend_Db_Table_Row_Abstract, NULL>
*/
public function findRandomNull(){
$authorModel = $this->getDbTable();
$select = $authorModel->select()
->setIntegrityCheck(false)
->from('author')
->joinLeft('project', 'project.author_id = author.id', array())
->where('project.author_id IS NULL')
->order('RAND()');
return $authorModel->fetchRow($select);
}
Which will produce the following SQL
SELECT `author`.* FROM `author` LEFT JOIN `project` ON project.author_id = author.id WHERE (project.author_id IS NULL) ORDER BY RAND() ASC
ZEND FRAMEWORK 1.10 IS OUT!
0Zend Framework 1.10 is out, and with it a bunch of new features, and for once… the documentation is VERY helpful! For those having problems getting their head around Zend_Acl check out this tutorial… http://framework.zend.com/manual/en/learning.multiuser.authorization.html
Zend_Acl + Zend_Auth + Zend_Controller_Plugin = HAPPY!
15Ok, so after playing around with Zend_Acl for what seems like forever I’ve finally cracked what feels like the perfect marriage between Zend_Acl, Zend_Auth and an application.
You may ask yourself, why the fuck is it so hard? The simple answer is this…
Zend_Aclwas designed in such a way that it does not require any particular backend technology such as a database or cache server for storage of the ACL data. Its complete PHP implementation enables customized administration tools to be built uponZend_Aclwith relative ease and flexibility.
Ease and flexibility my arse! This is the reason quite a few Zend Developers are just pulling their hair out day in day out. The documentation at zendframework.com by far is the most confusing I’ve ever seen and quite a bit of it is outdated. It’s actually easier reading through the API documentation and trolling through the code than it is reading this stuff. I truelly feel sorry for people using ZF in anything less than ZendStudio or an IDE without the code completion. Authentication and Authorisation are pretty key aspect of any application, if they made it simple for people to set up they wouldn’t need a 2 paragraph section saying how to store the data by serializing it. Any way, rant over!
The Solution
There are many ways to store the ACL data for persistence, but I think that’s the problem. As soon as you hear the words store and persistance the bells and whistles in your head are screaming at you telling you to store it in a database just like in CakePHP. For months I’d been trying to work out a way to do this until last night.
Why not put this in the application configuration (application.ini)? This is application configuration after all! What’s the point in taking a hit on your database every time you want to check authorisation and then having to write caching code to counteract that? It’s counterproductive and not cost effective (thanks Kennedy stole your phrase).
We can then read the configuration from ini file which contains all of our Resources and Roles.
To begin I set my self some conditions:
- Whatever the solution is, it has to be decoupled from the rest of the application apart from the models used for the user obviously.
- It has to be piss easy to implement
- It has to be so easy to implement my mum could do it!
PHP Variable Variables
0Whilst I don’t advocate assigning variable variables, there are times when you need to create variables in PHP dynamically.
What is a Variable Variable?
A variable variable is a variable that can be set dynamically. For instance the normal way to create a variable in PHP would be:
$foo = 'bar';
But what happens when you’re setting a variable dynamically, i.e. it doesn’t exist already and it’s dependant on user input or an unpredictable event? The solution… a Variable Variable
$foo = 'bar'; $$foo = 'hello'; echo $bar; // this will output 'hello'
This may seem useless to you but after just over 5 years of programming I’d finally found a sane some what safe use for it. I had an object that has a property that contained an array of data, I wanted to be able to access that data from within an included file in my function. To do this I had to assign a load of variables that were dynamically set within the object… you know what, let me just show you!
class Template {
protected $variables = array();
public function set($key, $value){
if($key === 'this'){
throw new Exception('Key cannot be set to "this"');
}
$this->variables[$key] = $value;
}
/**
* Outputs the fully rendered view
*
* @param bool $output
*/
public function output($output = true){
$this->_loadTemplate();
$this->output = ob_get_clean();
if($output === true){
echo $this->output;
}
}
private function _loadTemplate(){
foreach($this->variables as $key => $value){
$$key = $value;
}
require_once 'layout/' . $this->layout . '.phtml';
}
}
So now in my layout, instead of having to do this to get my template variables..
<?php echo $this->variables['foo'] ?>
I can use this
<?php echo $foo; ?>
All done, also as a side note, people who use
<?=$fool; ?>
to output content, stop it! You’re shooting your self in the foot, when you migrate to a server that doesn’t support short tags and you can’t change it, you’ll be fucked and annoyed!
Use
<?php echo $foo; ?>
Instead, the extra key strokes saves the weeks of headache!
Eclipse Shortcuts
0Right clicking to create new table classes in Zend Studio for Eclipse can get very annoying. The best solution is to create shortcut for it. To do this:
- open up preferences (cmd + , if you’re on a mac).
- type in “keys” without the quotation marks.
- to the right enter “Zend Table” into the “type filter text” field.
- You’ll see the “New (New Wizard: Zend Table)” command.
- Click on it
- Click on the binding text box and press your command keys.
Hope that speeds things up a little!
Non-existant fields Zend_Db_Table_Abstract
0I’d run into a problem in the Zend Table where when inserting data from a form, if a field didn’t exist in the database ZF would crap out with an exception. Having to unset posted variables I didn’t need, meant more typing, more typing meant more unnecessary code.
I found the easiest way to get around this is by overriding the insert method in my extended App_Db_Table_Abstract class. Here’s what my new insert method looks like.
public function insert($data, $skip = true){
if($skip === true){
$oldData = $data;
$data = array();
foreach($this->info('metadata') as $key => $value){
if(isset($oldData[$key])){
$data[$key] = $oldData[$key];
}
}
}
parent::insert($data);
}
The method takes two parameters, the data ($data) and a Boolean value ($skip). Skip defaults to true, so I don’t need to add this parameter to every call to insert, it’s also there in case I don’t want to skip my data.
It then iterates through the table meta data, which contains the field names for the table, checks to see if the key exists in the data from the form. If the field exists in the array then it’s added to the new data array.
Finally the parent insert method is called, bobs your uncle.
In case you’re wondering, I’ve subclassed some of the Zend classes, this allows me to override methods to my liking.
Agile Development
6Working at Channel 4 I’ve been introduced to Agile Development, to sum it up in one sentence…
“It’s a way of working in a development team, where the specification for a project is constantly changing and the waterfall approach (you get a spec, build to it over a long period of time, get feedback and make amends) just doesn’t cut it.”
It’s a completelty different way of working, and it’s full of terms which I would say were thought up by some drunk developer, introducing words such as “brown bag”.
(more…)
Zend_Acl Db Storage
1I’ve spent the last few hours trying to extend Zend_Acl_Role_Registry and Zend_Acl to support Db storage, when it just hit me what I’m actually trying to do, and a much easier way to do it!
(more…)
