PHPReports README
written by TaQ (eustaquiorangel@yahoo.com)
February 2003
Topics
1 - What is PHPReports ?
2 - What I need to use it ?
3 - Does I need to pay you to use it ?
4 - Tell me how it works.
4.1 - Report structure
5 - A simple example
5.1 - Report layout
5.2 - PHP code
5.3 - XML layout file
6 - DTD file
6.1 - REPORT element
6.2 - COL element
6.3 - ROW element
6.4 - HEADER element
6.5 - FOOTER element
6.6 - PAGE element
6.7 - FIELD element
6.8 - GROUP element
6.9 - GROUPS element
6.10- LINK element
6.11- XHTML element
7 - Validating your document
8 - File list
9 - Final considerations
10 - Changelog
11 - Index of the most common PHP functions in the PHPReports classes
12 - FAQ
1 - What is PHPReports ?
PHPReports is a set of PHP classes, XML instructions and a XSLT
script to transform the XML file into PHP code. The generated
PHP code will be used with the PHP classes.
I started the idea when I needed to make all the stuff we use
on programs like Visual Basic and Foxpro on the browser, and
one of the things that I didn't found was how to make and print
reports, using a SQL query, on a easy (not so easy but) way,
using the browser. Nowadays it runs fine here where I work, and
I hope it could be usefull for you guys too.
2 - What I need to use it ?
You need a Apache server with PHP support compiled with XML/XSLT
support. I use the Sablotron libs to make this
(http://www.gingerall.com/charlie/ga/xml/p_sab.xml), and all the
examples will be based on it.
3 - Does I need to pay you to use it ?
Hell, no. It's under the GPL, you don't need to pay. Just follow
the GPL rules and everybody will be happy. I really was needing
some way to contribute to the open source community, and I hope
it was just the beginning. If you really loved PHPReports and
want to make some kind of donation or stuff, you can see my
Amazon wish list at http://www.amazon.com. Just search for
Eustáquio Rangel there. :-)
4 - Tell me how it works
I heard one day a very smart teacher says that "the purpose of
a good documentation is that you don't need the author fixed
on it, on your bookshelf". I'll try to do the best I can to make
it come true, so here we go.
A report, on PHPReports or any other program that deal with that,
have always some divisions. I call it:
- the document layer
- the page layer
- the group layer
You just have one document layer, one page layer (you can have
a lot of pages, but just one page layer to configure) and some
group layers.
All these layers collect information about the data on your
report, like the number of lines, statistics about the fields
and so on.
The document layer stores ALL these statistics, and stores it
till the report end.
The page layer stores it till the page end, and reset it there.
The group layer stores it till the end of group, let me
translate here group as a set of data defined by a break
expression, which could be any kind of field contained on your
data set.
Each layer have its own header and footer. The group layer have
one more division where it shows the data info. If you have more
than one group ( even when you have just a simple report, you
need to add one group to deal with your info ), the most internal
group will show you the data, the other one can show it too, but
its your choice. Let me try to draw the full thing here:
4.1 - Report structure
+----------------------------------+
| DOCUMENT_LAYER |
+----------------------------------+
| HEADER |
| |
| +------------------------------+ |
| | PAGE_LAYER | |
| +------------------------------+ |
| | HEADER | |
| | | |
| | +--------------------------+ | |
| | | GROUP LAYER | | |
| | | break expression A | | |
| | +--------------------------+ | |
| | | HEADER | | |
| | | FIELDS | | |
| | | | | |
| | | +----------------------+ | | |
| | | | GROUP LAYER | | | |
| | | | break expression A,B | | | |
| | | +----------------------+ | | |
| | | | HEADER | | | |
| | | | FIELDS | | | |
| | | | FOOTER | | | |
| | | +----------------------+ | | |
| | | FOOTER | | |
| | | | | |
| | +--------------------------+ | |
| | | |
| | FOOTER | |
| +------------------------------+ |
| |
| FOOTER |
+----------------------------------+
So, document contains page, page contains groups, and a group can contain another group.
One rule on that case is that the break expression of the inner group must contain the
break expression of the group above. On the example, the first group break when A
changes, and the second group breaks when A or B changes. When this happens, its fired
an event that notify that the group needs to print its footer and header, and all the
other groups related to it are notified too, to make what needs to be done.
5 - A simple example
Ok, lets suppose you have the following table on your database (its not a good table
design, but its just for the example):
SalesLog
ID NUMBER 5
NAME CHAR 50
CITY CHAR 50
PRODUCT CHAR 50
VALUE NUMBER 15,5
If you do this query:
select * from SalesLog order by ID
you get:
1 - Eustaquio Rangel - Sao Jose do Rio Preto, SP - Book: Linux Programming Guide - 25.00
1 - Eustaquio Rangel - Sao Jose do Rio Preto, SP - Book: Design Patterns - 35.00
2 - Ana Carolina - Sao Jose do Rio Preto, SP - Book: Photoshop 7.0 - 22.50
3 - Andre Kada - Sao Paulo, SP - CD: Kreator - Violent Revolutions - 15.00
*** USEFUL TIP ***
For more samples, check the website (http://phpreports.sourceforge.net) with the files
included here.
5.1 - Report layout
Now you need a report grouping your data by city, something like this:
+---------------------------------------+----+
| John Doe Enterprises |////+--- document layer
| Sales Report |////|
+------+--------------------------------+----+
| city | <city goes here> |\\\\|
+------+-+------+-------------+---------+\\\\|
| id | name | product | $ |\\\\|
+------+--------+-------------+---------+\\\\+--- group layer
| <id> | <name> | <product> | <value> |\\\\|
+------+--------+-------------+---------+\\\\|
| total | <total> |\\\\|
+-----------------------------+---------+----+
| page total | <total> |////+--- page layer
+-----------------------------+---------+----+
| report total | <total> |\\\\+--- document layer (again)
+-----------------------------+---------+----+
The first thing you need to think is make your report layout as a HTML table
( to be honest, IT IS a HTML table ), so on the report above we have a HTML
table with 4 columns and 8 rows.
5.2 - PHP code
Now let's see the PHP code to ask your database about your data and make the
report:
<?php
include 'PHPReportMaker.php';
$sql = "select ID,NAME,CITY,PRODUCT,VALUE from SalesLog order by ID";
$parm = Array();
makeReport( "sales.xml", "PHPReport.xsl", "scott", "tiger", "connection", "databaseinterface", $sql, $parm );
?>
The makeReport function is the only one PHP function you'll need to deal with. Let's take
a look on the parameters above:
1 - "sales.xml" - a string with the report layout
2 - "PHPReports.xsl" - a XSLT file used to convert all the XML files into PHP code
3 - "scott" - a string with the database user name
4 - "tiger" - a string with the user password
5 - "connection"- the database connection
6 - "databaseinterface" - you'll need to specify which database you're connecting with,
for example, "oracle".
7 - $sql - a string with the SQL query
8 - $parm - an array with parameters - limited to 5 parameters
If you think there's is too much parameters on the makeReport function (sometimes I think
this way too), there's a class to help with this. It's named PHPReportMaker and the example
above will looks like this using it:
<?php
include 'PHPReportMaker.php';
$sql = "select ID,NAME,CITY,PRODUCT,VALUE from SalesLog order by ID";
$oRpt = new PHPReportMaker();
$oRpt->setXML("sales.xml");
$oRpt->setUser("scott");
$oRpt->setPassword("tiger");
$oRpt->setConnection("connection");
$oRpt->setDatabaseInterface("databaseinterface");
$oRpt->setSQL($sql);
$oRpt->run();
?>
Did you noticed that we didn't use the parameter array and the XSLT? The class have some
default values on it (to be honest, just the parameter is a Array() as default, the
XSLT processor is always "PHPReport.xsl" and the rest of the parameters are all null and
it wont work if you try to run it this way ehehe) and - for not mandatory parameters -
we can run it this way. Sometimes is very easier and coding understandable use the class
than the function.
Pay attention specially on the XSLT file - if its not on your current dir, it wont work
and you'll need to tell where it is. So you'll need something like
$oRpt->setXSLT(<myXSLTfilefullpath>) also.
The makeReports parameters are:
1 - a string with the path to the XML report file, where is the report layout *REQUIRED*
2 - a string with the path to the XSLT file used on the transformation *REQUIRED*
3 - a string with the database user name *REQUIRED*
4 - a string with the database password *REQUIRED*
5 - a string with the database connection name - for ex. in Oracle, a name in
the TNSNAMES.ORA file *REQUIRED*
6 - a string with the database interface (read about this below) *REQUIRED*
7 - a string with your sql query *REQUIRED*
8 - an Array with parameters
9 - a string with the database name you want to use
10 - a string with PHP code output file path - the PHP classes generated with the
XML -> XSLT files to run your report
11 - a string with the HTML result file path - when this parameter is not null,
the file will be created and no output will be done when running your report,
but its useful when you want to deal with another other thing before showing
the report on the screen - for ex. I use it when I want users open the report
on a new page when they want to do it, so I put some temporary name here and
make a link inside a Javascript script to open it.
12 - boolean - if true, PHPReports will give you a brief description of your report,
after process it - there you can see how PHPReports is "seeing" your XML layout file.
*** SECURITY WARNING ***
If you specify a PHP file to be created with the parameter 10, you *MUST* erased it
after the use, because it keeps the database user and password stored right there.
If you just use the parameter 10 as null, the file will be automatically erased
after the report output. Use as non null for debugging purposes.
The PHPReportMaker class have these methods:
run() - used when all parameters are ok - fire the report.
setXML(string)/getXML() - set/get the XML file path
setXSLT(string)/getXSLT() - set/get the XSLT file path
setUser(string)/getUser() - set/get the database user name
setPassword(string)/getPassword() - set/get the database password
setConnection(string)/getConnection() - set/get the connection name
setDatabaseInterface(string)/ - set/get the database interface
getDatabaseInterface()
setSQL(string)/getSQL() - set/get the SQL query string
setParameters(array)/getParameters() - set/get the parameters array
setDatabase(string)/getDatabase() - set/get the database name
setPHPOutput(string)/getPHPOutput() - set/get the PHP output file path
setOutput(string)/getOutput() - set/get the HTML output file path
setDebug(boolean)/getDebug() - set/get the debug feature
Just to take a quick explanation before going to the long one, the database interfaces
are some files with "db_" on the first position of its names. For example, there's a
db_oracle.php I'm working right now. Inside of it there's some functions to provide
ways to open the connection with the database, run the SQL query and so on. Since a
database uses different functions than the others, you can specify the way it will
handle that funcionality. The user and password parameters are used to open the
connection specified by the connection parameter.
I'm using the Oracle interface right now, I'll put some others on it, if you
make one please send me to be included on the project.
5.3 - XML layout file
*** IMPORTANT NOTE ***
Since PHPReports 0.0.8 I included some XML samples with the package - check the website
for samples.
Now, the XML report layout. It is specified by the sales.xml parameter, but what sales.xml
have inside ? Remember the HTML table comparison ? So, we'll need a XML *well-formed*
doc like that, with rows and columns. But with the three report layers defined on it
too !!! It will looks like :
(P.S.: The sales.xml included in the package is not equal this one - its here just for
example purposes)
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<?xml-stylesheet type="text/xsl" href="PHPReport.xsl"?>
<!DOCTYPE REPORT SYSTEM "PHPReport.dtd">
<REPORT>
<TITLE>Sales Report</TITLE>
<PATH>phpreports/</PATH>
<BACKGROUND_COLOR>#FFFFFF</BACKGROUND_COLOR>
<CSS>johndoe.css</CSS>
<DOCUMENT>
<FOOTER>
<ROW>
<COL COLSPAN="3" TEXTCLASS="BOLD" ALIGN="RIGHT">report total</COL>
<COL TYPE="EXPRESSION" TEXTCLASS="BOLD" ALIGN="RIGHT">$this->getSum( "VALUE" )</COL>
</ROW>
</FOOTER>
</DOCUMENT>
<PAGE SIZE="30">
<HEADER>
<ROW>
<COL COLSPAN="4" TEXTCLASS="BOLD">John Doe Enterprises</COL>
</ROW>
<ROW>
<COL COLSPAN="4" TEXTCLASS="BOLD">Sales Report</COL>
</ROW>
</HEADER>
<FOOTER>
<ROW>
<COL COLSPAN="3" TEXTCLASS="BOLD" ALIGN="RIGHT">page total</COL>
<COL TYPE="EXPRESSION" TEXTCLASS="BOLD" ALIGN="RIGHT">$this->getSum( "VALUE" )</COL>
</ROW>
</FOOTER>
</PAGE>
<GROUPS>
<GROUP NAME="CityBreak" EXPRESSION="CITY">
<HEADER>
<ROW>
<COL ALIGN="RIGHT">city:</COL>
<COL TYPE="EXPRESSION" COLSPAN="3" TEXTCLASS="BOLD">$header->getValue( "CITY" )</COL>
</ROW>
<ROW>
<COL>id</COL>
<COL>name</COL>
<COL>product</COL>
<COL>$</COL>
</ROW>
</HEADER>
<FIELDS>
<ROW>
<COL>ID</COL>
<COL>NAME</COL>
<COL VISIBLE="FALSE">CITY</COL>
<COL>PRODUCT</COL>
<COL ALIGN="RIGHT" NUMBERFORMATEX="2">VALUE</COL>
</ROW>
</FIELDS>
<FOOTER>
<ROW>
<COL ALIGN="RIGHT">total</COL>
<COL TYPE="EXPRESSION" COLSPAN="3" TEXTCLASS="BOLD" ALIGN="RIGHT" NUMBERFORMATEX="2">$this->getSum( "VALUE" )</COL>
</ROW>
</FOOTER>
</GROUP>
</GROUPS>
</REPORT>
So, let's take a look on it. First of all, we have three lines of XML instructions
about version, encoding, and the DTD file (we talk about it on the next section),
and our root element, always defined by the REPORT tag. REPORT have some elements
inside of it, but we'll see it later ( we have the TITLE, PATH, BACKGROUND_COLOR
and CSS elements defined here ). Next will come the DOCUMENT tag ( remember it? ) with the
FOOTER defined. FOOTER, as HEADER and other tags, have ROWs and COLs inside of it.
After the REPORT tag, we have the PAGE tag and the GROUPS tag, with GROUPs tags
inside of it.
You can have a preview of how your report will look like, *without* the data,
using the PHPReportPreview.php file. Just point your web browser to the file,
using a "xml" parameter with the full path of your XML report layout file, for ex.:
http://localhost/phpreports/PHPReportPreview.php?xml=sales6.xml
You really need to specify the full XML path and you *must* run PHPReportPreview
on the same dir where is located the PHPReportPreview.xsl file. Of course
you can change this behaviour on the PHPReportPreview.php code, its really
easy to do that. :-)
5.4 - DTD file
Let's take a closer look on the PHPReports.dtd file ( if you don't know what the
hell are XML tags, a DTD file and stuff like that, search on the web about some
quick-and-easy XML tutorial, will be better to understand the way the things works
here, http://www.w3schools.com/xml/ is a good choice ):
<?xml version="1.0" encoding="ISO-8859-1"?>
<!ELEMENT REPORT (TITLE?,PATH?,BACKGROUND_COLOR?,BACKGROUND_IMAGE?,CSS?,SQL?,DOCUMENT?,PAGE?,GROUPS?)>
<!ATTLIST REPORT MARGINWIDTH CDATA #IMPLIED>
<!ATTLIST REPORT MARGINHEIGHT CDATA #IMPLIED>
<!ELEMENT TITLE (#PCDATA)>
<!ELEMENT PATH (#PCDATA)>
<!ELEMENT BACKGROUND_COLOR (#PCDATA)>
<!ELEMENT BACKGROUND_IMAGE (#PCDATA)>
<!ELEMENT CSS (#PCDATA)>
<!ELEMENT SQL (#PCDATA)>
<!ELEMENT DOCUMENT (HEADER?,FOOTER?)>
<!ELEMENT HEADER (ROW*)>
<!ELEMENT FOOTER (ROW*)>
<!ELEMENT ROW (COL*)>
<!ELEMENT COL (LINK?)>
<!ATTLIST COL TYPE CDATA #IMPLIED>
<!ATTLIST COL NUMBERFORMAT CDATA #IMPLIED>
<!ATTLIST COL NUMBERFORMATEX CDATA #IMPLIED>
<!ATTLIST COL CELLCLASS CDATA #IMPLIED>
<!ATTLIST COL TEXTCLASS CDATA #IMPLIED>
<!ATTLIST COL ROWSPAN CDATA #IMPLIED>
<!ATTLIST COL COLSPAN CDATA #IMPLIED>
<!ATTLIST COL WIDTH CDATA #IMPLIED>
<!ATTLIST COL HEIGHT CDATA #IMPLIED>
<!ATTLIST COL ALIGN CDATA #IMPLIED>
<!ATTLIST COL VALIGN CDATA #IMPLIED>
<!ATTLIST COL VISIBLE CDATA #IMPLIED>
<!ATTLIST COL SUPPRESS CDATA #IMPLIED>
<!ELEMENT PAGE (HEADER?,FOOTER?)>
<!ATTLIST PAGE SIZE CDATA #IMPLIED>
<!ATTLIST PAGE WIDTH CDATA #IMPLIED>
<!ATTLIST PAGE HEIGHT CDATA #IMPLIED>
<!ATTLIST PAGE CELLPADDING CDATA #IMPLIED>
<!ATTLIST PAGE CELLSPACING CDATA #IMPLIED>
<!ATTLIST PAGE BORDER CDATA #IMPLIED>
<!ATTLIST PAGE ALIGN CDATA #IMPLIED>
<!ELEMENT GROUPS (GROUP+)>
<!ELEMENT GROUP (HEADER?,FIELDS?,FOOTER?,GROUP*)>
<!ATTLIST GROUP NAME CDATA #REQUIRED>
<!ATTLIST GROUP EXPRESSION CDATA #IMPLIED>
<!ATTLIST GROUP PAGEBREAK CDATA #IMPLIED>
<!ELEMENT FIELDS (ROW?)>
<!ELEMENT LINK (#PCDATA)>
<!ATTLIST LINK TYPE CDATA #REQUIRED>
<!ATTLIST LINK TARGET CDATA #IMPLIED>
<!ATTLIST LINK TITLE CDATA #IMPLIED>
<!ELEMENT XHTML (#PCDATA)>
6 - DTD file
6.1 - REPORT element
Elements inside:
TITLE - the HTML title that will appear on the window's title.
PATH - the path where the PHPReports classes are.
another thing you must do its provide a final slash (/)
on the path (ex. phpreports/). its also a good idea
put the contents of the PHPReports tar file on a directory
without any other classes, just for organization. :-) you
can set the include_path on PHP too to fit where the
PHPReports classes are and avoid this feature.
BACKGROUND_COLOR - report background color
BACKGROUND_IMAGE - report background image
CSS - path to the CSS file you want to use on your report
SQL - you can write the SQL query here if you want to
DOCUMENT - the document layer
PAGE - the page layer
GROUPS - the GROUPS element ( not the group layer! )
Attributes:
MARGINWIDTH - margin width, in pixels
MARGINHEIGHT - margin height, in pixels
6.2 - COL element
Elements inside:
LINK - LINK element (see 6.10)
Attributes:
TYPE - if you define type as EXPRESSION, PHPReports will parse all you put
on the COL element as PHP code
NUMBERFORMAT - if its a numeric column, you can specify here how to format it, using
the C formatting standard ( for example, "%10.2f" )
NUMBERFORMATEX - number format extended. use this property to format numbers with
decimal places and thousands separator. put the number of decimal places
on the property value. remember to use setLocale to the locale you want.
CELLCLASS - specify here a CSS class the column cell will use
TEXTCLASS - specify here a CSS class that the column text will use
ROWSPAN - how many rows this cell will use
COLSPAN - how many cols this cell will use
WIDTH - the cell width
HEIGHT - the cell height
ALIGN - cell horizontal alignment
VALIGN - cell vertical alignment
VISIBLE - if FALSE, this column will not be visible when on the group layer
SUPPRESS - if TRUE, will not show repeated values on the group layer
6.3 - ROW element
Elements inside:
COL - COL element (see 6.2)
6.4 - HEADER element
Elements inside:
ROW - ROW element (see 6.3)
6.5 - FOOTER element
Elements inside:
ROW - ROW element (see 6.3)
6.6 - PAGE element
Elements inside:
HEADER - HEADER element (see 6.4)
FOOTER - FOOTER element (see 6.5)
Attributes:
SIZE - the number of lines this page will have
WIDTH - page width, in pixels
HEIGHT - page height, in pixels
CELLPADDING - inner page cell padding ( the same as HTML TABLE CELLPADDING )
CELLSPACING - inner page cell spacing ( the same as HTML TABLE CELLSPACING )
BORDER - the page border between the rows and cols, you can set it greater than 0
to see how your table is looking like
ALIGN - the alignment of the page on browser window
6.7 - FIELD element
Elements inside:
ROW - ROW element (see 6.3)
6.8 - GROUP element
Elements inside:
HEADER - HEADER element (see 6.4)
FIELDS - FIELD element (see 6.7)
FOOTER - FOOTER element (see 6.5)
GROUP - GROUP element (this one! a group can contain another group)
Attributes:
NAME - name of the group, will be used to create a class with this name
EXPRESSION - the field name where the group break expression will be based, I
mean, when this field value changes, will be fired a group break
event
PAGEBREAK - if YES, everytime this group breaks it will generate a page break
6.9 - GROUPS element
Elements inside:
GROUP - GROUP element (see 6.8)
6.10 - LINK element
Attributes:
TYPE - STATIC for static links, ie links that do not change or
DYNAMIC for links that change with the values of a sql result field.
TARGET - target frame where the link will open
TITLE - mouse over tooltip text
6.11 - XHTML element
Elements inside:
Every XHTML element you want.
7 - Validating your document
You can use RXP (http://www.cogsci.ed.ac.uk/~richard/rxp.html) to validate your
XML file, ALWAYS BEFORE use it on the browser (trust me, it's a good idea).
The syntax is something like this:
rxp -V -o 0 <file.xml>
8 - File list
db_mysql.php - MySQL interface
db_oracle.php - Oracle interface
db_interbase.php - Interbase interface
db_mssql.php - Microsoft SQL Server interface
db_adodb.php - ADODB interface (thanks Aztek!)
PHPRepoDoc.php - document layer object
PHPRepoField.php - database field object
PHPRepoGroup.php - group layer object
PHPRepoPage.php - page layer object
PHPRepoRow.php - database row object
PHPReport.dtd - XML validation file
PHPReportMaker.php - the function/class used to make the reports
phpreports.css - style file
PHPReport.xsl - XSLT transformation file
PHPReportCol.xsl - XSLT transformation file
PHPReportDoc.xsl - XSLT transformation file
PHPReportField.xsl - XSLT transformation file
PHPReportGroup.xsl - XSLT transformation file
PHPReportPage.xsl - XSLT transformation file
PHPReportTable.xsl - XSLT transformation file
PHPReportXHTML.xsl - XSLT transformation file
sales.php - PHP sample file
sales7.php - PHP sample file
sales.xml - XML example file
sales2.xml - XML example file
sales3.xml - XML example file
sales3b.xml - XML example file
sales4.xml - XML example file
sales5.xml - XML example file
sales6.xml - XML example file
sales7.xml - XML example file
sales8.xml - XML example file
PHPReportPreview.xsl - XSLT transformation file for previewing
PHPReportPreview.php - code for use with the preview XSLT
README - this file
LEIAME - this file, but the Portuguese version
9 - Final considerations
No final considerations. :-) Test the tags and attributes to see which
satisfy your needs, make a lot of tests, I think everything should run
just fine. See ya !!!
10 - Changelog
2002 August 11
--------------
- rewriten some code to keep the database interfaces on a smooth way to deal with
- added the mySQL interface file
- changes made on the XSLT file
- added XSLT file path on the makeReport function
- added database parameter on the makeReport function
2002 August 31
--------------
- added the m$ SQL Server interface
- some corrections made on this document
2002 September 2
----------------
- added the NUMBERFORMATEX property, to format numbers with decimal places and
thousands separator.
2002 September 10
-----------------
- major bug fix: the values processed was not going to the header group, so
you could not referer to it (always null). now it works.
- added a reference to the header data with the $header var. now you can
refer to the header data using $oValue (urgh!) or $header (nice). :-)
2002 September 11
-----------------
- added the getRowNum() function, to return the row number on the page object.
2002 October 21
---------------
- fixed some stuff here on docs (thanks to Remigijus Sajauka)
2002 December 27
----------------
- fixed some stuff here on the docs again
2003 January 23
---------------
- added the HTML file output parameter
- created the PHPReportMaker class
- added the FAQ section here on the README file
2003 January 26 (1 week of vacations! ooh-hoo!)
-----------------------------------------------
- modified the parameters - now you can reference to it with the array key (if
is there any) or on the numeric form (still 1 based, not 0)
2003 January 28
---------------
- MAJOR BUG! MySQL returns some numeric fields as REAL type, and I didn't faced
it yet. Now its fixed. It corrects the behaviour of all the grouping functions
(getSum(),getMax(),getMin()...) who checks the field type to process its value.
my apologies to all the people who are using mySQL.
- to fix the bug above, we need a way to see how PHPReports is seeing the data
types, so I introduced the debug() function - check the makeReport parameters
above - to debug how PHPReports is "seeing" your XML layout file and on this
kind of bug, what the field type string the database is returning, remember that
only numeric fields are allowed to use the grouping functions.
2003 January 29
---------------
- spent all day writing the new site ... a lot of documentation, oh man I hate
to do that ehehe. :-)
- added the sample files - XML, PHP and CSS. check the website
(http://phpreports.sourceforge.net) for instructions how to use it.
- will release 0.0.8 today.
2003 February 04
----------------
- created the PHPReportPreview file. you can use it to preview how your report
layout is looking like *before* run the SQL query on your database. it can
save some time and data processing to you. Just refer to it on your web
browser with the parameter "xml" with your XML layout file path. for ex:
http://localhost/phpreports/PHPReportPreview.php?xml=sales6.xml
you really need to specify the full XML path and you *must* run PHPReportPreview
on the same dir where is located the PHPReportPreview.xsl file. of course
you can change this behaviour on the PHPReportPreview.php code, its really
easy to do that. :-)
2003 February 09
----------------
- translated this file to its Portuguese version, the LEIAME file
2003 February 10
----------------
- changed the way it print values - if no value is present on the
field, it prints a white space, to make the HTML cell table look
"right" (thanks to Kenneth N. Flaxman for my first patch!)
- created the CELLCLASSEVEN and CELLCLASSODD parameters - use it in
the fields elements to make a distinction between even and odd rows
(based on the current group). you can check sales3b.xml for an
example.
2003 February 15
----------------
- added the Interbase database interface (thanks to Andre "Biriba"
<andre@appsistemas.com.br> for his patience testing the interface -
I don't have a Interbase database for testing ehehehe).
- added the LINK element to insert HTML A HREF links inside the
COL element.
2003 February 22
----------------
- splitted the main XSLT file into smaller ones - easier to manage
- added the ADODB interface - thank you very much, Aztek!
to use this, set the set setDatabaseInterface("adodb") and
setConnection to something like setConnection("mysql:localhost");
- added support for XHTML elements into the XML file - pay attention,
its XHTML and not HTML, there's very few differences (the XHTML
files need to be well-formed) about them, learn more about on
http://www.w3.org
11 - Index of the most common PHP functions in the PHPReports classes
You can use some functions to returns you some values of the current
fields/groups:
getValue("field") - returns the current value of the field.
getMin("field") - returns the min value of the field on the current group
getMax("field") - returns the max value of the field on the current group
getSum("field") - returns the sum of all the field values on the current group
getAvg("field") - returns the average of all the field values on the current group
getRowCount() - returns the row count of the current group
getParameter(index) - returns the parameter on the index position (1 based)
getParameter("key") - returns the parameter on the specified key
You must use this functions with the $this-> reference. For example:
$this->getSum("TOTAL");
inside your XML file. The only exception is with values you get from
the HEADER element. You must use the $oValue-> reference there, for
example:
$oValue->getValue("CITY");
If you're using a version greater or equal 0.0.5, you can use the $header
var to do that also (I think the name is more "clear" ):
$header->getValue("CITY");
*** IMPORTANT ***
I explain why. PHPReports just process the field values when it
reachs the ROW element on the GROUP element. When it is on the HEADER
element, the values are passed there with the $header ( former $oValue )
object, but its not processed to be refered with the $this reference yet.
You need to understand that regarding the header values ...
Another other thing I must say that can be a little confuse is about
getParameter(). When you put the parameters values on the array you
use on the makeReport function, its 0 based. But when you get the
parameter on the XML file, its 1 based. I think its just weird you
say "get the parameter 0" so I put this way. Don't know if was a
good idea, but at least you can say "get the first parameter". :-)
On January 23 2003 I changed this only way to reference to the parameters
with the possibility to reference using the array keys too. In my opinion
its easier to deal with it ... for example:
On the numeric reference way:
$parm = Array();
$parm[0] = "SAO PAULO";
$parm[1] = "RIO DE JANEIRO";
and on the XML file
getParameter(1); <- will return SAO PAULO - remember, 1 based, not 0
getParameter(2); <- will return RIO DE JANEIRO
On the key reference way:
$parm = Array();
$parm["from"] = "SAO PAULO";
$parm["to"] = "RIO DE JANEIRO";
and on the XML file
getParameter("from"); // will return SAO PAULO
getParameter("to"); // will return RIO DE JANEIRO
12 - FAQ
Q: How can I test if Sablotron is running ok?
A: Make a little test with the sales6.xml file and the PHPReportPreview.xsl
file, run the sabcmd like this:
sabcmd PHPReportPreview.xsl sales6.xml test.html
It must return a valid HTML output in the test.html. Open it on your
browser to see a preview of the report layout.
Q: I got an error running the report and all the instalation stuff
is ok ... something like Fatal error: Call to a member function on
a non-object in blah blah blah ... what is happening?
A: Check the case of the fields on the SQL query and on the XML report
layout file - some databases needs the fields exactly equal, upper
and lower chars.
Q: My output is zero lines of data. What is happening?
A: Check the PAGE SIZE parameter, if its too tiny you will not see
your report.
Q: I'm having some trouble with the PHPReports classes - it tells
me that its not finding some classes to include.
A: There's a parameter PATH on the REPORT element. If using it your
problem is not over, remove the PATH parameter and add the PHPReports
path to your PHP code using ini_set("<your_phpreports_files_dir>"). I
think this way is better. :-)
Q: I can get any values on the header.
A: Use $header and not $this and check the HEADER element explanation above.
Q: The grouping functions (getSum(),getMin()) are not working! I just
get 0 or null results when invoking them.
A: Please uset the setDebug(true) method and email me the output -
there PHPReports will tell how it is seeing the field types, and
since it just process numeric fields, maybe the way your database
is returning the field type is not one of the types I put as numeric
ones. You don't need to send me the full report, just the description.
Ah, and tell me what database you're using too.
Q: Where can I find more info about PHPReports?
A: Check the website, http://phpreports.sourceforge.net.