A little late sorry, but ZF 1.5.1's package is now ready.
A propos
- something to tell me ? feel free to drop a mail
- Profile LinkedIn
Monday 31 March 2008, 17:08
By Geoffrey - Coding - Permalink
A little late sorry, but ZF 1.5.1's package is now ready.
Thursday 27 March 2008, 23:04
By Geoffrey - Coding - Permalink
A small bit of ruby to get a constant from an URL:
require 'uri'
def url_to_constant(url)
return URI.parse(url).host.gsub(/^www\./, '').capitalize.gsub(/[^a-z][a-z]/i) { |m| m.gsub(/[^a-z]/, '').upcase }.constantize
end
Nothing exceptionnal here, just a pretext to post something.
Saturday 22 March 2008, 18:19
By Geoffrey - Coding - Permalink
The long awaited 1.5 version of the Zend Framework has landed for some days already, and here comes its pear package. Please note the api version changed to 1.5 in this package.
Monday 10 March 2008, 21:48
By Geoffrey - Coding - Permalink
Après de longs mois d'attente, le related by tags nouveau arrive enfin ! Au menu des réjouissances, une interface de configuration, ainsi qu'un widget font leur apparition. Vous disposez donc désormais de deux manières d'afficher les billets liés, directement en modifiant le template comme avant:
{{tpl:include src="_related_by_tags.html"}}
ou tout simplement en activant le widget correspondant, que vous pouvez configurer comme vous l'entendez. Bien sur, ce widget ne s'affichera que lors de la visualisation d'un billet.
Au chapitre des fonctionnalités / bugfix manquant(e)s, on notera le bug lié à l'utilisation de postgresql, ainsi que la traduction française, qui sera pour plus tard.
Encore une fois, n'hésitez pas à poster tous vos commentaires ici même.
Wednesday 27 February 2008, 11:17
By Geoffrey - Coding - Permalink
The package for the last 1.0.x release, 1.0.4, is now available on the phpmafia pear channel. Please report any issue in the comment of this post. The Zend_Locale's xml bug should now be fixed (they are now considered as php and thus put at the right place, which is not the best way to fix the bug I guess but at least it should work for now).
Sunday 2 December 2007, 16:41
By Geoffrey - Coding - Permalink
I used to use this yaml_to_ar lib from christophe to load categories tree into my database, using acts_as_tree in the model that was perfect. Arrived the time when I felt the need to use acts_as_nested_set instead, for which I had to fill the lft and rgt columns. So I just rewrote the yaml_to_ar piece of code (put this in lib/yaml_to_ar.rb):
require 'yaml'
class YAML_to_AR
def initialize(file, model)
@data = File.open(file) { |yf| YAML::load( yf ) }
@model = model
end
def process(data = @data, parent = nil)
if data.is_a? Array
data.each do |val|
process(val, parent)
end
elsif data.is_a? Hash
data.each do |key,val|
parent = @model.create(:title => key)
process(val, parent)
end
elsif data.is_a? String
parent.add_child(@model.create(:title => data))
end
end
end
This should handle both acts_as_tree and acts_as_nested. To ease things a bit further, I also wrote a rake task (to drop in lib/tasks/db_load_categories.rake for example):
namespace :db do
desc "Loads categories defaults data"
task :load_categories => :environment do
require 'lib/yaml_to_ar'
Category.delete_all
categories = YAML_to_AR.new('db/categories.yml', Category)
categories.process
end
end
Now I just rake db:load_categories, and voila !
Wednesday 28 November 2007, 13:00
By Geoffrey - Coding - Permalink
It's a simple plugin (2 lines of code beside class and modules declarations) which allows routes created via the map.resources mechanism to be customized. Say you have the following map:
map.resources :members
It will generate routes like:
/members /members/:id /members/new
No say you want to i18n your app, in french for example, what do you do ? You just can't out of the box. This is where my plugin enters into action, just add a :route_name parameter to the map.resources call and you're set:
map.resources :members, :route_name => 'utilisateurs'
will generate routes like:
/utilisateurs /utilisateurs/:id /utilisateurs/new
It shall also work for nested resources, although I did not test that.
The code is actually pretty simple:
module ActionController
module Resources
class Resource
def path
route_name = @options.include?(:route_name) ? @options[:route_name] : @plural
@path ||= "#{path_prefix}/#{route_name}"
end
end
end
end
To install just use script/plugin:
script/plugin install http://tools.assembla.com/svn/riskle/rails/plugins/named_resources
or to install as an svn:external resource:
script/plugin install -x http://tools.assembla.com/svn/riskle/rails/plugins/named_resources
Wednesday 21 November 2007, 12:03
By Geoffrey - Coding - Permalink
For some reason, $HTTP_RAW_POST_DATA does not seem to be set inside an action controller. You'll have to use the php://input stream wrapper to access raw http post data:
$raw_post_data = file_get_contents('php://input');Monday 5 November 2007, 14:37
By Geoffrey - Coding - Permalink
Today I ran into an issue while extending Zend_Controller_Router_Route. I wanted to add a little path pre/post processing in the match() and assemble() methods, so I just extended the Route class to add my tiny bits of code into the methods. Except it did not work at all. After a few debuging, it turned out that the Router uses Zend_Controller_Router_Route::getInstance() to retrieve a route object, which uses a new self(); statement to instantiate the route object. Problem is that self always refers to the current class definition we're in, if the method is called from a child class, without being overloaded, self will refer to the wrong class.
Example:
class Foo {
public static function getInstance() {
return new self;
}
}
class Bar extends Foo {}
var_dump(Bar::getClass());
echoes something like:
object(Foo)#1 (0) {
}
Which is fscking wrong IMHO. A quick workaround is to overload the getInstance method, which is what I call pretty annoying as it does not follow the DRY principle.
Monday 22 October 2007, 13:39
By Geoffrey - Coding - Permalink
Having started a few applications using the Zend Framework, I came out with a few practices that I tend to use over and over. In this post I'll quickly expose some of them and explain why I do things the way I do them. As you'll notice, most of them are already widely known and used over the ZF developer's community. Please remember that these practices are just what I do, and come with no garanty at all to be best practices.
Thursday 4 October 2007, 20:50
By Geoffrey - Coding - Permalink
update: nouvelle version disponible
Allez hop, j'ai codouillé rapidement aujourd'hui un plugin dotclear 2 pour afficher une liste des billets ayant le ou les mêmes tags que le billet en cours de lecture par l'internaute. Il est téléchargeable dès maintenant sous forme d'archive tar gzipée ou directement de package dotclear. Pour l'utiliser, rien de plus simple, il suffit d'ajouter le tag suivant dans votre template, à l'endroit où vous souhaitez afficher la liste des billets:
{{tpl:include src="_related_by_tags.html"}}
Et voilà c'est tout :-)
Bon par contre, il faut faire gaffe a comment on tag ses billets (genre pour celui là j'ai preferré ne pas le taguer php histoire d'avoir des résultats plus pertinents).
ps: si quelqu'un connait un moyen d'éviter d'avoir a rajouter un bout de code au template je suis preneur (mais j'ai la flemme de chercher là tout de suite).
Monday 1 October 2007, 17:40
By Geoffrey - Coding - Permalink
Today I ran into an issue that I already ran into a few weeks ago when I did not have time to dig up, but today I had this time (this plus it's a really annoying issue as you'll see). The main symptom is that PDO does not throws exceptions when you'd expect it to. It's very annoying. The reason, in my case, seems to be that I am querying an old mysql (3.23.x in my case but any 4.x will do according to this bug report). I was not able to find any info from google, so I'm posting this here so that people know :-)
Monday 1 October 2007, 12:44
By Geoffrey - Coding - Permalink
For those caring, I just posted some quick documentation for the pagination component at my assembla space. More docs will follow (including extensive phpdoc docblocks I hope).
Sunday 30 September 2007, 16:21
By Geoffrey - Coding - Permalink
A PEAR package for the 1.0.2 version of the Zend Framework is now available from the PEAR PHPMafia channel. As usual, to install just issue the following:
pear channel-discover pear.phpmafia.net
pear install phpmafia/ZendSunday 30 September 2007, 01:28
By Geoffrey - Coding - Permalink
I just released on riskle's assembla space a new version of my pagination component for the Zend Framework which you can download right now:
This release fixes a nasty bug in Riskle_Db_Table::fetchCols which prevented from retrieving the right count of cols involved in the query.
The table component has also been slightly rewritten following Erik's suggestion to move the parent mapping into _fetch. The parent mapping itself has been improved to allow "multi level" table joining. This will be best explained with an example:
Say you have three table, Foo, Bar and Quux, and you would like to execute the following query:
SELECT * FROM Foo JOIN Bar ON Foo.bar_id = Bar.id JOIN Quux ON Bar.quux_id = Quux.id
This is now possible with the following mapping (in Foo's class of course):
array(
'Bar' => array('local' => 'bar_id', 'remote' => 'id'),
'Quux' => array('local' => 'quux_id', 'remote' => 'Quux.id'),
);
Easy heh ?
As usual, any comments are appreciated, and please note that this code is released under the same license as the ZF itself, the new-bsd license.
Sunday 23 September 2007, 00:55
By Geoffrey - Coding - Permalink
When anyone on #zftalk ask about where controller plugins should be kept, we usually responds something like have your own library namesapce alongside Zend/ and put it in it like YourNamespace/Controller/Plugin/YourPlugin.php. But what about application specific controllers ? There's a time where you have to write a plugin that relies on the application at such a level that using it elsewhere would make no sense. In that case, where can we store this plugin ? The question arised this morning, and we ended up to the fact that having a controller-level plugin directory would not hurt, after all. So one could have the following directory layout (simplified on purpose):
/application/modules/default
/controllers
/library/Plugin
MyPlugin.php
The drawback is that in order to use autoload you would have to have each modules Plugin dir in the include path, which is a bit of a hassle. Instead, we could have the much more simple folloing layout:
/application
library/Controller/Plugin
MyPlugin.php
Which is simpler but does not allow for modules specific plugins. Anyway, the former layout would require a bit more logic in the bootstrap in order to extract every modules path as plugins are registered pre-dispatch.
Hope it helps with directory layout organization :-)
UPDATE
What I've finally decided to do is the following:
/application
library/App/Controller/Plugin
MyPlugin.php
So that application specific code gets prefixed with the App_ namespace.
Sunday 23 September 2007, 00:07
By Geoffrey - Coding - Permalink
UPDATE: new version (r105) available.
The component was given a little rewrite as expected, but maybe a little bit later than I would have wanted to :-) So it now has its own Rowclass proxy from which you can pull various infos such as current page, page range, next page, etc all exposed as getter methods (that is, getCurrentPage, getPageRange, getNextPage, etc), which you won't really have to worry about since the brand new view helper will take care of that for you. Usage has changed a little, bit, so let's first have a look at what's happening from the controller point of view:
$table = new Riskle_Db_Table_Paginate(new Table, $this->_getParam('page'));
$this->view->rowset = $table->fetchAll();
Not much changed here, except we don't need anymore to call getPaginationInfos(). Nice ! Now the big part, the view:
$this->paginate($this->rowset);
echo $this->paginate()->previous();
echo $this->paginate()->navigation();
echo $this->paginate()->next();
The view helper uses the neat composite helper trick from naneau - which is a really cool trick, great job naneau my fellow no-more-a-bunny. The first call inits the helper, feeding him the necessary rowset to work on, then you just have to call the methods you need to draw the navigation links. As you may expect, previous and next method will return nothing if no page is available (actually, they return their second argument, which defaults to an empty string).
Also, it's worth noting that the bundled Riskle_Db_Table features the patch from Erik, as well as a totally rewritten fetchCols method (now uses a straight Zend_Db_Select object instead of the ugly trick it used to use).
My code is no longer available on subversion, I moved the project to assembla. Instead ou can download this component from the riskle space's files board (direct download), the file contains all classes needed for the component to work, just unzip it in your include_path and you're set.
As usual, any comments are more than welcome.
Wednesday 19 September 2007, 16:12
By Geoffrey - Coding - Permalink
So well, I've been busy these days working on my own implementation of a form component in the ZF spirit. This post is to help me see where I'm at with this component, as well as planning future evolution. I'll try my best to describe what it does and does not, and what it could do in the future.
Of course, while this is more of a personnal pense-bete than anything else, any comments are welcome.
Tuesday 14 August 2007, 14:01
By Geoffrey - Coding - Permalink
A quick post to show how one can easily implement a findByField wrapper in Zend_Db_Table:
/**
* Implements a simple findByField wrapper
*/
public function __call($method, $args) {
if (preg_match('/^findBy([a-zA-Z0-9]+)$/', $method, $parts)) {
$field = strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $parts[1]));
if (!in_array($field, $this->_cols)) {
throw new Zend_Db_Table_Exception(sprintf('\'%s\' field not in row', $field));
} else {
$db = $this->getAdapter();
$where = $db->quoteInto($db->quoteIdentifier($field).' = ?', $args[0]);
return $this->fetchAll($where);
}
}
}
What it does is basically trapping any non-existant method call and check if the corresponding field exists, after converting CamelCasing to underscore_notation (eg: FooBar becomes foo_bar).
Monday 13 August 2007, 15:39
By Geoffrey - Coding - Permalink
When developping a database tied application, you eventually come to a point where you get (at least) two tables with a parent/child relationship, such as for example a User table referenced by, say, a Post table (each post belonging to a specific user). That's basically the point where you need Zend_Db_Table relationships mechanism. the drawback of this mechanism is that, as far as I know, it does not produce joined queries to retrieve the parent data, but fires a query for each parent row. Thus instead of just using Zend_Db Relationships, I developped a simple yet effective auto-join mechanism that I called, in great simplicity, parent mapping. It supports multiple joins from multiple tables, remote fields specification and prefixing.
It is included in my db table class and you can see the interesting part of the code below for your convenience (Ignore the 3 first lines of the function as it is used for something else in my version of the framework).
« previous entries - page 1 of 8