1. Trang chủ
  2. » Công Nghệ Thông Tin

Tài liệu Migrating Web Applications to PHP ppt

70 390 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Migrating Web Applications to PHP
Trường học Unknown
Chuyên ngành Computer Science
Thể loại Báo cáo chuyên đề
Năm xuất bản 2003
Thành phố Unknown
Định dạng
Số trang 70
Dung lượng 1,7 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Conquer JpGraphXML Transformation With PEAR Using PEAR::XML_Transformer Advanced Features Revealed Form Validation From the Outside In A New And Interesting Perspective Practical Web Se

Trang 1

Conquer JpGraph

XML Transformation With PEAR

Using PEAR::XML_Transformer

Advanced Features Revealed

Form Validation From the Outside In

A New And Interesting Perspective

Practical Web Services with PHP

Computer Science Concepts With PHP

Writing A Parser And Expression Evaluator

Trang 2

As PHP’s importance grows on the IT

scene—something that is happening every

day—it’s clear that its true capabilities go

well beyond what it’s being used for

today The PHP platform itself has a lot of

potential as a general-purpose language,

and not just a scripting tool; just its basic

extensions, even discounting repositories

like PEAR and PECL, provide a

high-quality array of functionality that most of

its commercial competitors can’t afford

without expensive external components.

At php|a, we’ve always felt that our

mis-sion is not limited to try our best to

pro-vide the PHP community with a

publica-tion of the highest possible quality We

think that our role is also that of

reinvest-ing in the community that we serve in a

way that leads to tangible results.

To that end, this month we’re launching

the php|architect Grant Program, a new

initiative that will see us award two

$1,000 (US) grants to PHP-related

proj-ects at the end of June.

Participating to the program is easy We

invite all the leaders of PHP projects to register with our website at

their applications for a grant Our goal is

to provide a financial incentive to those projects that, in our opinion, have the opportunity to revolutionize PHP and its position in the IT world.

In order to be eligible for the Grant Program, a project must be strictly related

to PHP, but not necessarily written in PHP.

For example, a new PHP extension written

in C, or a new program in any language that lends itself to using PHP in new and interesting ways would also be acceptable The only other important restriction is that

the project must be released under either

the LGPL, the GPL or the PHP/Zend license Thus, commercial products are

Program

Trang 3

Migrating From Proprietary Tools to PHP

From Electronic Microsystems

PostgreSQL Manager and MySQL Manager

Trang 4

Visit www.zend.com

for evaluation version and ROI calculator

Zend Performance Suite

Reliable Performance Management for PHP

Serve More.

With Less.

The designers of PHP offer you the full spectrum of PHP solutions

Trang 5

Marco Tabini

Editor-in-Chief

Brian K Jones brian@phparch.com

Editorial Team

Arbi ArzoumaniBrian JonesPeter JamesMarco Tabini

Graphics & Layout

Although all possible care has been placed in assuring the accuracy of the contents of this magazine, including all associated source code, listings and figures, the publisher assumes no responsibilities with regards of use

of the information contained herein or in all associated material.

Copyright © 2002-2003 Marco Tabini & Associates,

Inc — All Rights Reserved

p

ph hp p||a ar rc ch hiit te ec ct t:: A A N Ne ew w

C

Co om mm mu un niit ty y

Since I first came on board as an editor

here (only days after the launch of

php|architect’s first issue), I’ve had the

dis-tinct pleasure of forming relationships

with some of the greatest minds in the

PHP community As a budding Editor in

Chief, it has become quite clear to me that

our ability to form synergistic,

collabora-tive relationships with our authors is

something of an anomaly in the magazine

publishing industry Lucky for me, it’s one

that is a welcome change to the authors

I’ve interacted with I’m proud to have a

part in creating this apparently new

para-digm in publishing, and this seemingly

new perspective on the editor-author

rela-tionship

I like to think of the editorial process as

the creation of what I am now dubbing ‘A

New Community’; A new community of

people from different walks of life, having

vastly different views on how different

technologies should work together,

differ-ent experiences to share, and from

dis-parate cultures and geographic regions of

the Earth A community bonding on the

common goals of furthering both the

development of PHP as a complete, stable,

mature development platform, and the

progress of other PHP developers.

The end result of this highly iterative,

interactive process is what is ultimately

delivered to you by php|architect every

month Not just a magazine, but a

some-what interactive experience in itself Let’s

not forget that in addition to working hard

to produce the magazine each month, the

members of our editorial staff are also

con-sumers of this magazine! As a result, we

experience along with all of you the

feel-ing that we are really befeel-ing taken by the

hand through what seems like a tour of a

particular project undertaken by a

particu-EDITORIAL

Trang 6

lar developer At the end of the tour, we’re

handed the bits of code which are out in

production somewhere, making things

tick As a consumer, I find this amazingly

useful I hope anyone reading this agrees,

or will send me email telling me how we

can make things even better

In addition, I invite those who might

cur-rently be passive consumers of information

to get involved! If you’re reading this,

you’re quite likely a PHP developer.

Chances are also good that you have a

unique opinion or perspective on some

aspect of technology that touches us here

in the PHP community We invite you to

participate more actively in the ‘New

Community’ by sharing your knowledge,

thoughts, and ideas with the rest of us.

We’ve just released a new version of our

author’s guidelines , which can help get

you started Anything that this leaves you

wondering about can be addressed by

ask-ing our editorial staff at

write@phparch.com

It could very well be that you haven’t

participated yet because you haven’t seen

a product offered by php|architect that

looks like a good fit for your own work.

Maybe you want to write a book, or start a

new project of unforeseeable dimensions I

urge anyone in this position to write to

editors@phparch.com with your concerns

in this area It’s quite possible that we have

a project in the works that could benefit

from your input

The plain and unequivocal fact is that

php|architect is growing quite rapidly This

growth stems from the ideas of those

col-laborating on the direction of

php|archi-tect as a diversified company – not just a

magazine For example, php|architect has

recently been translated and redistributed

in Japanese for that market This has been

a successful venture for all of those

involved, as well as the community at

large, and we urge any other parties

inter-ested in localized versions of php|architect

to contact us – editors@phparch.com What’s more, php|architect will soon see the release of our first full-fledged book, with more work in this area ongoing I won’t use this space to divulge the details now, but stay tuned to my monthly edito- rial for more as things progress In the wake of Wrox’s disappearance from the publishing world (a result of their parent company’s apparent insolvency), we at php|architect feel some obligation to at least partially fill the gap that will inevitably result in the area of authoritative PHP coverage From someone who owns several Wrox books, I can sincerely say that their work is well appreciated, and will be sorely missed We can only hope to do our best to keep up with the needs of a con- stantly growing developer base Luckily,

we don’t have to have the breadth of erage in our books that Wrox had in theirs – I have no desire to work on a Java book! These are just a couple of the ideas we’re currently pursuing Since no entity can claim monopoly ownership over all good ideas, it’s only natural that we reach out and make it known that we are a compa-

cov-ny which fosters and values ideas If you have an idea for which an outlet has yet to

be identified, we hope you’ll consider tacting us for help in discovering how best

con-to pursue your goals

Now on with the show! I’m excited by what lies between this editorial and Marco’s exit(0) (actually, I kinda like the editorial and exit(0) as well) I hope you can find enlightenment and inspiration from the articles which follow Let us know your thoughts:

editors@phparch.com

Trang 7

The PHING is Loose!

PHING (PHing Is Not Gnumake) is a make toolwritten in PHP and based on the ideas and con-cept of Apache Ant It can basically do anythingyou could do with a build system like Gnumake,for example, but uses XML for storing the targetsand commands Using XML, Phing avoids prob-lems like the “Space before tab problem” inGnumake Current features include processingfiles while copying (e.g do Token Replacement,XSLT transformation etc.) and various file systemoperations

Phing is written in the PHP scripting languageand designed to be extensible Thus, you can eas-ily add the behaviour you need for your project byadding a class (known as tasks) Additionally,Phing is platform independent and runs on Unixlike systems and Windows Phing is currently used

to build binarycloud, a PHP ApplicationFramework, and is maintained by its developers.For more information, or to download Phing,visit its website at http://binarycloud.com/phing/

PHP Architect Wo Yomitai!

We’re happy to announce the introduction of the Japanese edition of php|architect!Published by Asial Corporation, the best PHP company in Japan, the publication is called PHPProgrammer’s Magazine and it pro-

vides all the great content of php|a,

plus many localized features

specif-ic to the Japanese market

