Wouldn’t you agree that using exactly the same markup in 15 views is a little bit redundant? Now imagine doing that 10 times in your application (that’s 15*10-15 which equals to 135 reduntant repetitions of the same piece of XHTML). Well, that’s the easier part. Now imagine you need to make few changes in the markup after few days. Guess what – you are going to do those worthless 135 repetitions again. And surely you might need more changes in the markup two weeks later… I could go on. There’s nothing easier than avoiding this problem in Zend Framework.
The solution is to use partial view helper which allows you to put the repetitive XHTML into a single file. For example, this could be your partial:
-
<?php // saved in views/scripts/index/partials/partial.phtml ?>
-
<h3><?php echo $this->escape($this->heading); ?></h3>
-
<p>
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
-
Mauris porta, sapien at accumsan venenatis, neque velit
-
sodales augue, sit amet posuere odio enim quis risus.
-
Aliquam semper, ipsum porttitor ultricies bibendum, sem
-
sapien tincidunt purus, eget sollicitudin felis eros
-
fermentum felis. Praesent vehicula varius est at semper.
-
Nam nulla augue, fermentum in varius vel, tincidunt non
-
nibh. In vitae neque vitae metus dignissim hendrerit.
-
Nulla eget massa nec sapien tempor ultricies a et tellus.
-
Sed imperdiet, risus quis vehicula ornare, justo lorem
-
iaculis sapien, id semper massa nisi eu purus.
-
Suspendisse sed urna eu risus rhoncus bibendum. Cras
-
feugiat consectetur nisi id dictum. Pellentesque quis
-
mauris a risus dapibus dictum nec sed nisl.
-
</p>
-
<ul>
-
<li>List Item 1: <?php echo $this->escape($this->li1); ?></li>
-
<li>List Item 2: <?php echo $this->escape($this->li2); ?></li>
-
<li>List Item 3: <?php echo $this->escape($this->li3); ?></li>
-
</ul>
And this is how you would include it in all views where the same piece of markup occurs:
-
<?php echo $this->partial('index/partials/partial.phtml', array(
-
'heading' => 'Lorem Ipsum',
-
'li1' => 'Hello',
-
'li2' => 'World',
-
'li3' => '!!!')); ?>
It’s really easy and it saves a huge amount of time both to you and to a developer that might work on your application in the future so please, all of you Zend Framework developers, use partial helpers wherever there is a repetitive XHTML markup in your application.
Sometimes people will complain that the captcha is too difficult to read and they have to reload the page in order to be able to pass the captcha test. If you are not willing to say goodbye to the very flexible Zend_Captcha_Image there are only two ways how to make it easier to read:
- Use different font (I have found that Arial is sometimes hard to read, a good replacement seems to be LBRITED.TTF).
- Set lower dot and line noise level.
You can use “dotNoiseLevel” and “lineNoiseLevel” to tune down the captcha noise (and surpisingly this is not mentioned in the Zend Framework documentation):
-
$captcha = new Zend_Form_Element_Captcha('captcha', array(
-
'label' => 'Captcha',
-
'helper' => null,
-
'captcha' => array(
-
'captcha' => 'Image',
-
'wordLen' => 5,
-
'timeout' => 300, // 5 minutes timeout
-
'font' => 'fonts/LBRITED.TTF',
-
'fontSize' => 20,
-
'width' => 100,
-
'height' => 60,
-
'imgDir' => 'images/captcha/',
-
'imgUrl' => '/images/captcha/',
-
'dotNoiseLevel' => 15,
-
'lineNoiseLevel' => 1
-
)
-
));
Above I went over the top perhaps. Nevertheless, you must be able to find a compromise so that the users will be happy and the security side of your website won’t suffer too much.
Caching with PHP is the best way to speed up your application and it’s quite easy thanks to native PHP modules such as APC or output buffering control. It’s even much much easier when you are using the Zend Framework as it contains a native class just for caching – Zend_Cache. To use the Zend_Cache you must first initialize it in the bootstrap and add it to the registry so you can access it easily in controllers, I do it like this:
-
protected function _initCache()
-
{
-
$frontend = array('lifetime' => 7200,
-
'automatic_seralization' => true);
-
// where are we going to stored the cached files?
-
$backend = array('cache_dir' => 'cache');
-
$this->cache = Zend_Cache::factory('core',
-
'File',
-
$frontend,
-
$backend);
-
}
-
-
protected function _initRegistry()
-
{
-
$this->registry = Zend_Registry::getInstance();
-
$this->registry->cache = $this->cache;
-
// I store much more in the registry, of course
-
// for instance, configuration and db adapter
-
}
The frontend and the backend adapters can take much more arguments, read the documentation to learn all possible options. I initialized the Zend_Cache object with the factory method. First argument means that we want to use the Zend_Cache_Core frontend which is the core of the Zend_Cache module. The second argument is the backend we want to use the Zend_Cache_Backend_File backend or that we want to store cached data as files in a specific directory. The other two parameters are frontend and backend options.
Now we can easily access the cache object in controllers or models:
-
$cache = Zend_Registry::get('cache');
-
// does the cache contain data we are looking for?
-
if (!$result = $cache->load('myUniqueId')) {
-
// if not let's cache the data
-
// here I use only a random array but in a real application
-
// you would probably cache some database entries
-
$data = array('John Doe', 'Jane Doe', 'Baby Doe');
-
// besides unique cache id you can use tags to categorize data
-
$cache->save($data, 'myUniqueId', array('tag1', 'tag2'));
-
} else {
-
// dump the cached data
-
var_dump($result);
-
}
That was easy, wasn’t it?
Cleaning the cache
You will surely also want to remove cached files at some point in your application:
-
// clean all cached files
-
$cache->clean(Zend_Cache:: CLEANING_MODE_ALL);
-
// clean only outdated cached files
-
$cache->clean(Zend_Cache::CLEANING_MODE_OLD);
-
// remove a particular cache id
-
$cache->remove('myUniqueId');
-
// remove records tagged as "tag1" AND "tag2"
-
$cache->clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG,
-
array('tag1', 'tag2'));
-
// remove records tagged as "tag1" OR :tag2"
-
$cache->clean(Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG,
-
array('tag1', 'tag2'));
-
// remove records NOT tagged as "tag1" or "tag2"
-
$cache->clean(Zend_Cache::CLEANING_MODE_NOT_MATCHING_ANY_TAG,
-
array('tag1', 'tag2'));
That’s it for today and, by the way, Merry Christmas
I have recently switched web hosting provider and had to move my personal website and blog over to the new one. I have encountered a simple problem when trying to get my personal website to work (it’s a Zend Framework application). I got the 500 Internal Server Error:

