Changes since 0.4:
- [NEW] support for HEAD requests [#12 state:resolved]
- [FIXED] internal routes are at the begining of the lib so can’t be bypassed [#13 state:resolved]
- [FIXED] internal CSS we’re renderred with a layout if defined [#14 state:solved]
- [FIXED] bug in file_is_text
- [CHANGED] removes mime_content_type compatibility function and add file_mime_content_type() [#15 state:resolved]
- [NEW] Adding an $exit optional parameter to the stop_and_exit() function
- [FIXED] Fixing flash bug while redirect_to [#16 state:resolved]
- [FIXED] Fixing redirect_to bug with multiple parameters [#17 state:resolved]
- [FIXED] Fixing bug setting an error_layout [#18 state:resolved]
- [FIXED] buggy url_for()
- [NEW] url rewriting support by explictly setting option(‘base_uri’)
See http://github.com/sofadesign/limonade/blob/master/CHANGES for all changes.
Working on the new Limonade 0.4 branch, it’s also time to read and read again current code, and checking code design consistency.
Something i didn’t notice before suddenly appears: options are managed with the singular function option but params are retrieved with the plural option params… very confusing…
I probably had in mind those two naming ways:
- using plural, like accessing a member of an array
- using singular, like an action method or like saying “get/set option”
I’ll try in this post to explain each feature in order to find the right naming. As me, you’ll probably be surprised how such a small question raises new problematics and reveals hidden design defects.
About function naming
Every code project has its conventions. Habits also depends on the language. But there are common rules that you can find most of the time.
In Limonade, i choosed to be as close as possible to the PHP native API conventions:
- lowercase
- underscored names
- prefixed by module name (but i’ve not prefixed all my functions with
limonade_… too verbosed…)
I’m trying to keep functions names short and simple but always meaningful. For simplicty and compacity, some function are in the same time a getter and a setter: so i don’t need to, and i can’t, use a get_ or set_ prefix. But remember those functions are still verbs.
Options features
Many features are covered in this single option() function
- getting all options (no argument provided)
- getting an option (one argument provided)
- setting an option (two arguments provided)
I should have wrote option with three function instead of one:
get_all_options()
get_option($name)
set_option($name, $value)
This all-in-one getter/setter function is very convenient but it’s also the source of our problem.
I’m not sure that getting all options is useful: perhaps for internal use ? There’s no need of it for now, so i should remove it in the next release (never implement unnecessary features…).
So, we only use it for getting and setting an option: prefering a singular naming is probably the most common and logical solution.
Params features
Actually, params() does 4 things:
- getting all params (no argument provided)
- getting a param (by providing a argument)
- setting a param (by providing a $name argument and a $value argument, or n arguments…)
- resetting params (with a null argument)
Getting a param is the main use. Maybe getting all can be useful too. But setting and resetting should really be reserved for an internal use. Params should be read-only: they are passed by current uri, so they can’t be changed.
Maybe you might want to filter a param in the before function, like in Wikir
function before()
{
if($page_name = params('page'))
{
params('page', rawurldecode($page_name));
}
}
In this case, if params() has no writing feature anymore, we need to use a global variable or better, creating our own filter function and calling it when needed
function my_filtered_params()
{
$params = params();
if(array_key_exists('page', $params)) $params['page'] = rawurldecode($page_name);
return $params;
}
And about the reset feature, there is no reason to use it unless for internal use: this is a good example to show that using public API in a private context makes it more complicated that it needs to be.
So we only need to get all params or one. 95% of the time, we’ll call a unique param: so it will be singular
And next… refactoring
Now I really need to refactor those functions. I will also apply the same process to all functions of the limonade public API to improve it.
I read recently this great article by Yehuda Katz. Heaven if we can’t compare with such a huge task (Rails 3.0 refactoring), i note 4 refactoring good practices:
- Having a test suite for each part that will be refactored
- Don’t add any new features during a refactoring cycle
- Make changes step by step, by logical groups and make tests after each change
- Separate public api from internal functions / don’t use public api functions for internal use.
So Limonade will need a good refactoring phase: not for 0.4 branch because it adds new features, maybe in the 0.5 branch after completing unit testing.
(Author: Fabrice Luraine - second reading/corrections: Mathias Standaert)
Good news for those who asked me more examples: i wrote a page on the website to link to some.
For now, you’ll find Wikir, the text file-based wiki we produce during the 2 days workshop with Mathias. It well describes how to write your routes and your controllers functions in a RESTful way.
I’ll add it some comments this week and Mathias will publish a french tutorial for newbies.
Andrey Pankov published yesterday a good DB based example application. It’s a kind of book cataloger based on PDO, with great functions to handle data objects. It just needs sanitization and a validation process to cover real needs. I suggest to use the PHP native filter functions, they can do that in a very clean way
And if you haven’t check it before, iSearch, from Imre Mehesz, is a good start if you want to make iPhone like webapps with Limonade an iUI.
That’s all for now but thursday will be the Workshop Day #3. We will prepare a blog example that will be the start for a typical “first app” tutorial like we can find for most populars frameworks.
Until that, let me know if you have other examples, in order to add them to the page.
I hope the list of examples will become longer in the next weeks ;-)
I planned to publish everything from our last 2 limonade workshops this week… but days are really too short.
So you can still have a look to the sources of the wiki example (aka Wikir).
Next week i’ll try to:
- add comments (so that code could be read like a tutorial)
- make a brief README (in english, there is still one in french)
- publish an online demo, with a daily reset of wiki pages
_______
_oo88888888888oo_
_o8888888888888888888o_
,d88888888888888888888888b.
d888888888888888888888888888L
d88888888888888888888888888888b
d8888888888888888888888888888888b
_ _ _
| | (_)_ __ ___ _ _ __ _ __| |___
| |__| | ' \/ _ \ ' \/ _` / _` / -_)
|____|_|_|_|_\___/_||_\__,_\__,_\___|
888888888888888888888888888888888
`8888888888888888888888888888888'
Y888888888888888888888888888P
Y8888888888888888888888888P
`Y8888888888888888888P'
`"P8888888888888P"'
`'`"""""'''
This tumblog will be the place for all that things about Limonade PHP micro-framework:
- News
- Tips
- Faqs
- Tutorials
- Examples
- …
If you want to contribute, don’t hesitate to contact me ;-)