Asial (http://www.asial.co.jp) is a

Tokyo-based company that

special-izes in the production of PHP

sys-tems and the localization of

soft-ware and documentation for the

Japanese market

You can find the PHP

Programmer’s Magazine website at

http://www.phppro.jp

If you are interested in localizing

php|a in your language, don’t

hesi-tate to drop us a note at

info@phparch.com

ionCube Announces

Special Offer

The ionCube standalone PHP encoder is a high

per-formance and complete PHP encoding solution,

employing the technique of compiled code

encod-ing to maximize both runtime performance and

code protection Encoded scripts can be run by the

free Loader product with a standard PHP server in

one of two ways The Loader can be installed in

php.ini, and this delivers the best performance and

is compatible with safe mode For users with no

access to php.ini, on many systems the Loader can

be installed “on demand” by the scripts themselves

This requires no php.ini edits or server restart

The Base Edition comes with a single user license

and, as with all current ionCube products, full

sup-port and upgrades are included for Free

To download an evaluation or purchase of the

standalone encoder, you can visit the ionCube

web-site at http://www.ioncube.com

Trang 8

NEW STUFF

eZ publish 3 Released

ezPublish 3 is a professional open source content

management system and development

frame-work

As a CMS its most notable feature is its

revolu-tionary, fully customizable and extendable content

model This is also what makes it suitable as a

plat-form for general web development Its

stand-alone libraries can be used for cross-platform,

database independent PHP projects eZ publish is

also well suited for news publishing, e-commerce

(B2B and B2C), portals, and corporate web sites,

intranets, and extranets

For more info, visit the eZPublish website at

http://ez.no

phpOpenTracker 1.1.1 Is

Unleashed!

phpOpenTracker is a framework solution for the

analysis of Web site traffic and visitor behaviour

It features a logging engine that, either invoked

as a Web bug by an HTML image tag or

embed-ded with two lines of code into your PHP

applica-tion, logs each request to a Web site into a

data-base One installation can track an arbitrary

num-access the gathered data and perform complexoperations on it (for instance, the analysis of yourvisitors’ click paths)

For more information, visit the phpOpenTrackerwebsite at http://www.phpopentracker.de/

MySQL AB Launches MySQL 4.0, Announces Certification Program

MySQL AB, producers of the popularMySQL database management system,have announced the release of version4.0 of their flagship product, which isnow officially ready for production Meanwhile,they have started development of version 4.1,which will include such long-awaited goodies assubqueries

Through the MySQL certification program,MySQL software developers can earn one or moreformal credentials that validate their knowledge,experience and skill with the MySQL database andrelated MySQL AB products

The MySQL certification program consists of eral unique certifications The first, which is nowgenerally available, is called the MySQL CoreCertification The Core Certification providesMySQL users with a formal credential that demon-strates proficiency in SQL, data entry and mainte-nance, data extraction for reporting and more.The MySQL Professional Certification, which will

sev-be available in Q3 of this year, is for the moreexperienced MySQL user who wants to certify his

or her knowledge in MySQL database ment, installation, security, disaster preventionand optimization MySQL Core certification will be

manage-a prerequisite for tmanage-aking the Professionmanage-alCertification exam

MySQL also plans to offer a MySQL PHPCertification by the end of the year, which isdesigned for the MySQL and PHP developer whowants to simultaneously certify his knowledge ofMySQL and of the PHP Web development tool Inaddition, a MySQL DBA Certification, a top-levelcertification for the most accomplished MySQLgurus, will be offered in 2004

If you are interested and want to know more,check out the MySQL website at

http://www.mysql.com

PHP 4.3.2RC1 Released

The first public release candidate of the

lat-est version of PHP was posted for

down-load on the PHP.Net website earlier this

month The new version includes several

bug fixes and a few new features

com-pared to version 4.3.1, which was released

in February in response to a CGI-related

security issue

For more information, visit the PHP

web-site at http://www.php.net

Trang 10

class library that easily enables you to generate

profes-sional quality graphs using a minimal amount of code

This article is a case study illustrating some of JpGraph’s

advanced features; specifically, it covers the following:

• a generalized methodology for JpGraph script

development

• the evolutionary process of developing a

graph (in contrast to presenting only the final

product)

• the use of server-side caching with JpGraph

for performance

• the use of Client Side Image Maps (CSIM) to

implement “drill-down” functionality in your

graphs

Installation and Environment

The easiest way to get started with JpGraph is to

down-load the source, available at

http://www.aditus.nu/jpgraph/jpdownload.php Next,

unpack the source archive into a directory in PHP’s

include path Now you can modify the paths to your

installed fonts, as well as to the cache directory These

settings are found in jpgraph.php.

testsuit.php file in the examples directory This page

generates over 200 example graphs using JpGraph,and allows you to review the code for each of them

If you’re just learning JpGraph and exploring its bilities, you will find the manual very handy It’s avail-able athttp://www.aditus.nu/jpgraph/jpdownload.php, andhas both a narrative text and an excellent class refer-ence You might also want to visit the JpGraph supportforum at http://jpgraph.fan-atics.com/

capa-All of the scripts in this article were developed andtested using PHP 4.3.0 (with the built-in GD2 library)running as a module under Apache 1.3.27 on RedHatLinux 7.2

The code in this article was developed using MySQL(http://www.mysql.com/) as a database, and ADOdb(http://php.weblogs.com/adodb) as a databaseabstraction layer To this end, all of the scripts include

a common file called phpa_db.inc.php, shown in

Listing 1

JpGraph

By Jason E Sweat

This article originated as a case study in the newest book

in the Wrox Handbook series: PHP Graphics

(http://www.wrox.com/books/1861008368.htm).

This material was omitted in the final publication of the

book, and was modified for presentation here

PHP Version: 4.0.4 minimum, 4.1 recommended O/S: Any

Additional Software: JpGraph, GD Enabled PHP

REQUIREMENTS

Trang 11

FEATURES Advanced Features in JpGraph

This include file creates an ADOdb connection object

named $conn which is used to access the database

throughout the rest of the scripts You'll want to

change the Connect() call's parameters to reflect

your setup, including the name of the database you

create for the examples

ADOdb needs to be installed in a directory in PHP's

include path For readers unfamiliar with the ADOdb

API, I'll give a very brief overview of some of the basic

functionality In ADOdb you can fetch the results of an

SQL statement using

If your query is successful, this method will return an

ADOdb resultset object If not, the method will return

false Two resultset methods that are useful are

return a vector of rows where each row is an associative

array of 'COLUMN' => 'VALUE' The GetAssoc()

method will return an associative array, instead of a

vec-tor, where the index of the returned array for each row

is the value of the first column

The examples below assume that you have the type 'Arial' font installed If this is not the case, JpGraphwill emit an error to this effect An easy way to getaround this is change all of the references to the

a built-in system font, and while it won't look as pretty

That should be enough to get you through the ples ahead Let's take a look at the case study

exam-Case StudyOur case study will look at the sales data for the ABCCompany, a fictitious manufacturer of widgets ABCmakes everything from the economical $12.99 Widget

B through to the ultra-deluxe $1,499.50 Widget E Thisstudy focuses on the sales in the continental UnitedStates, in which the company is divided into fourregions The company sells to resellers via three chan-nels: the Internet, a call center and various retail outlets.You are asked to create a graph depicting the sales inunits and dollars You'll need to further split this graph

by catalog item for each sales region, and make a parison to the forecasted sales ABC also requires thatyou create a graph showing the year-to-date sales bychannel for each region They need to be able to nav-igate quickly between the two graphs

com-Database DesignSix tables compose ABC's data model The central

table is abc_sales This table tracks information

about sales, including the time, the sales channel, thelocation, the item, the quantity sold, and the revenuegenerated

$rs = $conn -> Execute ( $sql_statement ,

$bind_array );

<?php

error_reporting ( E_ALL );

require_once 'adodb/adodb.inc.php' ;

define ( 'MYSQL_DT_FMT' , '%Y-%m-%d' );

$conn = & ADONewConnection ( 'mysql' );

Trang 12

FEATURES Advanced Features in JpGraph

The other tables making up the data model are

abc_catalog , abc_channel, abc_forecast,

abc_region , and abc_state_region The

abc_catalog table provides a surrogate key for

par-ticular items customers can purchase, a description of

the item, and the current unit price of the item The

abc_channel table provides a surrogate key, name

and description of the market channel an item can be

purchased through (web, phone or retail in this study)

The abc_forecast table stores a forecasted sales plan

by item, channel, region and month For each of these

"slices" of data, the quantity and revenue expected are

also stored The abc_region table stores the

surro-gate key and description for each of the company's

sales regions The abc_state_region table is a

map-ping between state abbreviation code and the sales

region to which the state belongs

The SQL used to create the tables, along with 'INSERT'

statements to populate the smaller tables, is included in

this article's source directory in the mysql_ddl.sql

file As for the other tables, the sales and sales forecast

data for the year can be simulated using the scripts

abc_gen_sales.php and abc_fcst_ins.php,

respectively abc_gen_sales.php needs to be run

first, as abc_fcst_ins.php depends on that data it

creates

Sales vs Forecast Graph

Our first task is to create a dynamic graph comparing

the number of units sold and the revenue of those sales

to the forecasts made for each region This information

is considered proprietary by the company, and is not

intended for public distribution They would like the

chart to indicate this

In developing PHP scripts to generate graphs using

JpGraph, I have found the following four-step process

useful:

1 Retrieve and manipulate the data for

plot-ting

2 Create the Graph object and set general

graph properties (like colors and plot axes)

3 Create the Plots to add to the Graph object

graphFollowing this process for graph development, youfirst need to retrieve the sales and forecast data To seehow you use ADOdb to retrieve the data for thesegraphs, please review lines 26-122 of the

abc_reg_sales_graph.php file The focus of thisarticle is on graphing, so the database retrieval andgraph data construction will not be covered in detail.Because the graphs being produced are by region,your script will need to accept and validate a parame-ter for the region If the value passed is a valid region,assign it to the variable $region_id If it is not valid,generate an error

There could be a little problem here Since the put of this script is a graph, your site will most likely

out-refer to this script using an HTML <img> tag, like so:

<img src="abc_reg_sales_graph.php">

If your script outputs a text message (like a PHPerror), this would result in an invalid image, and theonly thing a user will see is the missing image symbolwhere your graph was supposed to be The codeshown in Listing 2 validates the region, and shows how

to create a "graphical" error message This codeassumes you have already queried the database forvalid regions, and stored them in a global array called

Note: These scripts were originally written in

December of 2002 The data is simulated as if the

current date is December 15, 2002 in order to show

graphs with nearly complete data for the year.

Because it is now 2003, the scripts have been

modi-fied to query and show the prior year.

1 $region_id = check_passed_region ( 'region' );

10 if ( array_key_exists ( $parm , $_GET )) {

11 $val = $_GET [ $parm ];

12 if ( array_key_exists ( $val , $regions )) {

Trang 13

FEATURES Advanced Features in JpGraph

the jpgraph.php and jpgraph_canvas.php

library files

After retrieving the "raw" data from your database,

you often need to manipulate it into a format better

suited for graphing This often means making a series

of zero-indexed arrays of single data series' Rather

than have different global arrays for each series, I

pre-fer to have a single associative array named

individual arrays The code in Listing 3 assembles these

pieces into the $graphData array, which will be used

for graphing

Now let's take a look at some of the data by drawing

your first graph This graph

will compare the number

of units moved to the

fore-casted number of units

that should have moved

Listing 4 shows the code

for this

This code highlights the

lightweight nature of the

JpGraph API As you

enhance the appearance

of your graphs, the code

will expand, but the lines

of code required to

pro-duce a functional graph

really are minimal

These few lines of code

complete the four-step

process outlined earlier In

step 2 you create and

con-figure the Graph object

1 $graphData [ 'f_qty' ] = array();

2 $graphData [ 'labelX' ] = array();

3 for ( $i = , $j = count ( $salesData ); $i < $j ; $i ++) {

4 $row = $salesData [ $i ];

5 if ( 'A' == $row [ 'short_desc' ]) {

6 $graphData [ 'labelX' ][] = strftime ( '%b' , mktime ( , 0 , 0 , $row [ 'm' ], 1 , $row [ 'y' ]));

7 }

8 if (! array_key_exists ( $row [ 'm' ]- 1 , $graphData [ 'f_qty' ])) {

9 $graphData [ 'f_qty' ][ $row [ 'm' ]- 1 ] = $fcstData [ $row [ 'f_key' ]][ 'qty' ];

10 $graphData [ 'f_rev' ][ $row [ 'm' ]- 1 ] = $fcstData [ $row [ 'f_key' ]][ 'rev' ];

11 $graphData [ 'qty' ][ $row [ 'm' ]- 1 ] = $row [ 'qty' ];

12 $graphData [ 'rev' ][ $row [ 'm' ]- 1 ] = $row [ 'rev' ];

13 } else {

14 $graphData [ 'f_qty' ][ $row [ 'm' ]- 1 ] += $fcstData [ $row [ 'f_key' ]][ 'qty' ];

15 $graphData [ 'f_rev' ][ $row [ 'm' ]- 1 ] += $fcstData [ $row [ 'f_key' ]][ 'rev' ];

16 $graphData [ 'qty' ][ $row [ 'm' ]- 1 ] += $row [ 'qty' ];

17 $graphData [ 'rev' ][ $row [ 'm' ]- 1 ] += $row [ 'rev' ];

18 }

19 if(! array_key_exists ( $row [ 'short_desc' ], $graphData )) {

20 $graphData [ $row [ 'short_desc' ]][ 'qty' ] = array();

21 $graphData [ $row [ 'short_desc' ]][ 'rev' ] = array();

22 }

23 $graphData [ $row [ 'short_desc' ]][ 'qty' ][] = $row [ 'qty' ];

24 $graphData [ $row [ 'short_desc' ]][ 'rev' ][] = $row [ 'rev' ];

25 }

Listing 3: Composing a single $graphData array

sales_graphdata_loop.php

$graph = new graph ( WIDTH , HEIGHT );

$graph -> SetScale ( 'textlin' );

$b1 = new BarPlot ( $graphData [ 'qty' ]);

$l1 = new LinePlot ( $graphData [ 'f_qty' ]);

Trang 14

FEATURES Advanced Features in JpGraph

In step 3, you create a BarPlot object and a LinePlot

object You complete the process in step 4 by adding

the plots to the graph and using the

Calling Graph::Stroke() with no arguments will

make JpGraph stream the image directly back to the

browser from the PHP script The resulting graph is

shown in Figure 1

The regular style line graph does not really seem

appropriate for this graph, since the data is not really

changing over the course of the month (forecasts are

fixed for the entire month) The forecasts might be

bet-ter represented using the 'step' line graph

Let's incorporate this change and, while we're at it,

take a look at the revenue numbers instead You can

do this by changing the two plots as shown in Listing

5 The output is shown in Figure 2

The next step is to look at both units and revenue on

the same graph Management is more concerned with

meeting the revenue forecast, so forecast revenue

should be the only line graph superimposed on the

chart (as opposed to forecasted units) There are two

challenges here First, by looking at the two charts, you

can see that units and revenue are definitely on

differ-ent scales Second, it would be nice to figure out a way

to have the last step of the line graph plot over the

December bar

To represent units and revenue you will need to usethe second Y-axis feature of Jpgraph Ideally you woulduse a grouped bar graph JpGraph, however, does notallow us to add bars from different scales to the samegrouped bar plot What you can do is use a littledeception to accomplish this Make them two differentgrouped bar plots, and then trick JpGraph into believ-ing that they are next to another bar plot on the samescale by adding a plot to each with all zero values Theeffect here is that one scale has the zero-value plot onthe right, pushing the real plot to the left, while theother scale has the zero-value plot on the left, pushingthe real plot to the right When they are finally com-bined on the graph, they will appear to be a singlegrouped bar plot, but will actually be scaled on theirrespective axes You will need some new data toaccomplish this effect, which we can get in Listing 6

$b1 = new BarPlot ( $graphData [ 'rev' ]);

$l1 = new LinePlot ( $graphData [ 'f_rev' ]);

Figure 2: Using a step-style line plot

for ( $i = , $j = count ( $graphData [ 'labelX' ]); $i < $j ; $i ++) {

$graphData [ 'zero' ][ $i ] = 0 ;

}

//extend the forecast revenue line by repeating the last value

$graphData [ 'f_rev' ][ $j ] = $graphData [ 'f_rev' ][ $j - ];

Listing 6: Creating a zerio-value plot.

Trang 15

FEATURES Advanced Features in JpGraph

You can create a callback function for formatting the

second 'Y-axis' labels JpGraph will then call this

func-tion for each value to be labeled on the axis, and will

use the value returned by the function rather than the

raw number This allows us to format numbers to

dol-lars, for instance, as shown in Listing 7

To generate the plot (shown in Figure 3), modify your

graph generation script to include the code in Listing 8

You have a very presentable graph now, but some

additional information would be useful The company

would like to be able to differentiate between the

dif-ferent widgets' contributions to unit sales and revenue

This can be accomplished by generating a 'stacked' bar

graph, to be added to each of the grouped bar plots

This is shown in Listing 9

This now results in the graph shown in Figure 4

We're almost there Just a little more formatting to

the plot area, axis titles and location of the legend isneeded Also, we need make sure that viewers areaware this graph is for internal purposes only

One technique for marking an image as proprietary is

to add a background image to it In this case, we'll usethe string "ABC Co Proprietary" turned diagonally andrepeated Note the color is much darker than youwould normally want to see on a "watermark" You canadjust this with the

can adjust the brightness, contrast and saturation ofthe image prior to use in the graph This can save youthe effort of doing this externally in an image-process-

ing program See the img/abc-background.png

“ the lines of code required to

produce a functional graph

1 $graph -> SetY2Scale ( 'lin' );

2 $graph -> SetY2OrderBack ( false );

3

4 //generate the individual plots

5 $b1 = new BarPlot ( $graphData [ 'qty' ]);

6 $b2 = new BarPlot ( $graphData [ 'rev' ]);

7 $b2 -> SetFillColor ( 'lightgreen' );

8 $b1z = new BarPlot ( $graphData [ 'zero' ]);

9 $b2z = new BarPlot ( $graphData [ 'zero' ]);

10 $l1 = new LinePlot ( $graphData [ 'f_rev' ]);

11 $l1 -> SetStepStyle ();

12 $l1 -> SetColor ( 'darkgreen' );

13 $l1 -> SetWeight ( );

14

15 //create the grouped plots

16 $gb1 = new GroupBarPlot (array( $b1 , $b1z ));

17 $gb2 = new GroupBarPlot (array( $b2z , $b2 ));

Trang 16

FEATURES Advanced Features in JpGraph

file in this article's source directory for an example of

what this background image could look like

You can use this image as the background by using

the code shown in Listing 10

You can use the code in Listing 11 to add the

finish-ing touches like graph and axis titles, and to adjust the

legend placement The output of this code is shown in

Figure 5

For performance reasons, you decide to implement

the JpGraph image-caching mechanism on this graph

This caching is accomplished by saving a copy of your

graph as a file on the server Instead of generating the

image on-the-fly, this cached file is streamed back (if

the cached copy is still valid) Note that the web

serv-er must have write access to the directory in which the

cached images are saved

Instead of creating the Graph class instance with just

the width and height parameters, you will need to also

pass in a name for the cached image, a timeout value

in minutes (how long the image is valid), and a final

parameter telling JpGraph to continue to stream the

images This means that you will still use the PHP script

itself as the image tag's 'src' parameter The code

nec-essary to implement caching is shown in Listing 12

Note: There is a conflict with the

the GD2 library that comes bundled with PHP 4.3.0.

If you have upgraded to this version, you will have to

fall back to the method of adjusting the image with

an editor until the conflict is resolved.

Figure 4: Using stacked bars

1 $colors = array( 'pink' , 'orange' , 'yellow' ,

'lightgreen' , 'lightblue' );

2

3 $abqAdd = array();

4 $abrAdd = array();

5 for( $i = , $j = count ( $items ); $i < $j ; $i ++) {

6 $key = $items [ $i ][ 'short_desc' ];

7 $b1 = new BarPlot ( $graphData [ $key ][ 'qty' ]);

16 $ab1 = new AccBarPlot ( $abqAdd );

17 $ab2 = new AccBarPlot ( $abrAdd );

18 $b1z = new BarPlot ( $graphData [ 'zero' ]);

19 $b2z = new BarPlot ( $graphData [ 'zero' ]);

20

21 $gb1 = new GroupBarPlot (array( $ab1 , $b1z ));

22 $gb2 = new GroupBarPlot (array( $b2z , $ab2 ));

web.”

Trang 17

FEATURES Advanced Features in JpGraph

Now if the same graph - for the same region - is

requested more than once within 24 hours (our

time-out value of 60 minutes * 24 hours) , the cached

ver-sion will be streamed back to the browser, and no code

after the 'new Graph()' line will be executed This

means that in order to maximize the gains from

caching you will want to move the Graph object

instan-tiation prior to any expensive database queries

if ( USING_TRUECOLOR ) {

$graph -> SetBackgroundImage ( 'img/abc-background_prefade.png' , BGIMG_FILLFRAME );

} else {

//AdjBackgroundImage only works with GD, not GD2 true color

$graph -> SetBackgroundImage ( 'img/abc-background.png' , BGIMG_FILLFRAME );

$graph -> AdjBackgroundImage ( 0.9 , 0.3 );

}

Listing 10: Code to use and adjust the background image.

background_image.php

1 $graph -> title -> Set ( date ( 'Y' ) " Sales for { $regions [ $region_id ]} Region" );

2 $graph -> title -> SetFont ( FF_ARIAL , FS_BOLD , 12 );

3 $graph -> SetMarginColor ( 'white' );

4 $graph -> yaxis -> title -> Set ( 'Left Bar Units Sold' );

5 $graph -> yaxis -> title -> SetFont ( FF_ARIAL , FS_BOLD , 10 );

6 $graph -> yaxis -> SetLabelFormatCallback ( 'y_fmt' );

7 $graph -> yaxis -> SetTitleMargin ( 48 );

8 $graph -> y2axis -> title -> Set ( 'Right Bar Revenue ( $ 000 )' );

9 $graph -> y2axis -> title -> SetFont ( FF_ARIAL , FS_BOLD , 10 );

10 $graph -> y2axis -> SetTitleMargin ( 45 );

11 $graph -> y2axis -> SetLabelFormatCallback ( 'y_fmt_dol_thou' );

12 $graph -> xaxis -> SetTickLabels ( $graphData [ 'labelX' ]);

13

14 $graph -> legend -> Pos ( 0.5 , 0.95 , 'center' , 'center' );

15 $graph -> legend -> SetLayout ( LEGEND_HOR );

16 $graph -> legend -> SetFillColor ( 'white' );

17 $graph -> legend -> SetShadow ( false );

18 $graph -> legend -> SetLineWeight ( );

Listing 11: Code to finalize the graph in Figure 5.

fifth_graph.php

Figure 5: Completed regional graph

define ( 'GRAPH_NAME' , 'abc_reg_sales' );

$graphName = GRAPH_NAME $region_id '.png' ;

Trang 18

FEATURES Advanced Features in JpGraph

Region-by-Channel Graph

The second type of graph you were asked to create

shows the sales for each region by channel, and needs to

provide an easy way of navigating to the first graph you

constructed This type of report means viewing the

infor-mation in proportions, so a pie graph may be effective

Again, please review lines 22-82 of the

abc_map_graph.phpfile in this article's source

directo-ry to understand the database queries and array creation

for the following graphs

Listing 13 shows the code necessary to generate the

pie graph shown in Figure 6

You can expand on the use of background images that

was introduced in the first set of graphs, and add

addi-tional information to your graph Consider a map of the

United States showing the divisions of each region for

the ABC Company If you use this map image as a

back-ground for your graph, you can actually place the pie

charts on each of the regions to make it clear what

region the pie chart represents See the

img/abc-regions.png file in this article's source directory for

the example background image used here

To use this example, you will need to add a couple of

more lines to the $graphData construction loop to

allow for dynamic placement of the pie charts for each

region:

Now let's look at the entire code, shown in Listing 14,

to generate the graph in Figure 7

The company's final request was to be able to drill

down from these pie charts to the regional sales data

graphs you constructed earlier You can implement thisfeature using Client Side Image Maps (CSIM) CSIM is

an HTML technology allowing you to specify regions of

an image to associate with a hyperlink To implementCSIM for this chart, you will need to make the CSIM tar-gets (hyperlinks) and image alts (tips for the user)

First we'll define a constant containing most of thelink to drill down to

Now in the $graphData loop we'll populate the gets and alts:

tar-$graphData [ 'r' $rIndex ][ 'targets' ][] = DRILL_GRAPH $regionData [ $i ][ 'region_id' ];

$graphData [ 'r' $rIndex ][ 'alts' ][] = "Click for more information regarding

{ $regions [ $rIndex ][ 'region' ]} sales." ;

Figure 6: Simple pie chart

$sliceColors = array( 'lightgreen' , 'pink' ,

'lightblue' );

$graph = new PieGraph ( WIDTH , HEIGHT );

$graph -> title -> Set ( $regions [ $region ][ 'region' ]

' Region' );

$graph -> subtitle -> Set ( 'Sales by Channel since '

GRAPH_START );

$p1 = new PiePlot ( $graphData [ $pickRegion ][ 'rev' ]);

$p1 -> SetLegends ( $graphData [ $pickRegion ][ 'label' ]);

Trang 19

FEATURES Advanced Features in JpGraph

Because there is now HTML information (the CSIM)

in addition to the binary image content, you can't

stream it back to the browser like you normally would

The CSIM and the image depend on each other too

much In order to make this work, you need to cache

the image This allows you to output the image map,

as well as the image tag used to fetch the cached

image Instead of using the JpGraph cache outlined

above, we'll use another form of image caching and

store it in a place where we can request it directly To

accomplish this you will need to create a directory

called img immediately below the script directory This

directory must be writeable by the web server

When you are creating the graph, treat it as if you

were going to stream the image In the pie chart loop,

add the CSIM information like so:

To output the graph, use the code in Listing 15

This code instructs JpGraph to output the image to a

file called img/abc_channel_graph.png You then

fetch the image map generated by the graph into the

incorporated into a larger valid HTML document, buthere you can see the coupling between the image mapand the image tag The image tag specified allows the

$p1 -> SetCSIMTargets (

$graphData [ $pickRegion ][ 'targets' ]

$graphData [ $pickRegion ][ 'alts' ]

);

1 $graph = new PieGraph ( WIDTH , HEIGHT );

2 $graph -> SetBackgroundImage ( 'img/abc-regions.png' , BGIMG_FILLFRAME );

3

4 for ( $i = ; $i < $rIndex + ; $i ++) {

5 $pickRegion = 'r' $i ;

6

7 $p1 = new PiePlot ( $graphData [ $pickRegion ][ 'rev' ]);

8 $p1 -> SetCenter ( $graphData [ $pickRegion ][ 'map_x' ],

9 $graphData [ $pickRegion ][ 'map_y' ]);

Trang 20

FEATURES Advanced Features in JpGraphimage to use the generated map.

Key Concepts

The following concepts, related to graphing and

JpGraph, were introduced or emphasized in this case

study:

• the use of the JpGraph Bar, Line and Pie plot

types

• the use of stacked and grouped bar graphs

• the use of an alternative scale on the Y axis

• the use of a callback function to perform

for-matting of labels

• the generation of error messages in an image

• the creation of a "watermark" using a

back-ground image

• the use of the JpGraph image caching - forboth performance, as well as to facilitate use

of the CSIM feature

• the use of a background image as part of thecharts information content (pie chart location

on the sales by region chart)

• the use of CSIM for drill-down capability ongraphs

ConclusionJpGraph is a lightweight API that allows you to quicklygenerate professional looking graphs CouplingJpGraph with PHP's database access capabilities pro-vides you with a powerful toolset for the generation ofdynamic graphs on the web This article has intro-duced you to some of the more advanced features ofJpGraph like caching, background images and ClientSide Image Maps Hopefully you are now familiarenough with these technologies for you to considerusing PHP and JpGraph for your next data mining proj-ect

define ( 'IMG_DIR' , 'img/' );

$graphName = IMG_DIR 'abc_channel_graph.png' ;

$graph = new PieGraph ( WIDTH , HEIGHT );

//the rest of the graph code

$graph -> Stroke ( $graphName );

$mapName = 'ABC_Region_Drill' ;

$imgMap = $graph -> GetHTMLImageMap ( $mapName );

print <<<EOS

$imgMap

<img src="$graphName" alt="ABC Sales by Channel"

ismap usemap="#$mapName" border="0">

EOS;

Listing 15: Code to handle CSIM's.

csim_stroke.php

Jason has been an IT professional for over ten years He is currently an application developer and intranet webmaster for a Fortune 100 compa-

ny He has written several tutorials and articles for the Zend website, and has recently contributed to the Wrox "PHP Graphics" handbook He resides in Iowa with his wife and two children.

Click HERE To Discuss This Article

https://www.phparch.com/discuss/viewforum.php?f=12

Publish your data fast with PHPLens

PHPLens is the fastest rapid application tool you can find for publishing your databases and creating sophisticated web applications Here’s what a satisfied customer, Ajit Dixit of Shreya Life Sciences Private Ltd has to say:

I have written more than 650 programs and have almost covered 70% of MIS, Collaboration, Project Management, Workflow based system just in two months This was only possible due to PHPLens You can develop high

quality programs at the speed of thinking with PHPLens

Visitphplens.comfor more details Free download

Trang 21

It seems like every book I read on PHP has a chapter on

forms Of course, form handling is what server-side

languages are usually employed for, so it is good to see

it get this kind of coverage Unfortunately, most books

only provide slightly more information on form

pro-cessing than you’d find in a good HTML book They

usually only cover how to build a form, what the data

comes through as on the other side, and some

com-mon uses for it

So, while I know what forms are, what they’re for,

and how I can use them, I have yet to read a book (or

article) that answers my age-old question: What’s a

good way to validate forms?

Obviously, ‘good’ is the operative word here, and is

based solely on my opinion To be fair, I have seen

books and articles that talk about form validation They

just don’t talk about it the way I think it needs to be:

atomic I mean that the validation engine should be

fully-encapsulated Validation atomicity comes

part-and-parcel with functional separation You shouldn’t

be doing a check here and then a check there,

inter-spersed in the same script that will be using the data to

perform some operation Form validation needs to be

a separate entity You should know if it succeeds or

fails, and then be free to take the appropriate action

Over the course of this article, I’m going to talk about

the form validation system that I have developed This

system may be a little different than what you’re used

to, but it’s robust, reliable, and very extensible

I will first examine an evil necessity for our purposes:dynamic form generation Following this will be a dis-cussion of the form validation techniques presentedhere After all of this theory, I’ll throw a couple of class-

es at you, and tie it all together with a nice example.This should leave you feeling refreshed and invigorated,and ready to tackle your next form validation project.Let’s go

Dynamic Form Generation

In order to fully encapsulate the process, we will want

to build our form elements dynamically If you follow

phpclasses.org or hotscripts.com, you probably know

that everybody and their dog has created a class tomake form creation ‘easier’ While I’m not personallyconvinced that this is necessarily better or easier by

itself, it will make the rest of our process easier I’ll

dis-cuss, in detail, the reason for this a little later

In recognition of the composite nature of a form, wewill (just like everybody else’s dog) use a set of classesfor this task A number of element classes (Text, Button,

By Peter James

Staff editor and veteran PHP pro Peter James approaches

the age old problem of form validation from a new and

interesting perspective.

PHP Version: PHP 4.3 O/S: Any

Additional Software: N/A

REQUIREMENTS

Trang 22

FEATURES Form Validation From the Outside In

Checkbox, etc) and a main form class should provide all

of the functionality we need

A form usually contains one or more form elements,

and one or more of a number of form tag attributes In

order to provide the most value, the form class needs

to follow a few guidelines, listed below It should

• provide intuitive defaults for the standard form

tag attributes (like method, etc), so that

sim-ple forms are easy to create

• provide an easy way to add extra attributes to

the form tag

• provide a simple way to add form elements to

the form

• be flexible enough to handle new form

ele-ment types transparently

Following the above guidelines will make the class

more robust and durable Let’s look at how the form

element classes fit into the picture

Each form element type can be represented with a

class The interface to the element classes should be

loose and generic Methods

should be provided for

things like setting the value

of the element, getting the

HTML representation of the

element, and adding tag

attributes to the element

Because there will be a

large amount of functionality

that is common across the

different element types, it makes sense to build an

abstract form element class, and have each type of

ele-ment class extend it This will also ensure that it is easy

to add a new element type You just extend the base

class and add to it to meet the needs of the new type

Easy as pie!

Once the form composition is done, the user should

be able to get the HTML representation of the form,

including all elements, for layout Some form classes

provide built-in layout capability In the interests of not

introducing any unnecessary limitations, I won’t deal

with this functionality here

“So,” you ask, “why do we need to dynamically

gen-erate the form to do validation?”

It all comes down to control It’s the same reason

that when you sell your house, your lawyer takes care

of all disbursements What if they gave you all the

money, and you decided that you’d rather live in a nice

tropical country with no extradition agreements? The

lawyer wants to make sure that they get paid, and that

the bank gets paid, and that the realtor gets paid

Likewise, while we technically don’t need to

dynami-cally generate the form, it makes sure that things

oper-ate in a consistent way, and that everything about the

erate the form, we know what type of form elements,

as well as how many, are present We know their ues, attributes, and names We are omniscient aboutthe form, and that is invaluable when we want to vali-date that form

val-Now that we have an idea of how the dynamic formgeneration will work, let’s explore how we’re going tovalidate forms

Form Validation in a NutshellAlthough web applications are state machines, the pro-tocol the web is built on (HTTP) is ironically stateless.Sessions are most commonly used to circumvent thislimitation, and they will play a large role in how we will

go about validating forms

Sessions allow us to maintain state, which means wecan develop our applications in a manner more similar

to client-side (desktop) development Client-side cations start and end with the user When the userstarts MS Word, an environment is created that knows

appli-as much appli-as it needs to about what they are doing Thisenvironment, containing their document, undo levels,

comments, an so on, is alivefor as long as they are work-ing When they are done,the environment isdestroyed

Compare this to a webapplication such as a con-tent management system.Every single time a user per-forms an action, the systemstarts from zero It must recognize who the user is,determine what actions they are allowed to take,understand what action they are trying to take, loadany context necessary, perform the action, store anycontext, output to the user, and exit back to zero This

There are many ways to do most things, and formprocessing is no different Some people, for instance,like to mix the screen and action code This means that

" You shouldn't be doing a check here and then a check there, inter- spersed in the same script that will

be using the data to perform some

operation."

Trang 23

FEATURES Form Validation From the Outside In

process it A short example of this is shown in Listing

1

I have done a lot of this in my career It’s very

effi-cient, and allows you to display errors easily If the

val-idation code runs into a problem, you can abort

pro-cessing of the action code, and just redisplay the form

with the errors This is nice for most forms where there

are required fields If your validation code executes

cleanly and you don’t want to display the form, then

you can take any number of actions (exit, return, or

include another file, etc) This provides lots of options

The bad thing about this is that it promotes the

mix-ing of validation and processmix-ing with content You

might feel that there is a strong coupling between

val-idation code and processing code, but that is similar to

saying that there is a strong coupling between the

application and the presentation layer in a web

applica-tion A strong link between them is undeniable, but

there are big advantages to achieving maximum

sepa-ration

Another common way to process forms is to have

separate action pages and screen pages This means

that the screen resides in one file, and the form’s action

will point to the action page (whereas in the above

example it pointed to itself) This achieves better

sepa-ration, but still mixes the validation and processing An

even better way to process forms is to split it all out,

and have screen pages, validation pages, and action

pages This could quickly become unwieldy, though

All of the above methods suffer from redundancy and

duplication of effort You will no doubt need to do

sim-ilar types of checking on many forms With form

check-ing code all over the place, you may end up writcheck-ing in

the same functionality needlessly Function libraries are

an obvious solution to this

While there is nothing technically wrong with the

above solutions, they all miss the boat in terms of

encapsulation and atomicity No matter how long you

look at them, they are not clean, oiled form-validating

machines I think that perhaps the above methods are

looking at things from the wrong angle They are

look-ing at it on a need-by-need basis “I need a function

that checks this ”, rather than asking “what do I need

to check this form element for?” While we can slice upvalidation functionality along other lines, I believe thatthe best way is to slice it along form element lines

Validating on an element-by-element basis gives us agreat deal of power Attaching form validation ability

to each element means that an element can essentiallyvalidate itself By extension, his means that a form canessentially validate itself

Unfortunately, the reality of validating a form in thisway requires that we know everything about what ele-ments are in the form How can we do this on thereceiving side without any of the above methods? Wereally can’t Sure, we can check for what variablescame through, but we’d have to set up some expectantcode on the receiving side, and that really wouldn’t beany different than the above methods

It seems that we’ve come full circle The reason that

we need the dynamic form generation might now bemaking itself clear We build the form using our formobject, specifying how to validate each form elementwhen we create it Now we’ve got all of the informa-tion about the form, as well as how to validate it, in oneobject Unfortunately, this object is only available when

we make the form, not when we validate it

The need for the session now becomes obvious Inorder to validate the form, we need the form validationcode on the receiving side of the request Rememberthat we set up the form validation code on the initiat-ing side of the request, when the form was created Bystoring the validation configuration (the form object) inthe session, we are able to validate the form on thereceiving side atomically

In the end, this method might look a little

complicat-ed It really isn’t, especially considering the complexitysavings we’ll experience when we use it Not surpris-ingly, doing form validation this way satisfies the atom-icity and logical separation requirements that werespecified earlier It also means that when a formchanges, the validation changes are made in the samespot, reducing the risk of introducing subtle bugs andinconsistency

Specifying Form ValidationEarlier, we set up a bunch of requirements for formgeneration Now let’s look at some requirements forform validation

Specifying form element constraints should be easywhen it’s simple, and possible when it’s not If it’s asimple check, it should be easy to specify If it’s a com-plex check, like a multi-step dependency check, itshould still be possible to do This simply is not a use-ful solution if we can’t extend it to handle the specialcases

Constraint specification (what makes a form elementvalid) should be consistent, too One form elementtype shouldn’t implement a common check differently

1 <?php

2

3 // start action code

4 if (isset( $_REQUEST [ 'foo' ]))

13 <form action=" <?php print $_SERVER [ 'PHP_SELF' ];

14 <input type="text" name="foo" value="" />

15 </form>

Listing 1

Trang 24

FEATURES Form Validation From the Outside In

than another The constraint specification interface to

a text box should be intuitively similar to a text area,

since they are similar in function

Because we are looking for atomicity, there must be

an easy way to see if a form is valid or not By

exten-sion, this is also a form element requirement

I think that we’ve talked enough talk, and we should

get busy on walking the walk Let’s get to some code

The Classes

The first class we’ll develop is the main form class It is

listed in Listing 2 (provided in this month’s code

pack-age)

Let’s examine the code listing in Listing 2, and talk

about the method (pardon the pun) to our madness

The constructor, Form(), simply takes an identifier as

an argument The identifier is the value of a form

vari-able that will identify the form Basically this translates

into a hidden field in the form with a name of “_form”

It’s really helpful when you have multiple forms on a

page It is used to identify the particular form object in

the session, so you know which form object to validate

with This should become clear a little later

the form The $element variable is an object derived

from the abstract form element class

name attribute for the form The name of the form

defaults to ‘form1’ The form name is really only useful

for client-side scripting, such as JavaScript, and can

usu-ally be ignored

method used to transfer the data to the server, and

defaults to ‘get’ This is generally either ‘get’ or ‘post’

associated with the form It defaults to

current page This is a common action, especially if you

are using a central controller script that delegates by

inclusion

window or frame of the form This is the window or

frame that will display the results of the submission It

defaults to ‘_self

form tag attributes It accepts an attribute name and

an attribute value, which will be entered into the tag as

name=”value” You can add as many extra attributes

as you need As an example, you might add an “

enc-type” attribute with a value of “

multipart/form-data” if you were creating a file upload form

checks as to whether the form that was created by this

object was actually the one submitted on the last

request This is what the form’s identifier (from the

constructor, above) is used for If

then the form was submitted This function is used onthe receiving side of the form submission

our atomicity This function checks first if the form wasactually submitted (using the above function) and, if

so, loops through each element in the form to mine if the form itself is valid If any of the form ele-ments are not valid according to their own definitions,the form is not valid This function is also used on thereceiving side of the form submission

HTML representation of the form’s tag, including all ofthe specified attributes

gets the HTML representation of the hidden field thatcontains the identifier variable passed into the con-structor

gets an array of the HTMLrepresentations of the formand all of its elements It firstgets the form tag and theidentifier tag, then it loopsthrough all of the elements inthe order in which they wereadded Finally it adds theclosing form tag to the array

This array is indexed by ment name for layout pur-poses

function returns an array of messages produced by theform validation

the form object to access a form element’s value Thisfunction is generally used on the receiving side of theform submission

As you can see, this is a simple but powerful class forform creation and validation Now let’s see some of itspartners in crime: the form element classes

The abstract form element class is shown in Listing 3(provided in this month’s code package)

It’s not meant to be instantiated and implements a lot

of the element functionality Let’s walk through it

The class constructor, FormElement(), is used toset the properties common to all elements: type andname

to the function by the same name in the form class Itjust allows us to add extra attributes to the form ele-ment tag

said earlier that we were going to avoid any layoutcapabilities in the classes, but this looks suspiciously like

a layout capability Actually, this is mainly for the radiobutton elements Since radio buttons are really a num-

"A strong link between (validation code and content)

is undeniable, but there are big advantages to achieving maxi- mum separation."

Trang 25

FEATURES Form Validation From the Outside In

allows you to layout the radio buttons If you’re

adven-turous, you could use this to provide limited layout

capabilities for other element types A sample layout for

radio buttons forming a boolean entry are shown

below This simply augments the HTML being

generat-ed for a set of radio buttons It takes a standard

printf() format

provided by set_format() to the element’s HTML

representation Any class, like the radio button element

class, that has special formatting

requirements would override this

function

func-tion specifies whether the form should

look for a $_REQUEST variable with

the same name as the element, and

use this as the element’s value when

displaying it This is handy when

redisplaying a form after an invalid

submission The default is to use the

will display the invalid values back to

the user automatically, which is nice

Any call to the set_value() function (described

below) will override this setting and use the value

pro-vided to it

pro-vides these classes with their immense extensibility It

allows the user to specify either an element-specific

check such as ‘regex’ (for textboxes) or ‘selected’ (for

dropdowns), or an external function An external

func-tion receives the validating element’s type, name and

value It returns true or false based on if the value was

found to be acceptable or not You can add as many

checking methods as you want This function accepts

an optional fourth parameter that is useful when

speci-fying an external checking function This parameter

allows you to specify the external file containing the

checking function (in case it’s not normally loaded)

The private _run_check_function() function is

used internally to actually implement the call to the

specified checking function(s) This function returns

true or false based on whether the check came back

successful or not

set-ting of element values You might use this with the

radio button form element to specify a default

selec-tion If no value is specified to this function, any

avail-able $_REQUEST value will be used if allowed by

abstract method It is meant to be implemented insubclasses, and should return the HTML representationspecific to the element In most cases this will just

return one HTML tag (an <input> tag) For radio

buttons, select boxes, and text areas, however, itreturns a set of HTML tags with some text

self-valida-tion It is called by the form class when the form isasked if it’s valid This function runs through all of thechecking methods that were specified for the element(if any) If a checking method returns false, which

means the value was not acceptable,

this element, and returns false to thecalling class (the form class)

The final function in this class,

method This is the function that

and must be implemented in the class according to the particular ele-ment type’s special checking require-ments A select box form element, forexample, exposes three checkingtypes: ‘selected’, ‘func’ and ‘’ The firsttype checks whether a selection was made from the thebox (applies when the default selection is not a validselection – like ‘select one’) The second type is present

sub-$e -> set_format ( ‘True % s & nbsp ; False % s’ );

7 // allows checking types:

8 // * 'regex' - pattern matching

9 // * 'func' - user-defined function

15 // call parent constructor

16 $this -> FormElement ( 'text' , $name );

Trang 26

FEATURES Form Validation From the Outside In

in all elements, and is the external checking

function method The third type specifies no

checking method (we don’t care what the

value is)

As you can see, the base class takes care of

most of the form elements’ dirty work Our

element classes only have to implement a

minimal set of specific behavior For example,

in the text box element class, shown in Listing

4, only four methods have been defined or

overridden (and one of them is the

construc-tor!) Have a look at the class in Listing 4, and

then I’ll run through it

constructor, and in this class its function is

simply to call the parent class constructor In

other classes, such as the radio button class or

the select box class, it also sets up all of the

selection options

imple-ments the text box element’s built-in regular

expression checking This is the function that

is called when you specify the check method

to be ‘regex’ Other elements will have

func-tions specific to their operation In the select

box element class, there is an

built-in ‘selected’ check method

implementation of an abstract method from

the base form element class It simply returns

the HTML representation of the element

Assuming that the format has not been

mod-ified, this will return the ‘input’ tag for the

text box Other elements, such as the radio

button element, may return a number of tags in a

for-matted string

The final function, check(), is also a required

imple-mentation of an abstract method It implements thevalue-checking capabilities of the element This gener-ally includes at least one element-specific check such as

‘regex’ or ‘selected’ (specific to dropdowns), tioned earlier

men-In the interests of variety, and so that we can provide

a useful example later, lets look at another form ment subclass The class for the submit button is listed

ele-in Listele-ing 5

As you can see, there’s very little difference in theinterface to the subclass, which makes sense

and, like the FormTextbox() constructor, it calls theparent constructor The submit button class has anextra variable, $desc, that holds the button title This

is also set in the constructor

implementation from the base class It simply returnsthe HTML representation of the element

implemen-tation from the base class It simply directs the calls to

28

29 // render the element and return it

30 function get_element ()

31 {

32 $element = "<input type=\"text\" "

33 "name= \"{ $this -> name }\" "

34 "value= \"{ $this -> value }\" " ;

35

36 // add extra attributes

37 foreach ( $this -> attributes as $attribute => $value )

16 // call parent constructor

17 $this -> FormElement ( 'submit' , $name );

18 $this -> desc = $desc ;

19 }

20

Listing 5

Trang 27

FEATURES Form Validation From the Outside In

The submit button form element is a great deal

simpler than any other element Mainly, this is

because it doesn’t implement any checking

capabilities With very little effort, checking

capabilities could be added to the submit

but-ton, although they probably have little use

So that’s it! Now we need an example to tie it

all together Since I only introduced the text box

form element and the submit button form

ele-ment, we’ll keep it simple That said, it should

still serve to demonstrate how powerful this

solu-tion is

An Example

Our example will be a very simple form

contain-ing a scontain-ingle text box and submit button The

value of this text box upon submission must be

numeric and even Let’s take a look at the code,

shown in Listing 6

We start out by simply including the Form.php

class file It takes care of all other dependencies

for us, so we don’t have to load any elements

Next, we start the session This is critical because

the form creation and validation code won’t

work without it Remember, the form object is

stored in the session for use on the next page

Next we check if the form was submitted on

the previous page If it was, we check if it’s valid

If the form checks out, we display a message,

‘form was valid’, to the user and exit

If the form was not valid, we display the error

mes-sages On a real form, these might be requiring the

user to enter an email address, or a postal code Next

we get into the actual form specification Considering

what we’re doing, the form specification is a fairly

non-intrusive process

We put two constraints on the text box element

One is a regular expression that requires a number The

other is a custom function that checks that the number

entered is even They have their own error messages sothat you can play around and see which constraint istaking effect Notice how simple it is to extend the val-idation with user-defined functions

The last step in the form generation is to output theform You can see how this form class lets you retaintotal control over the layout process The form isreturned in an array from the get_form() call

Although all elements are accessed by their names,there are two special indices: ‘form_start’ and

‘form_end’ These contain the form start tag and tifier hidden field, and the form end tag, respectively

iden-At the bottom of the file the custom checking tion is implemented We’re done! Play with this exam-ple a bit, and think about the flexibility it offers Forexample, by using a user-defined function, we can per-form form validation with information from a database,socket, or other external resource The possibilities real-

func-ly are limitless

As an example of how this form class could be usedfor other tasks, think about authentication Rather thanvalidating the form elements against ‘regular’ criterialike patterns, we could validate against the database,and check login information

Further Extension andImprovement

The form class, as it stands, is very useful and very

21 // render the element and return it

22 function get_element ()

23 {

24 $element = "<input type=\"submit\" "

25 "name= \"{ $this -> name }\" "

26 "value= \"{ $this -> desc }\" " ;

27

28 // add extra attributes

29 foreach ( $this -> attributes as $attribute => $value )

Listing 5: Continued from Page 26

dynamic web pages - german php.node

news scripts tutorials downloads books installation hints

D y namic Web Pages

www.dynamicwebpages.de

sex could not be better |

Trang 28

FEATURES Form Validation From the Outside In

extensible As always, however, there’s a ton of room

for improvement and further abstraction

Each element contains only one or two specialized

checking methods (regex or selection, for example)

Adding more specialized text-checking methods like

‘email’, ‘phone’, and so on, would add lots of value,

and would cut down on the number of custom

func-tions that are required

Some current limitations of the class are a lack of

error checking There is lots of opportunity for

incor-rect input here Checking that user-defined callback

functions actually look like functions, and that they

exist, for instance, would be a good idea All of the

input to the classes should be checked for correctness

ConclusionAlthough the technique is a little unconventional, thisform validation solution performs well It excels inextensibility, atomicity and separation It provides aconsistent interface to the developer, and allows forfuture expansion of the types of form elements andattributes

In short, it provides a lot and assumes very little

Peter James is a developer and team lead working in Edmonton, Alberta.

In his spare time he tries to magically juggle his family, freelance work, tool development and learning You can reach Peter at

7 // check the forms validity

8 if (isset( $_REQUEST [ '_form' ]))

23 // set up the form and validation tests

24 $f = &new Form ( 'foo' );

25 $tb = &new FormTextbox ( 'foo_textbox' );

26 $tb -> add_check_method ( 'regex' , 'Invalid entry by regex' , '/^\d+$/' );

27 $tb -> add_check_method ( 'func' , 'Invalid entry by func' , 'foo_textbox_check' );

28 $sb = &new FormSubmit ( 'foo_submit' );

41 // special checking function (checks if the value is an even number)

42 function foo_textbox_check ( $type , $name , $value )

Trang 29

PHP is an Open Source

scripting language with serious

technical muscle No wonder it’s the

language of choice for Yahoo, Inc and

over 8 million domains worldwide Whether

you’re a PHP pro or completely new to the language,

PHPCon East 2003 will take you to the next level

Meet and mingle with the experts during two conference days

PHPCon East 2003 Speakers include:

• Rasmus Lerdorf, Opening Keynote Speaker and Inventor of PHP

• Zeev Suraski, Closing Keynote Speaker, CTO of Zend

• Zak Greant, MySQL.com

• Shane Caraveo, ActiveState, Inc

• Luke Welling and Laura Thompson, Tangent Technologies

• George Schlossnagle, OmniTI

Technical learning at all levels

PHPCon has a full day of hands-on, technical

tutorials that offer something for everyone, including:

CHECK OUT THE PROGRAM

& REGISTER TODAY! http://www.php-con.com/pa

PHPCon East 2003 Park Central New York Hotel New York City, New YorkApril 23 - 25, 2003

Live PHP!

Use PHP?

Love PHP?

(for three days)

Trang 30

We all come to open source software from different

tracks and for different reasons Because you are

reading this, you are at least somewhat interested in

open source and may even be an open source

advo-cate Your interest in open source web application

development has led you to PHP (I believe I can safely

assume this because you are, after all, reading a

maga-zine focused on PHP!) For myself, incorporating and

utilizing PHP (and open source software in general) into

my arsenal of tools was an evolutionary process It

start-ed slow, building steam to where I am now: a full

blown open source/PHP advocate

Of Zines and other things DIY

I was seriously involved in the underground zine

pub-lishing community for many years A zine (pronounced

“zeen”) is defined as a small publication typically

cov-ering non-mainstream topics published by an

individ-ual or a small group for the sole purposes of expression

and communication Zines are part of the much larger

DIY community The DIY (Do-It-Yourself) community is

comprised of independent musicians, record

compa-nies, distributors, zine publishers, artists, designers,

small business, writers, publishers, and crafts people

When I started dabbling in web development I found

that there was almost no representation on the web for

this extremely dynamic community I got down to

to catalog DIY projects on the web DIY’ers could entertheir URL on their own, and make it available to otherDIY’ers Diysearch was a place where DIY’ers could findother projects like their own, or look for resources fortheir projects

When I started working on Diysearch, I found outrather quickly that just plain HTML pages just weren’tgoing to cut it with respect to what I wanted to do Iwanted interaction and user participation, and had NOclue what made this possible That’s when I stumbledacross a few free Perl CGI scripts (a guestbook and alinks database/search engine script) I started playingaround with them and, even though I didn’t reallyknow what I was doing, it was fun Just getting thethings to work provided me with an incredible oppor-tunity to learn something Diysearch was born

So as it turned out, I came to the open source campquite by accident As a hapless newbie “hacker” dab-bling in Perl CGI in 1994, I was almost completelyunaware that there was an actual name for this com-munity movement

After many years, Diysearch strayed away from open

Freedom

By Dave Palmer

Veteran web application developer Dave Palmer shows you how to create killer

sites without being killed by things like vendor lock-in, software licenses and

expensive, yet inflexible and incomplete software tools

PHP Version: 4.3 or Above O/S: Any

Additional Software: N/A

REQUIREMENTS

Trang 31

FEATURES Porting and Migrating and the Move to PHP

source and into the realm of propriety via ColdFusion

It suited me just fine The site worked, the user base

continued to grow, and I added patches here and there

as needed A few more years went by Finally, a few

months ago, I had an epiphany: Diysearch was a total

wreck The software I wrote was showing its age in a

big way (it was last updated in 1998!) Users were

growing frustrated over the lack of new functionality, as

well as the inability to manage the links they submitted

It finally occurred to me that it was time to re-engineer

the site

Over the years I had become more and more

involved in the open source community, mostly just by

adopting a lot of open source technology and making

minor contributions here and there I decided it was

now time to make a real commitment to open source

with something I had a vested interest in: my silly little

side project

I knew there was no way I would re-engineer the site

using ColdFusion Having worked with ColdFusion

since the “version 1.5” days, I am intimately aware of

all of its shortcomings and faults Because of this, I

decided that PHP would be my web application

plat-form of choice for this porting and migration project

I had come to PHP several years earlier when

explor-ing other options outside of CGI scriptexplor-ing (back when

PHP was still called Personal Home Page) I liked it

because it looked like Perl and worked like ColdFusion,

but I never gave it much thought I worked a little bit

with PHP here and there over the intervening years, but

it wasn’t until about a year ago that I saw it’s potential

I developed a commercial e-commerce site for a

com-pany in Atlanta using nothing but PHP (on Linux with

MySQL), and finally realized that this PHP stuff was for

real It became clear to me that PHP (pardon the

intro-duction of controversy) was technically (and in my

mind politically) superior to ColdFusion

With this minor revelation in hand, I set out to

con-vert Diysearch from a collection of ColdFusion hacks

into a unified and homogenous PHP-based web

appli-cation Having a revelation is one thing, but turning

that revelation into reality is something else entirely

The idea of writing a content management system

from scratch (which I had done before on many

occa-sions, but in a proprietary fashion) with user

manage-ment, link database managemanage-ment, and a sophisticated

search engine was just something I was not really into

doing

Enter PHPNuke

After several fits and starts and not really getting

any-where, something occurred to me The problem I was

trying to solve had already been solved in a whole slew

of different ways, many of which could be found in the

open source universe After some deliberation, I settled

on using PHPNuke (http://www.phpnuke.org)

For those that are not aware, PHPNuke or “Nuke”

-is an open source content management and portalmanagement system written in PHP Nuke implements

a modular design where all major pieces of

functionali-ty are set up as a group of modules Each moduleresides in a designated directory where the Nuke “ker-nel” can be made aware of the module Each moduleincludes a few lines of code to comply with the Nukemodule standard, but from there on out is writtenspecifically for whatever functionality the module isdesigned

This design, coupled with its “theme-based” and-feel implementation, made it quite suitable forwhat I needed to do Diysearch is a community-orient-

look-ed site with a strong concentration on user interaction.While Nuke was quite strong “out-of-the-box”, it was inneed of some changes for what I needed to do.Diysearch had specialized requirements that the Nukedevelopment team could not have anticipated Theseincluded:

•An upgraded search engine

•The ability for users to add, edit or delete linksthey “own”

•A “review” process for links submitted by users(to eliminate violations to the acceptableusage policy)

•A customized banner management and tion application (to enable real-time bannerpackage purchasing integrating with PayPal’sIPN system)

rota-•A volunteer mechanism to enable interestedusers to volunteer time in the managementand upkeep of the site

Working with modules in PHPNukeAdding new functionality to an existing framework orapplication typically ranges from being a difficult task(at best) to being nearly impossible (at worst) Because

of Nuke’s thoughtful design, adding new functionality

is a clear and straightforward process requiring a fewsteps These steps are a mixture of writing new code(your functionality) and modifying certain pieces ofNuke code

Actual functionality is often encapsulated in what isreferred to as a “module.” A module lives in a specifi-cally named directory under the main “modules” subdirectory and contains one or more PHP scripts Eachmodule contains an index.php script that includes aswitch statement for traffic control, and function defini-tions for carrying out the specific tasks See Listing 2 for

an example module’s index.php script, which shows

specifically what a module might look like This ule, called “Volunteers”, is responsible for enabling

Trang 32

mod-FEATURES Porting and Migrating and the Move to PHP

users to sign up as a volunteer It’s a very simple

exam-ple, but clearly illustrates what modules consist of and

how they fit in the Nuke infrastructure

Taking a look at the anatomy of this (or any other)

module, you will notice the following at the top of the

index.phpscript:

This bit of logic implements some very basic security

so that malicious users cannot try to access the module

file directly; all requests must come through the main

‘modules.php’ script (in the root directory)

After this initial security check, you will notice several

function definitions which are responsible for carrying

out the specific tasks the module is responsible for In

keeping with the self referencing pattern used

through-out Nuke, the module’s source code ends with a switch

statement that controls the process flow

Some other interesting things to note are several

Nuke global variables and functions that come in rather

handy when developing modules

First, in the entry() function you’ll notice calls to

con-venience methods defined as part of the theme

archi-tecture, and are used for printing HTML table tags

These functions are available to all modules, which

makes creating a consistent look-and-feel across all

modules a simple task

Next, in the add_volunteer() function, you’ll

notice $dbi This global variable holds a reference to

the database connection used within Nuke This means

that you are not responsible for setting up database

connections within your module All of that work has

been taken care of for you Simply do a global $dbi;

in your function and use the database abstraction layer

included with Nuke This allows you to query the

data-base with very little coding overhead

The PHPNuke “kernel” automatically notices any

modules in the modules/ directory An illustration of

the file system for modules follows

If you create a new directory under “modules”, and

access the “Modules” option in PHPNuke’s

administra-tion secadministra-tion, you will see the newly created module

list-ed there (namlist-ed using your directory name) Modules

are initially marked as “inactive”, and can remain

inac-tive while testing occurs Nuke will provide navigation

into your module under the “Inactive modules” header

Enhancing the search engine module

The first thing I needed to do was upgrade the searchcapabilities Diysearch is, first and foremost, a searchengine organized like Yahoo It uses a hierarchy of cat-egories, into which links are logically filed The searchengine component is responsible for querying a linkdatabase (where all of the user-submitted links live) andreturning a ranked result set to the user

Nuke has a “Web links” module, but its functionality

if (! eregi ( "modules.php" , $PHP_SELF )) {

die ( "You can't access this file directly" );

}

1 <?php

2

3 /*

4 * This is a snipit of the Volunteers module

5 * developed to satisfy a specific requirement

6 * for Diysearch that was not covered by

7 * PHPNuke's core set of modules

8 */

9

10 // This is typically the first line in most

11 // modules for security reasons

12 if (! eregi ( "modules.php" , $PHP_SELF )) {

13 die ( "You can't access this file directly" );

14 }

15

16 // this is essentially the Nuke "kernel" and

17 // defines global variables and establishes

18 // the environment in which Nuke runs

42 * Our main operation switch statement which

43 * determins which function to call

Trang 33

FEATURES Porting and Migrating and the Move to PHP

of Diysearch’s link database The first thing I did was

implement Lucene Lucene is a Java -based indexing

and search engine API provided by the Apache

Foundation as part of the Jakarta project Lucene

pro-vides a very elegant and powerful indexing and

search/query engine that rivals commercial products,

like Verity (http://www.verity.com)

I had been using Verity as the primary indexing and

search engine for Diysearch for years (as Verity is

distrib-uted with ColdFusion) Verity has some nice features

such as the ability to run query results and the provision

of a flexible query language, enabling complex

key-word searches Lucene, to my

delight, not only has similar features

but is also much simpler in design in

that it is simply an API The

imple-mentation of indexing and querying

is left to the developer While on the

surface this may seem like a Bad

Thing, it actually isn’t because the

developer is not constrained in how

the indexing or search engines are

implemented

Overall, the implementation of the

indexing and searching engines into

Lucene was pretty simple (my next

article will focus on the details of

using Lucene in a PHP application)

It did, however, take a few steps to

integrate this feature into PHPNuke

In the February issue of PHP Architect

I showed daring readers how to

inte-grate EJB’s (Enterprise Java Beans)

with PHP applications The

tech-nique involved using PHP’s Javaclass as an “interface”

between PHP and the actual Java object Following this

model, the code below shows how we talk to our

Java-based search engine class

In the first line I instantiate a Java object of the

“org.diysearch.searchengine.Searcher” type (which

implements the Lucene API) We can then perform a

search by calling the object’s “search” method This

method is passed the specific index we wish to search,

the type of search (for our purposes we just default to

a “OR” type of search, meaning keywords are joined by

“OR”), and our query (composed of one or more

key-words)

The search engine class, when queried, returns a

WDDX packet containing the search results WDDX is a

type of XML that describes simple or complex data

types so that those data types can be used by disparateprogramming languages Integrating the upgradedsearch functionality into Nuke was done using XML-RPC, and is just a matter of adding some code to the

“Search” module (see Listing 1)

Link databaseAnother of the key functions I needed to implementinto Nuke was the ability to enable registered users toadd URL’s for their projects into the search engine The

“Web Links” module that comes bundled with Nukewas insufficient for this purpose, so I created a new

module (following the procedure described above).This time, though, I also needed to modify some ofNuke’s administrative code so that site administratorscould review submitted links before they became

“active” in the search engine It’s crucial to have areview process when providing this sort of functionali-

ty to a very “diverse” group of users The integrity ofthe site must always be upheld

The old site just allowed anyone to submit anythingand then required me to review entries in the databaseone-by-one, deleting offending links by hand Therejust wasn’t a simple and easy way to add new function-ality in order to make management manageable Inorder to implement this “link queue” and “link brows-ing” functionality into Nuke, I simply added a new cus-tom module to Nuke

DIY banner rotationRunning a Web site isn’t cheap Ask anyone who does,and they will probably say the same thing Sites thathave specific technical requirements often rule outgoing with low-cost, shared hosting providers In order

$obj = new Java

( “org diysearch searchengine Searcher” );

$result = $obj -> search ( $index , $search_type ,

$query );

1 <?php

2

3 /*

4 * This code implements the searching of a Lucene index

5 * Using the XML-RPC bundled with PHP 4.3.0, we connect

6 * to the XML-RPC Web server (which is part of Apache's

7 * Web Services project: http://ws.apache.org)

8 *

9 * We establish a connection to the Web Service, and provide

10 * the name of the index, the query and the search type

11 * and are returned with a WDDX packet that we stuff into a

20 $args = array( $SearchIndex , "OR" , $q );

21 $request = compact ( 'host' , 'port' , 'uri' , 'method' , 'args' );

22 $result = xu_rpc_http_concise ( $request );

23 $sess_qrows = $result ;

24 ?>

Listing 1: Integrating the search engine with PHPNuke

Trang 34

FEATURES Porting and Migrating and the Move to PHP

to offset some of those costs, banner rotation is

need-ed

While Nuke is bundled with a banner rotation

mod-ule, Diysearch had a specific need with respect to how

banners would be handled and uploaded into the site

The nature of the site is “do it yourself” This is a

recur-ring theme in that the direction and control of the site,

and its content, is in the control of the end user

Instead of a prospective sponsor contacting us, working

out payment, and then emailing us a banner, we’ve

automated the process

The solution enables anyone who wanted to

pur-chase banner ad space to simply follow a wizard This

wizard would allow them to select an impression

pack-age and upload their banner to the server Payment

(fulfillment) is done through PayPal, using their “single

item purchase” feature Once the customer completes

the payment process (after uploading their banner),

PayPal’s IPN (Instant Payment Notification) system

takes over

The IPN system accesses a URL in our site and passes

authentication and verification data, along with a

trans-action ID The URL is a simple PHP script which accepts

this input from PayPal and verifies the transaction If

verification is successful, the banner ad table is

updat-ed This marks the particular banner ad with a status

identifier, and places the banner in rotation This fully

automated system of handling banner management

and rotation opens up greater opportunities for users to

take part in sponsoring the site

Look and feel

Perhaps the most challenging task in this porting

proj-ect was implementing the new look-and-feel into Nuke

In the old site there was a custom look-and-feel

infra-structure which, while being rather simple (and old),

was quite effective and clean It was implemented as a

simple inclusion of header and footer files for each

ColdFusion template Nuke has something somewhat

similar but, in this writer’s opinion, it’s a bit convoluted

and messy

Nuke uses a “theme” system where the look-and-feel

elements are contained in HTML fragments These

fragments reside in named theme directories (under

the “themes” sub-directory) While on the surface this

may seem simple, it can quickly become rather

com-plex If you’re experienced in PHP, and you familiarize

yourself with Nuke’s design, adding functionality or

modifying existing functionality is often trivial

Creating a new theme or customizing an existing one,

however, is downright frustrating (for me anyway)

I used the PHPNuke “News” theme as a starting

point, and began to make changes to the HTML

“head-ers” and “content” area templates After battling with

HTML irregularities, and figuring out where and how

certain HTML templates were included (or in some

With no shortage of wrangling and gnashing of teeth(namely my own), the theme for the site was complet-

ed A significant amount of trial and error wasrequired, as well as modifications to the master themescript (all themes in Nuke have a theme.php scriptwhich includes required function definitions the kerneluses in order to “paint” the screen)

Wrapping upAfter starting this project in mid-January of this year,the new and vastly-improved site was re-launched onFebruary 15th (during the worst snowstorm inMaryland’s history) While fine-tuning, additions andbug fixes are always on-going, it is because of PHP’sand, more specifically, Nuke’s well-proven design andflexibility that I was able to completely scrap the oldsite

None of this would have been possible if it wasn’t foropen source software Open source’s natural evolutionand adoption, as well as the contributions of thousands

of gifted and dedicated developers and writers, has ated a rich environment for all Small-scale sites all theway up to large enterprises are able to take advantage

cre-of the work done by these folks, and are able to returnthe favor Open source projects are providing business-

es and organizations the tools they need to competeand stay current Businesses based on these technolo-gies are able to expand and grow in an almost organicway, losing the constraints associated with closed/pro-prietary solutions For these organizations, gone arethe days of hoping that a particular bug will be fixed inthe next release, or that a feature enhancement requestwill actually be entertained

Migrating from ColdFusion to PHP was a much pler task than I had originally thought When youremove the “write from scratch” from the re-engineer-ing equation, and replace it with “don’t re-invent thewheel”, the job just gets that much easier If this migra-tion case study has illustrated anything, it’s that nomatter how old and antiquated (dare I say “legacy”) aparticular Web application may be, PHP and one of thefew thousand PHP-based open source projects is able toprovide a real working solution

Dave is a professional geek specializing in java/j2ee, php (naturally), and perl development which is just a cover for his real passion for spend- ing large sums of money on home recording and musical equipment and generally making anuisance of himself it should also be noted that his / karma is currently "positive" which will surely fall.

Click HERE To Discuss This Article

Trang 35

Being relatively new to the game, the first database

that I had any real contact with was Microsoft

Access 97 Back in those “dark days” I was playing

around with ASP using Windows 98 SE’s Personal Web

Server Ohhh, the stuff I dreamed of creating

Even though I’ve pretty much exclusively used

PostgreSQL and PHP since then, I’ve always missed

Access’s user-friendliness I remember the day I was

(rather rudely and abruptly) introduced to psql (the

PostgreSQL command-line utility) I sat there looking

at it sort of blankly, thinking that maybe if I ignored it,

it would go away I didn’t know what to type, or what

I was typing into

I’ve since come to terms with the psql and mysql

shells, learning to love them (in their own ways)

Sometimes, though, I wish I could go back to a kinder,

gentler time A time where the mouse was king, and I

could make mass changes with a single click The

hard-core Unix hackers out there are probably ready to move

on to the next article now, shaking their heads in

disap-proval Wait, though After reading this, you may just

push away your keyboard for a moment (when

nobody’s looking, of course)

Why on Earth would I want a

graphical database tool?

Hey, that’s a reasonable question I’ve used virtually

nothing but psql to talk to PostgreSQL for the last two

Windows and PostgreSQL

MySQL Manager 2.0 from Electronic

Ngày đăng: 11/12/2013, 02:15

TỪ KHÓA LIÊN QUAN

w