Number of visits counter

There is possible to write a number of accesses directly to the text of the page. For our study subject, it is more interesting to create a counting picture; it will be auto-increased every time when being displayed.

As the first, we will try to display a number send by form. The form can be simple:

<form action="zobraz.php" method="get">
Enter integer number (no error check!):&nbsp;
<input type="text" name="cislo"> 
<br>
<input type="submit" name="submit" value="display">
</form>

Note, that the following text will assume the "register globals" allowed (it will be described while file upload task). If not, please do as the first:

$cislo = $_GET["cislo"];

For clearly graphics solution, we will need a picture with all possible digits, from zero to nine. Each of the digits should have the same width. If it is possible, use the gif format - jpeg is easier to find, but it is better for photos (on the next picture, example is a jpeg):

For example, in this case, each digit is 25 dots wide and 39 dots height (this number will be used in the script without more explanation, as constant). The picture alone is a little bigger. We can copy single digit from this picture, for example the "5" to position no. 2 we can copy by the function:

imagecopy($dst, $src, 2*25, 0, 5*25, 0, 25, 39);

We have assumed $src and $dst as names of images in memory. The source image was created by imagecreatefromjpeg function, the destination image could be created by

$dst = imagecreatetruecolor(25*4, 39);

For displaying, the number has to be split into single digits. The last digit is obvious, it is a modulo after division by 10:

$c = $cislo % 10;

For getting the rest of the number, we need to divide it by ten, but as an integer. Problem is, that we cannot use solution typical for other languages, for example like C++ " cislo = cislo \ 10; ", because surprisingly we have not integer division in php. We have to use a different method:

$cislo = ($cislo - ($cislo % 10)) / 10;

or better $cislo = ($cislo - $c) / 10; , because modulo has been already calculated. Another possibility is to call a floor function after floating point division:

$cislo = floor($cislo / 10);

, which round a number to nearest lower integer (work wrong for negative values, but we will display only natural numbers). Division is faster, the floor function will guarantee to get integer value.

Another possibility is to convert $cislo to a text string using sprintf(%d, $cislo); function and disassemble to single digits by str_split function:

$str = sprintf(%d, $cislo);
$letters = str_split($str, 1);

After this operation, each letter have to be converted to number; if we remember, that ASCII code of "0" is 48, we can use the "ord" function to get the number of characters in the ASCII and then simply subtract the 48 (numbers are in most of computer codes as a sequence) - we can use command like:

$cislice[3] = ord($letters[3])-48;

Another possibility is to use the intval( ) function.

In the next example, we will use the integer division method. The main cycle will look like:

for ($i=3; $i>=0; $i--) {
  $c = $cislo % 10;
  $cislo = ($cislo - $c) / 10;
  imagecopy($dst, $src, $i*25, 0, $c*25, 0, 25, 39);
}

To be correct, we should set the background color first. It is only a formal error, because we will fill all the picture pixels by our letters.

We have tried how to work with pictures in the previous task.

If you like to test it, please visit the Czech examples: pocitadlo.htm (pocitadlo.htm) (insert the four-digit number to the edit box and press the only button), or you can call it directly as http://zpp.wz.cz/zobraz.php?cislo=3573 (using the GET method, we can change the number from the address line).


The next problem is where to save the number on the server. Because working with files is problematic, I would prefer using the SQL database. For the simplest solution, we can create a table with only one line; to access it with SQL, it is reasonable to add a next item (it is named "key" here), to create the SELECT command easy. The example of the table:

cislo key
57 77

We can read the correct line, if we are using the correct key (just a simple SELECT without WHERE cause could (after any unwanted access into the table) respond a wrong line). It is important to fill some starting values into the table.

In the next script, we will open the database, read the value of our variable, increase it by one, and write it back. By using the UPDATE function, we will rewrite the previous value. SQL keywords are written in bold. Note, that there is no error checking:

mysql_connect('mysql.webzdarma.cz','zpp','[password]')
   or die('Error: '.mysql_error() );
mysql_select_db('zpp');
$result=mysql_query('select * from pocitadlo where key=77');
$cislo=intval(mysql_result($result,0,"cislo"));

//increment and the only table line rewritting:
$cislo++;
$result=mysql_query('update pocitadlo set cislo='.$cislo.' where key=77;');
mysql_close();     

Now, we have the number, so we can use the previous script for the picture generation.


In some cases, there could be interesting to keep a record, which computer asks for our picture. Because the counter will be used as a picture, created on the client computer demand, we will get at least the ip address. (It is a pity, that in the last years, it will be mostly the proxy server address, not the client itself.) In this case, we have to change the table structure - each access to the table will add a line with the "client" ip address. There could be used the auto_increment property, but we have to look for the maximum value in the number ("cislo") column, so we can calculate it "manually":

$result=mysql_query('select max(cislo) as minuly from pocitadlo');
$cislo=intval(mysql_result($result,0,"minuly"));

//increment, then table rewritting:
$cislo++;
$result=mysql_query('insert into pocitadlo values ('.$cislo.',"'.$_SERVER["REMOTE_ADDR"].'");');

"select max(cislo)" is not a function, but special method for the SELECT calling, which will select the maximum value from the "cislo" column. In this example, I have used the "as" directive, which causes renaming of the result in the associative array returned by the mysql_result function - just for keeping the next line understandable, better than to have two times the word "cislo".

This example is not complete, opening and closing of the database and picture generation should be the same, as in the previous example.

Warning: Now, the second column in the table "pocitadlo" have to be declared as text (i.e. varchar2), at least 16 letters long.

This is all, you can try it...

BTW - how to create more counters? For us, the simplest way is to create more tables and more php scripts. If we don't like to record ip addresses, we can create one line for each counter, and then distinguish them for example by passing another parameter using the GET method (simply add a parameter to the url while script calling, for example http://zpp.wz.cz/3pocitadlo.php?k=37).

Tested on the webzdarma server: http://zpp.wz.cz/0pocitadlo.php, or http://zpp.wz.cz/1pocitadlo.php - for the php code listing, there are text versions: 0pocitadlo.txt and 1pocitadlo.txt .

Dictionary (only the variable names were not translated):

cislo number
pocitadlo counter
minuly previous
zobraz display

Real solution for our pages | try "echo" version | text version of this