The problem lied in this .htaccess rule:
php_flag magic_quotes_gpc off
So I just commented the line and the error went away.
The line’s purpose was to make sure magic quotes are turned off in PHP. You can use it if your web host supports it, if not just add this to your bootstrap file:
-
protected function _initGetRidOfMagicQuotes()
-
{
-
if (get_magic_quotes_gpc()) {
-
function stripslashes_deep($value) {
-
$value = is_array($value) ?
-
array_map('stripslashes_deep', $value) :
-
stripslashes($value);
-
return $value;
-
}
-
-
$_POST = array_map('stripslashes_deep', $_POST);
-
$_GET = array_map('stripslashes_deep', $_GET);
-
$_COOKIE = array_map('stripslashes_deep', $_COOKIE);
-
$_REQUEST = array_map('stripslashes_deep', $_REQUEST);
-
}
-
}
One of my school assignments was to write a simple ANSI C Perceptron algorithm that would be able to separate points on a two dimensional plane into two sets (-1 and 1). Fortunately, while reading a Wikipedia article about Perceptron, I have found a great external link at the bottom of it: C# implementation of a Perceptron. This helped me a lot to understand how the Perceptron works and how to implement it programatically.
What I have done is rewrite the code snippet from John Wakefield in the C language. Instead of data type double I used two integer arrays (one denotes x and the other one y coordinates of points from a training set). Plus I have added a simple code do draw a nice graph of the training set and its linear separation. I used GD to draw the image. I would also like to thank Amro for helping me finish this algorithm.

