Zend Framework and locales
Last night I spent a couple of hours with Zend Framework and especially Zend_Form. I discovered, and now also reported as ZF-6175, a bug in Zend_Validate_Float when using a locale with a decimal point other than “.”. There are unit tests but none that test Zend_Validate_Float under a different locale.
It is important to know that floats are actually locale aware in PHP. I’m not sure if that have always been the case. The below code will actually output 10,5 as Swedish use “,” as decimal point.
setlocale(LC_ALL, 'sv_SE.UTF-8'); echo 10.5;
The test in Zend_Validate_Float looked like
$locale = localeconv();
$valueFiltered = str_replace($locale['thousands_sep'], '', $valueString);
$valueFiltered = str_replace($locale['decimal_point'], '.', $valueFiltered);
if (strval(floatval($valueFiltered)) != $valueFiltered) {
$this->_error();
return false;
}
Under the Swedish locale mentioned above this will result in a comparison between two strings; “10,5″ and “10.5″.
I have proposed the following solution.
$locale = localeconv();
$valueFiltered = str_replace($locale['thousands_sep'], '', $valueString);
$valueFiltered = str_replace($locale['decimal_point'], '.', $valueFiltered);
list($num, $dec) = explode('.', $valueFiltered);
if (strval(intval($num)) != $num || strval(intval($dec)) != $dec) {
$this->_error();
return false;
}
But I just realized that it can be further simplified.
$locale = localeconv();
$valueFiltered = str_replace($locale['thousands_sep'], '', $valueString);
list($num, $dec) = explode($locale['decimal_point'], $valueFiltered);
if (strval(intval($num)) != $num || strval(intval($dec)) != $dec) {
$this->_error();
return false;
}
Ye olde English is dead
There are probably as many solutions to creating SEO friendly urls as there are actual implementations. After real work yesterday I started looking at the rather simple method based on the PHP built in strtr() we use. It’s very simple and apart from some uppercase, lowercase and utf8 juggling the (very shortened) basis is something like below.
$isochars = "\xFC\xFD\xFF"; $asciichars = "uyy"; $urlfriendly = strtr($actual_string, $isochars, $asciichars);
What struck me was that the character þ (FE in hex) was translated into y. As is correct if you look at how y, in different forms, was used as an abbreviation for the, that and so on in old English – or Anglo-Saxon. Often it is now written “Ye” as in the blog post title. (Yes – the “Y” in the title should be pronounced as “th“.
However, it is a bit odd as the Icelandic language still use the letter frequently. The sound value is more or less the equivalent of the English “th” in this or the.
The major value in SEO friendly urls is the readability. Shouldn’t it be more friendly and natural to translate þ into “th” in SEO friendly urls then?
Company, work and conferences
As mentioned earlier I moved with my family from Sweden to Spain for awhile. To complicate things further me and my girlfriend Malin created a new company called Dotvoid AB focusing on web sites and applications based on PHP. (So expect things to change around here in 2009 – though no timeplan or schedule exists). I have also quit working with debt collection software and is now working full time on Spanish consumer web sites for Grupo Inico.
Conferences? Apart from the usual PHP conferences that might or mightn’t (!?) be of interest there’s a score of other events focusing less on technology and more on softer issues. An hour ago I received an email from the Ning group Swedish Startups with lots of interesting conferences. I probably won’t be able to attend many of those. But Future of Web Apps in Dublin really caught my attention. A not too expensive one day event with lots of cool people and companies. Not to mention a good reason to visit the city I lived in almost eight years ago. (At the time I was working as a contractor on a then cool project.)
I have moved
I have been away from blogging awhile. Life has been really busy lately and I have sold my house and moved, with my family, to Fuengirola in Spain. Hopefully now that daily life is again back to normal I’ll blog a bit more. Maybe I’ll talk a bit more about daemons, asynchronous I/O and CodeIgniter as my current contract includes those topics.
Wishlist
As it is nearing Christmas I started thinking about things I would like to see in the PHP world. I don’t have time to write down a long wishlist but a few things would make me a happier person.
- Faster Eclipse/PDT/Zend IDE
- Builtin, reliable, refactoring support in PDT
- A good (good === simple and extensive) tutorial on using Zend_Test for testing applications built on Zend Framework – cause I’m starting to feel stupid here.
Apart from those three PHP specific wishes I also wish for all the usual stuff; a new mobile (I’ll buy one myself soon), more spare time with my family and friends (I’ll get that soon as well), world peace (tough one unfortunately), new laptop (my currrent – almost new – Dell sucks) and more.
I will get more free time soon. I’m selling the house in southern Sweden and moving with my family to southern Spain where I will work as a contractor for major Spanish consumer sites. Fun PHP work ahead!
First OpenCoffee in Karlskrona
Yesterday we had the first OpenCoffee in Karlskrona at the new place Bistro Java. The initiative came from Martin and Christian at Svensk Webbutveckling. Really nice guys even though they seem to prefer strongly typed languages over PHP. We had a good chat about both business and web development in general as well as technology and languages.
Unfortunately we three were the only ones showing up so the event will be repeated next thursday. If you are interested in business, technology, internet and web development – and are nearby – drop in!
Statistics
Last week we launched a new beta of our Swedish TV guide. It used to be based on Zend Framework 1.0 and has now been completely rewritten and upgraded to version 1.6.2. We didn’t seem to have any difficulties moving from 1.5 to 1.6 during development.
The framework is getting better and better even though I probably never will use things like the form builder functionality. One should never say never. But it seems backwards to me and I think it makes it more difficult to produce more advanced user friendly form based applications. Maybe I should force myself to use it a few times so that I can have a better opinion on it. Maybe…
Anyways, I’m more than happy with the first few days.
SOAP structures in PHP
Handling SOAP structures in PHP can sometimes be really annoying. If an interface is defined in the WSDL as returning an array I can’t be sure that I will get an array. If there is only one element in the array PHP tries to be clever and turn the wanted array into an object which, too me, isn’t really smart. I don’t know if this is a problem/limitation on the client side, server side or if it is just me doing something stupid in the wsdl.
As an example I have the below complex types, message and operation defined in the WSDL file. (The example is not complete of course.)
<complexType name="KeyValueData">
<sequence>
<element minOccurs="1" maxOccurs="1" name="id" type="string"/>
<element minOccurs="1" maxOccurs="1" name="name" type="string"/>
<element minOccurs="1" maxOccurs="1" name="data" type="string"/>
</sequence>
</complexType>
<complexType name="ArrayOfKeyValueData">
<sequence>
<element minOccurs="0" maxOccurs="unbounded"
name="keyval" type="tns:KeyValueData"/>
</sequence>
</complexType>
...
<message name="StatisticsListOutput">
<part name="data" element="tns:ArrayOfKeyValueData"/>
</message>
...
<operation name="getStatistics">
<input message="tns:StatisticsListInput"/>
<output message="tns:StatisticsListOutput"/>
</operation>
Sending this from the client is an absolute no brainer. It is a simple array containg associative arrays in every slot. When receiving this structure on the client side the original array (the member variable Map in the example) with one element turns into
Class Object
(
[Map] => stdClass Object
(
[item] => Array
(
[0] => stdClass Object
(
[key] => id
[value] => value
)
[1] => stdClass Object
(
[key] => name
[value] => value
)
where an array with multiple elements turn into
stdClass Object
(
[Map] => Array
(
[0] => stdClass Object
(
[item] => Array
(
[0] => stdClass Object
(
[key] => id
[value] => value
)
[1] => stdClass Object
(
[key] => name
[value] => value
)
This is annoying. Just imagine the situation when you have multiple arrays in arrays… Which actually does happen every once in a while when sending compounds of various elements declared as ComplexTypes in the WSDL.
Is it a feature, quirk or anti social behaviour? I don’t know. If there is another way I’d like to hear about it.
Calculating annuity in PHP
A collegue asked me about calculating annuity payments on loans. So I had a quick look around and found many people asking the same thing. The concept might be simple but it seems a lot of people stumble when it comes t othe algorithm.
Most of what I found was online calculators. The Swedish site rantekalkyl.se does exactly what I figured I wanted. (I even found an incorrect solution published in a thread at the Swedish phpsidan.nu.)
So I created a small class that calculates the monthly payment as well as the actual interest and amortization for every payment. Partly because I am sure others can be interested in the solution and partly because I’d like the code quality checked by as many as possible I publish it here. Feel free to suggest improvements and additions.
I know PHPUnit test case would be a nice addition but I didn’t have the time today.
<?php
/**
* @version 1.0
* @author Danne Lundqvist, http://www.dotvoid.com
*/
/**
* Class Financial_AnnuityLoan
*/
class Financial_AnnuityLoan {
/**
* Number of periods per year
* @var int
*/
private $aP;
/**
* Total number of periods
* @var int
*/
private $tP;
/**
* Yearly interest rate in decimal
* @var float
*/
private $rate;
/**
* Debt amount
* @var float
*/
private $amount;
/**
* Monthly payment
* @var float
*/
private $monthlyPayment;
/**
* Period specification
* @var array
*/
private $periodSpec;
/**
* Constructor for Annuity
*
* @param int $annualPeriods Number of periods per year
* @param int $totalPeriods Total number of periods
* @param float $interestRate Interest rate in decimal notation
* @param float $amount Total amount of debt
*/
public function __construct($annualPeriods, $totalPeriods, $interestRate, $amount) {
$this->aP = $annualPeriods;
$this->tP = $totalPeriods;
$this->rate = $interestRate;
$this->amount = $amount;
$this->monthlyPayment = null;
$this->periodSpecification = null;
}
/**
* Calculate monthly payment for annuity loan
*
* @return float
*/
public function monthlyPayment() {
if ($this->monthlyPayment != null) {
return $this->monthlyPayment;
}
$i = 1 / (1 + ($this->rate / $this->aP));
$this->monthlyPayment = ((1 - $i) * $this->amount) / ($i * (1 - pow($i, $this->tP)));
return $this->monthlyPayment;
}
/**
* Calculate actual debt, interest and amount to pay each period
*
* Calculates the actual interest, amortization, and remaining debt for each period.
* The method return an array with associative arrays, each with period, interest,
* payment and debt elements.
*
* @return array
*/
public function periodSpecification() {
if ($this->periodSpec != null) {
return $this->periodSpec;
}
$pmt = $this->monthlyPayment();
$periodrate = $this->rate / $this->aP;
$debt = $this->amount;
$val = array();
for ($i = 0; $i < $this->tP; $i++) {
$interest = $debt * $periodrate;
$payment = $pmt - $interest;
$debt -= $payment;
$val[] = array('period' => $i + 1,
'interest' => round($interest, 2),
'payment' => round($payment, 2),
'debt' => round($debt, 2));
}
$this->periodSpec = $val;
return $val;
}
}
Finally namespaces
There’s a lot of whining whining about the new namespace separator these days. Not only on blogs. At first I was a bit negative towards the choice but is more and more convinced it is a good one.
First of all, few of the people complaining seem to have read the RFC documents explaining in detail the pros and cons of different choices. So here goes, read carefully before deciding.
To be honest. If some of the other suggestions in the RFC “Namespace separators” above would have won I think a lot more people would have had better reasons to rant. The backspace “\” is probably the most readable choice and thus less prone to typos which is a Good ThingTM.
Most of the criticism seem to stem from the problems you could get from having namespaces in strings and that backslash is used for escaping. I am a unix based developer but I guess that to developers using windows this is a no brainer. They’re already used to have a backslash in another context. If you then have a look at the way many projects, including for example Zend Framework, organize their classes and what should be namespaces into directories it makes sense to a lot of people.
So it’s not all bad. I’m looking forward to not having to instantiate insanely named classes like
$upload = new Zend_File_Transfer_Adapter_Http();