Here’s the entire code:
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <gd.h>
-
#include <math.h>
-
-
#define NUMEL 208
-
#define LEARNING_RATE 0.1
-
#define MAX_ITERATION 100
-
-
float randomFloat()
-
{
-
float r = (float)rand() / (float)RAND_MAX;
-
return r;
-
}
-
-
int calculateOutput(float weights[], float x, float y)
-
{
-
float sum = x * weights[0] + y * weights[1] + weights[2];
-
return (sum >= 0) ? 1 : -1;
-
}
-
-
int main(int argc, char *argv[])
-
{
-
srand(time(NULL));
-
-
float x[NUMEL], y[NUMEL], weights[3], localError, globalError, a, b;
-
int outputs[NUMEL], patternCount, i, p, iteration, output;
-
-
FILE *fp;
-
if ((fp = fopen("training-set.txt", "r")) == NULL)
-
{
-
printf("Cannot open file.\n");
-
exit(1);
-
}
-
i = 0;
-
while (fscanf(fp, "%f %f %d", &x[i], &y[i], &outputs[i]) != EOF)
-
{
-
if (outputs[i] == 0)
-
{
-
outputs[i] = -1;
-
}
-
printf("%.4f %.4f %d\n", x[i], y[i], outputs[i]);
-
i++;
-
}
-
patternCount = i;
-
-
system("PAUSE");
-
-
weights[0] = randomFloat();
-
weights[1] = randomFloat();
-
weights[2] = randomFloat();
-
-
iteration = 0;
-
do {
-
-
iteration++;
-
globalError = 0;
-
for (p = 0; p < patternCount; p++)
-
{
-
output = calculateOutput(weights, x[p], y[p]);
-
-
localError = outputs[p] - output;
-
-
// Update weights.
-
weights[0] += LEARNING_RATE * localError * x[p];
-
weights[1] += LEARNING_RATE * localError * y[p];
-
weights[2] += LEARNING_RATE * localError;
-
-
globalError += (localError * localError);
-
}
-
-
/* Root Mean Squared Error */
-
printf("Iteration %d : RMSE = %.4f\n", iteration,
-
sqrt(globalError / patternCount));
-
-
} while (globalError != 0 && iteration <= MAX_ITERATION);
-
-
// Display network generalisation.
-
printf("X Y Output\n");
-
float j, k;
-
for (j = -1; j <= 1; j += .5)
-
{
-
for (j = -1; j <= 1; j += .5)
-
{
-
// Calculate output.
-
int output = calculateOutput(weights, j, k);
-
printf("%.4f %.4f %s\n", j, k, (output == 1) ? "Blue" : "Red");
-
}
-
}
-
-
// Display modified weights.
-
printf("Modified weights: %.2f %.2f\n", weights[0], weights[1]);
-
-
// Create image representation.
-
gdImagePtr im;
-
im = gdImageCreateTrueColor(600, 600);
-
if (im != 0)
-
{
-
// Allocate colors.
-
int white = gdImageColorAllocate(im, 255, 255, 255);
-
int lightGrey = gdImageColorAllocate(im, 220, 220, 220);
-
int black = gdImageColorAllocate(im, 0, 0, 0);
-
int blue = gdImageColorAllocate(im, 0, 0, 255);
-
int red = gdImageColorAllocate(im, 255, 0, 0);
-
int green = gdImageColorAllocate(im, 0, 200, 50);
-
-
// White flood fill.
-
gdImageFill(im, 0, 0, lightGrey);
-
-
// Points.
-
float cx, cy;
-
for (i = 0; i < patternCount; i++)
-
{
-
// Calculate output.
-
int output = calculateOutput(weights, x[i], y[i]);
-
-
cx = floor(300 + 30*x[i] + 0.5);
-
cy = floor(300 - 30*y[i] + 0.5);
-
-
int color = (output == 1) ? blue : red;
-
-
gdImageFilledEllipse(im, (int)cx, (int)cy, 5, 5, color);
-
}
-
-
// Linear separation
-
a = -weights[0] / weights[1];
-
b = -weights[2] / weights[1];
-
printf("Decision boundary (line) equation: y = %.4fx + %.4f\n", a, b);
-
// x = -10 => y = -10a+b
-
// x = 10 => y = 10*a + b
-
-
gdImageLine(im, 0, (int)(300 + 300*a - 30*b), 600, (300 - 300*a - 30*b), green);
-
-
// X coordinate.
-
gdImageLine(im, 0, 300, 600, 300, black);
-
-
// Y coordinate.
-
gdImageLine(im, 300, 0, 300, 600, black);
-
-
fp = fopen("training.png", "wb");
-
if (fp != 0)
-
{
-
gdImagePng(im, fp);
-
fclose(fp);
-
}
-
}
-
gdImageDestroy(im);
-
-
system("PAUSE");
-
return 0;
-
}
I used the Dev C++ to write the program. Here is how to use GD in Dev C++.
#include <stdlib.h>
#include <gd.h>
#include <math.h>
float randomFloat()
{
srand(time(NULL));
float r = (float)rand() / (float)RAND_MAX;
return r;
}
int calculateOutput(float weights[], float x, float y)
{
float sum = x * weights[0] + y * weights[1];
return (sum >= 0) ? 1 : -1;
}
int main(int argc, char *argv[])
{
// X coordinates of the training set.
float x[] = {
-3.2, 1.1, 2.7, -1
};
// Y coordinates of the training set.
float y[] = {
1.5, 3.3, 5.12, 2.1
};
// The training set outputs.
int outputs[] = {
1, -1, -1, 1
};
int patternCount = sizeof(x) / sizeof(int);
float weights[2];
weights[0] = randomFloat();
weights[1] = randomFloat();
float learningRate = 0.01;
int iteration = 0;
int i, p;
float globalError;
do {
globalError = 0;
int p = 0; // iterator
for (p = 0; p < patternCount; p++)
{
// Calculate output.
int output = calculateOutput(weights, x[p], y[p]);
// Calculate error.
float localError = outputs[p] – output;
if (localError != 0)
{
// Update weights.
for (i = 0; i < 2; i++)
{
float add = learningRate * localError;
if (i == 0)
{
add *= x[p];
}
else if (i == 1)
{
add *= y[p];
}
weights[i] += add;
}
}
// Convert error to absolute value.
globalError += fabs(localError);
printf(“Iteration %d Error %5.2f\n”, iteration, globalError);
iteration++;
}
} while (globalError != 0);
// Display network generalisation.
printf(“X Y Output\n”);
float j, k;
for (j = -1; j <= 1; j += .5)
{
for (j = -1; j <= 1; j += .5)
{
// Calculate output.
int output = calculateOutput(weights, j, k);
printf(“%5.2f %5.2f %s\n”, j, k, (output == 1) ? “Blue” : “Red”);
}
}
// Display modified weights.
printf(“Modified weights: %5.2f %5.2f\n”, weights[0], weights[1]);
// Create image representation.
gdImagePtr im;
FILE *fp;
im = gdImageCreateTrueColor(600, 600);
if (im != 0)
{
// So the points are further from each other
// and the graph is more readable.
int multiplier = 50;
// Allocate colors.
int white = gdImageColorAllocate(im, 255, 255, 255);
int lightGrey = gdImageColorAllocate(im, 220, 220, 220);
int black = gdImageColorAllocate(im, 0, 0, 0);
int blue = gdImageColorAllocate(im, 0, 0, 255);
int red = gdImageColorAllocate(im, 255, 0, 0);
int green = gdImageColorAllocate(im, 0, 200, 50);
// White flood fill.
gdImageFill(im, 0, 0, lightGrey);
// Points.
float cx, cy;
for (i = 0; i < patternCount; i++)
{
// Calculate output.
int output = calculateOutput(weights, x[i], y[i]);
cx = floor(300 + multiplier*x[i] + 0.5);
cy = floor(300 – multiplier*y[i] + 0.5);
int color = (output == 1) ? blue : red;
gdImageFilledEllipse(im, (int)cx, (int)cy, 10, 10, color);
}
// Linear separation.
float a = 0, b = 0;
for (i = 0; i < patternCount; i++)
{
int fx = (a > 0 && b > 0) ? 1 : 0;
a += learningRate * (y[i] – fx) * x[i];
b += learningRate * (y[i] – fx);
}
printf(“y = %5.2fx + %5.2f\n”, a, b);
// x = -300 => y = -300*a + b
// x = 300 => y = 300*a + b
gdImageLine(im, -2, (int)(300 + multiplier*300*a + b), 598, (int)(300 – multiplier*300*a + b), green);
gdImageLine(im, -1, (int)(300 + multiplier*300*a + b), 599, 300 – (int)(multiplier*300*a + b), green);
gdImageLine(im, 0, (int)(300 + multiplier*300*a + b), 600, 300 – (int)(multiplier*300*a + b), green);
gdImageLine(im, 1, (int)(300 + multiplier*300*a + b), 601, 300 – (int)(multiplier*300*a + b), green);
gdImageLine(im, 2, (int)(300 + multiplier*300*a + b), 602, 300 – (int)(multiplier*300*a + b), green);
// X coordinate.
gdImageLine(im, 0, 300, 600, 300, black);
// Y coordinate.
gdImageLine(im, 300, 0, 300, 600, black);
fp = fopen(“training.png”, “wb”);
if (fp != 0)
{
gdImagePng(im, fp);
fclose(fp);
}
}
gdImageDestroy(im);
system(“PAUSE”);
return 0;
}
Here are three useful MATLAB commands.
To clear the command line:
clc
To clear all variables:
clear all
To clear the command history:
com.mathworks.mlservices.MLCommandHistoryServices.removeAll
Just putting this information down for my own reference so I won’t have to search for it later.
If you are a high school or college student you can download Windows Server 2008 R2 Standard Edition for free from the Microsoft DreamSpark website. You can also download Visual Studio, Expression Studio and other useful applications for free.
The only thing you need is a valid Hotmail e-mail account and an ISIC card number. It’s very easy
I often need to test several Zend Framework projects on my local machine (I’m running Windows Vista and WAMPSERVER 2.0). To do that, I just create a virtual host for every project. There are just two files you have to modify:
- C:\wamp\bin\apache\Apache2.2.11\conf\httpd.conf
- C:\Windows\System32\drivers\etc\hosts
Paths to those files may differ on your PC, depends on the installation.
For instance, you might want to save your Zend Framework project to “C:\wamp\www\myproject” and access it with “http://myproject”. Add this at the end of the httpd.conf file:
NameVirtualHost *:80
<VirtualHost *:80>
ServerName myproject
DocumentRoot "C:\wamp\www\myproject"
</VirtualHost>
Now open the hosts file and write on the last line:
127.0.0.1 myproject # my cool ZF project
Restart all services and it should work.
As promised, here’s how to change your MAC address in Windows Vista (this method will hopefully also work in Windows 7).
Go to Start -> Control Panel -> View network status and tasks -> Manage network connections (in the left sidebar).
Choose the connection for which you want to change the MAC address, right click on it and select “Properties”.
Click on the “Configure” button and go to “Advanced” tab. In the “Property” box look for “Network address”. Now you should see a window like this:

Instead of “000000000000″ fill in your desired MAC address and press “OK” button. Open the command prompt and check that the MAC address got changed:
ipconfig /all
From time to time you will need to change the MAC address of your computer. My Internet provider, for instance, allows me to connect only my desktop PC to the Internet. To connect my laptop I had to change its MAC address to the same MAC address my desktop PC has.
First, donwload Macshift and save it to some convenient location like C:\ and extract it.
Second, you must know the name of the connection you want to change. Usually it will be the Ethernet called “Local Area Connection”.
Third, open the command line (Start -> Run -> “cmd”) and type:
cd C:\macshift
The above command moved you to the C:\macshift directory. Now type (just substitute 012345123456 with an actual MAC address):
macshift 012345123456 -i "Local Area Connection"
If you want to find out what MAC addres your PC has, type in the command line:
ipconfig /all
And look for “Physical Address”.
However, this works only in Windows XP. I will cover Windows Vista/Seven in my next post.