I. Introduction▲
PHP a gagné d'année en année une image de langage professionnel, simple et performant. Comme le montre l'Association française des utilisateurs de PHP dans son livre blanc « PHP en Entreprise » (1), il y a un très grand nombre de sites Internet de renom, de sociétés du CAC 40 qui développent en PHP. Ce qui renforce alors cette image de robustesse. Cette notoriété du langage est aussi visible compte tenu du nombre d'articles qui lui est consacré, et le nombre très important de recherches effectuées sur Google(2).
Il existe quelques bibliothèques de bon niveau pour la production de graphiques, de documents au format pdf. Toutefois, peu d'entre elles fournissent un environnement pour assister les concepteurs de rapports dans leur élaboration et leur publication. Agatha Reports (3), un projet brésilien présente l'ambition d'apporter à PHP les outils de reporting qui lui manque. Cette solution bien que fonctionnelle ne supporte pas à ce jour PHP5 (4). De même, la nouvelle plate-forme de Zend en version 3.0.2 (5) affiche un support pour BIRT(6), un environnement de conception de rapport basé sous Eclipse et appuyé par Actuate.
Jasper Reports a offert au monde Java TM un moteur de grande qualité pour la génération de rapports rassemblant tableaux, graphiques, mêlant des sources de données très hétérogènes (rapport multisource). Cet outil en plus d'être très performant sait exporter vers divers formats tels que : pdf, html, xls, xml, cvs, txt, rtf et notamment un support pour Open Office depuis sa dernière version. Par ailleurs, iReport, un environnement de développement pour Jasper Reports procure une assistance de haut niveau dans la construction des autres rapports ou états. En plus, les deux projets suivent une évolution synchronisée. Ainsi, toutes les fonctionnalités ajoutées au moteur Jasper Reports sont prises en compte par iReport.
Nombreuses sont les interrogations postées sur les forums sur les outils de reporting en PHP, ou encore sur l'intégration entre PHP et des environnements de reporting tiers. Voilà une réponse : « PHP et Jasper Reports » ! Celle-ci nous semble élégante parce qu'elle apporte de la productivité, grâce à iReport qui est assez simple à prendre en main évitant alors d'apprendre l'API de la bibliothèque. Ensuite, Jasper Reports est un moteur aujourd'hui éprouvé : de nombreuses solutions libres ou propriétaires l'embarquent, des grandes sociétés comme Siemens, des administrations françaises en font un usage régulier. Enfin, l'association PHP, Java, via PHP/Java Bridge (7) commence à gagner ses galons. Même si certains pensent qu'il existe des marges d'amélioration (8). Ce projet rend possible l'instanciation d'objets java depuis des programmes PHP avec la syntaxe PHP.
Vous l'avez compris pour intégrer des rapports Jasper Reports à vos programmes PHP, il est nécessaire d'installer PHP/Java Bridge.
II. Installation de PHP/Java Bridge▲
II-A. installation sous GNU Linux▲
L'installation sous GNU Linux est assez simple, car les packages sont disponibles au format rpm. Il convient de télécharger le fichier php-java-bridge-x.y.z-1-i386.rpm et de l'installer :
rpm -i php-java-bridge-x.y.z-1
-i386.rpm
où « x.y.z » correspond à la dernière version stable.
Bien sûr il est nécessaire d'avoir une machine virtuelle Java installée sur sa machine. Dans le fichier php.ini il faut au moins initialiser la variable java.java. Vous devez dans votre fichier php.ini (ou php.d/java.ini) ajouter les entrées :
java.java_home
=
{Répertoire d'installation JAVA}
java.java={Répertoire d'
installation JAVA}/java
où {Répertoire d'installation JAVA} est à remplacer par le chemin vers votre installation du SDK.
Si vous souhaitez faire dialoguer vos applications PHP et un serveur J2EE installez le package php-java-bridge-tomcat :
rpm -i php-java-bridge-tomcat-x.y.z-1
.i386.rpm
Pour télécharger les fichiers adéquats, voir : http://sourceforge.net/project/showfiles.php?group_id=117793.
II-B. installation sous Windows▲
Ici, il faut télécharger php-java-bridge_y.x.z_j2ee.zip, le décompresser dans un répertoire temporaire. Parmi les fichiers décompressés il y a une archive web JavaBridge.war. Décompressez-la aussi et copiez les fichiers JavaBridge.jar et java-x86-windows.dll respectivement depuis WEB-INF/lib et WEB-INF/cgi dans le répertoire de vos extensions php. Enfin, il vous faut ajouter quelques entrées dans votre fichier php.ini.
Extension=php_java.dll
Votre fichier php.ini intègre alors la ligne précédente et est proche de ce qui suit :
; windows Extensions
; Note that ODBC support is built in, so no dll is nedded for it.
; Note that mny DLL files are located in the extensions/ (PHP 4
) ext/ (PHP 5
)
...
...
;extension-php_mbstring.dll
;extension-php_bz2.dll
...
...
extension-php_java.dll
...
...
Enfin configurez le connecteur Java pour PHP
;;;;;;;;;;;;;;;;;;;
; Module Settings ;
;;;;;;;;;;;;;;;;;;;
[java]
java.java_home = "c:\Program File\Java\jdk1.5
.0_10\bin"
java.java = "c:\Program File\Java\jdk1.5
.0_10\bin\javaw.exe"
java.class.path = "c:\php\ext\JavaBridge.jar"
java.library.path = "c:\php\ext"
;java.hosts = "127
.0
.0
.1
:8080
"
;java.servlet = On
java.log_level = 2
Bien sûr les différentes variables sont à initialiser avec les valeurs relatives à votre environnement Java (le répertoire où est installé votre SDK), ou de votre serveur d'application J2EE.
Pour plus d'informations : http://www.dsl.uow.edu.au/~sk33/php5java.htm.
II-C. Vérification du support java de PHP▲
Vous devez redémarrer votre serveur apache et vérifier que vous avez bien le support java de PHP.
Créez une page phpinfo.php et insérez-y les lignes suivantes :
<?php
phpinfo();
?>
Sauvez ce fichier, publiez-le sur votre environnement web, et appelez la page depuis votre navigateur. Vous devrez observer le support java de php.
II-D. Votre première intégration entre PHP et Java▲
Créez un fichier java.php et collez les lignes suivantes :
<?php
// créer une instance de la classe Java java.lang.System dans PHP
$system
=
new
Java('java.lang.System'
);
// accéder aux propriétés
echo 'Java version='
.
$system
->
getProperty('java.version'
) .
' <br />'
;
echo 'Java vendor='
.
$system
->
getProperty('java.vendor'
) .
'<br />'
;
echo 'OS='
.
$system
->
getProperty('os.name'
) .
' '
.
$system
->
getProperty('os.version'
) .
' on '
.
$system
->
getProperty('os.arch'
) .
'<br />'
;
// Exemple avec java.util.Date
$formater
=
new
Java('java.text.SimpleDateFormat'
,
"EEEE, MMMM dd, yyyy 'at' h:mm:ss a zzzz"
);
echo $formater
->
format(new
Java('java.util.Date'
));
?>
Enregistrez cette page web et appelez-la depuis votre navigateur.
III. Appel des fichiers JasperReports depuis PHP▲
III-A. Bâtir votre modèle de document avec iReport▲
Grâce à iReport vous allez pouvoir construire votre rapport :
- Définissez votre connexion à votre base de données ou autre source de données ;
- Créez un nouveau document ;
- Créez une requête avec l'assistant ;
- Ajoutez les éléments que vous souhaitez à votre rapport ;
- Enregistrez votre rapport ;
- Exécutez le rapport.
III-B. Écrire le script PHP qui appelle votre fichier JRXML▲
Dans l'exemple qui suit nous allons procéder à des instanciations des classes de l'API java de Jasper Reports en suivant les étapes généralement indiquées dans les exemples fournis par leur démo.
Créez un fichier que vous pouvez par exemple nommer jasperreports.php et ajoutez les lignes suivantes :
<?php
$reportsPath
=
"/home/ccharly/publichtml/utils/reports/"
;
$reportFileName
=
"CommandesClients1"
;
$jasperReportsLib
=
"/home/ccharly/publichtml/utils/jasperlib"
;
if
(extension_loaded('java'
)) {
// lecture du répertoire où sont rangées les bibliothèques utiles à JasperReports
$handle
=
@
opendir($jasperReportsLib
);
// ajout de tous les fichiers jar au chemin de classe (Class Path)
while
(($new_item
=
readdir($handle
))!==
false
) {
$java_library_path
.=
'file:'
.
$jasperReportsLib
.
'/'
.
$new_item
.
';'
;
}
try
{
// chargement des bibliothèques au classpath
java_require($java_library_path
);
// création de la connexion JDBC
$Conn
=
new
Java("org.altic.jasperReports.JdbcConnection"
);
// driver
$Conn
->
setDriver("com.mysql.jdbc.Driver"
);
// url de connexion
$Conn
->
setConnectString("jdbc:mysql://localhost/erpmart"
);
// utilisateur
$Conn
->
setUser("root"
);
// mot de passe
$Conn
->
setPassword(null
);
// Compilation du fichier JRXML en fichier Jasper
$sJcm
=
new
JavaClass("net.sf.jasperreports.engine.JasperCompileManager"
);
$report
=
$sJcm
->
compileReport($reportsPath
.
$reportFileName
.
".jrxml"
);
// Remplir le modèle avec les données
$sJfm
=
new
JavaClass("net.sf.jasperreports.engine.JasperFillManager"
);
$print
=
$sJfm
->
fillReport(
$report
,
new
Java("java.util.HashMap"
),
$Conn
->
getConnection()
);
// Export du fichier au format pdf
$sJem
=
new
JavaClass("net.sf.jasperreports.engine.JasperExportManager"
);
$sJem
->
exportReportToPdfFile($print
,
$reportsPath
.
$reportFileName
.
".pdf"
);
if
(file_exists($reportsPath
.
$reportFileName
.
".pdf"
)){
header('Content-disposition: attachment; filename="'
.
$reportFileName
.
'.pdf"'
);
header('Content-Type: application/pdf'
);
header('Content-Transfer-Encoding: binary'
);
header('Content-Length: '
.
@
filesize($reportsPath
.
$reportFileName
.
".pdf"
));
header('Pragma: no-cache'
);
header('Cache-Control: must-revalidate, post-check=0, pre-check=0'
);
header('Expires: 0'
);
set_time_limit(0
);
@
readfile($reportsPath
.
$reportFileName
.
".pdf"
) or
die("problem occurs."
);
}
}
catch
(JavaException $ex
) {
$trace
=
new
Java("java.io.ByteArrayOutputStream"
);
$ex
->
printStackTrace(new
Java("java.io.PrintStream"
,
$trace
));
print
"java stack trace:
$trace\n
"
;
}
}
?>
Vous devez adapter le fichier en modifiant les variables suivantes :
$reportsPath : chemin où sont rangés vos rapports au format jrxml ;
$reportFileName : nom du fichier à compiler et exporter en pdf (remarque : ici seule la racine du nom du fichier est nécessaire) ;
$jasperReportsLib : répertoire des bibliothèques nécessaires à l'utilisation de JasperReports. Ce répertoire contient par exemple les mêmes bibliothèques que celles contenues dans le répertoire lib d'iReport.
La commande java_require charge dans le classpath toutes ces bibliothèques. Veillez à ce que le répertoire désigné par $jasperReportsLib soit accessible à l'utilisateur qui fait tourner apache ainsi que les fichiers qu'il contient.
Ajoutez le fichier alticJasper.jar, il contient un petit utilitaire pour créer une connexion JDBC.
package
org.altic.jasperReports;
import
java.io.FileInputStream;
import
java.io.InputStream;
import
java.sql.Connection;
import
java.sql.DriverManager;
import
java.sql.SQLException;
import
java.util.Properties;
/**
*
@author
ccharly
*
*/
public
class
JdbcConnection {
private
String driver; // "oracle.jdbc.driver.OracleDriver";
private
String connectString; // "jdbc:oracle:thin:@YOUR_ORACLE_HOST:1521:YOUR_SID";
private
String user; //"YOUR_ORACLE_USER_NAME";
private
String password; // "YOUR_ORACLE_PASSWORD";
public
JdbcConnection
(
){
//loadPropertiesConnection();
}
public
JdbcConnection
(
String driver, String connectString, String user, String password){
this
.driver =
driver;
this
.connectString =
connectString;
this
.user =
user;
this
.password =
password;
}
public
void
loadPropertiesConnection
(
){
this
.driver =
""
;
this
.connectString =
""
;
this
.user =
""
;
this
.password =
""
;
try
{
Properties props =
new
Properties
(
);
InputStream resourceAsStream =
getClass
(
).getResourceAsStream
(
"/connection.properties"
);
props.load
(
resourceAsStream);
this
.setDriver
(
props.getProperty
(
"driver"
));
this
.setConnectString
(
props.getProperty
(
"connectString"
));
this
.setUser
(
props.getProperty
(
"user"
));
this
.setPassword
(
props.getProperty
(
"password"
));
}
catch
(
Exception e){
e.printStackTrace
(
);
}
}
public
Connection getConnection
(
)
{
try
{
//Change these settings according to your local configuration
Class.forName
(
this
.getDriver
(
));
Connection conn =
DriverManager.getConnection
(
this
.getConnectString
(
),
this
.getUser
(
),
this
.getPassword
(
));
return
conn;
}
catch
(
ClassNotFoundException e){
e.printStackTrace
(
);
}
catch
(
SQLException e){
e.printStackTrace
(
);
}
return
null
;
}
public
String toString
(
){
return
" Driver : "
+
this
.getDriver
(
) +
" | "
+
" ConnectString : "
+
this
.getConnectString
(
) +
" | "
+
" User : "
+
this
.getUser
(
) +
" | "
+
" Password : "
+
this
.getPassword
(
);
}
public
String getConnectString
(
) {
return
connectString;
}
public
void
setConnectString
(
String connectString) {
this
.connectString =
connectString;
}
public
String getDriver
(
) {
return
driver;
}
public
void
setDriver
(
String driver) {
this
.driver =
driver;
}
public
String getPassword
(
) {
return
password;
}
public
void
setPassword
(
String password) {
this
.password =
password;
}
public
String getUser
(
) {
return
user;
}
public
void
setUser
(
String user) {
this
.user =
user;
}
}
Vous devez donc modifier les paramètres de connexion vers votre base de données. Pensez aussi à ajouter la bibliothèque du connecteur JDBC vers votre base de données.
Indiquez le driver JDBC de votre base de données, par exemple pour MySql
$Conn
->
setDriver("
com.mysql.jdbc.Driver
"
);
Indiquez l'url de connexion
$Conn
->
setConnectString("
jdbc:mysql://{Nom du S}:{port}/{Nom de la Base de données}
"
);
Indiquez le nom de l'utilisateur
$Conn
->
setUser({
utilisateur};
Indiquez le mot de passe
$Conn
->
setPassword({
Mot de passe}
);
Une fois ces paramétrages terminés, vous êtes en mesure de générer vos rapports JasperReports depuis PHP. La compilation n'est sans doute pas utile si vous publier directement les fichiers « .jasper » que vous pouvez récupérer depuis iReport.
IV. Conclusion▲
Ce petit exemple montre comment il est ainsi possible d'exploiter JasperReports via une application PHP. Cette intégration apporte à PHP un outil de reporting performant et particulièrement productif grâce à iReport. Les concepteurs de rapports se retrouvent dans un environnement convivial et productif.
Pour augmenter à ce titre la productivité, il serait intéressant d'encapsuler JasperReports afin d'en masquer la complexité pour ne pas rebuter les utilisateurs de PHP déjà habitués à une syntaxe relativement simple. Prenons par exemple la connexion vers la base de données il faudrait une ligne de code qui serait :
$conn
->
getMySqlConnection({
nom du Serveur},
{
Port},
{
Base de données},
{
Utilisateur},
{
Mot de passe}
);
ou bien
$conn
->
getConnection({
Type de Base},{
nom du Serveur},
{
Port},
{
Base de données},
{
Utilisateur},
{
Mot de passe}
);
où {Type de Base} vaudrait : ORACLE, MYSQL, POSTGRESQL.
L'encapsulation éviterait aussi aux développeurs PHP d'avoir à manipuler les appels directs aux classes java, ce qui en simplifierait la lecture du code.
Le projet Dynamic Jasper offre une simplification de l'API JasperReports. Il serait intéressant de se baser sur ce projet pour développer une bibliothèque de scripts PHP pour JasperReports.
Pour aller plus loin▲
PHP / Java Bridge http://php-java-bridge.sourceforge.net/pjb.
Jasper Reports and PHP C'est un très bon article qui apporte déjà une certaine abstraction de la complexité de Jasper Report en PHP. Il faut je pense aller encore plus loin. Mais c'est un très bon début. http://www.rjohnson.id.au/wordpress/2007/02/04/jasper-reports-and-php/.
Projet Jasper Reports http://jasperforge.org/sf/projects/jasperreports.
Projet iReport http://jasperforge.org/sf/projects/ireport.
PHP et BEA Weblogic http://dev2dev.bea.com/pub/a/2007/02/php-java-bridge.html.
Les cours sur les générateurs d'états - sur Developpez.com https://etats.developpez.com.
Intégration de FOP et PHP / Java Bridge http://wiki.apache.org/xmlgraphics-fop/HowTo/PHPJavaBridge.
Dynamic Jasper http://dynamicjasper.sourceforge.net/.
Auteur▲
Charly Clairmont
Après un passage en startup de la « nouvelle économie », ensuite en SSII, il fonde Altic avec Marc Sallieres.
ALTIC, société spécialisée dans l'informatique de gestion en logiciel libre. Depuis trois ans, elle a aussi développé une forte expertise dans les solutions d'informatique décisionnelle en logiciel libre. Les différents projets menés dans le monde de l'entreprise, mais aussi des grandes administrations ont apporté aux consultants d'ALTIC une expérience pragmatique des solutions de reporting open source du marché (Jasper, Birt, Agata…).
ALTIC accompagne ses clients directement avec le support de ses partenaires qui sont pour la plupart les éditeurs open source du marché de l'informatique décisionnelle : Talend, Engineering, eXo Platform, JasperSoft…
ALTIC propose d'ailleurs des formations autour de ces solutions JasperReports/iReport Niveau 1 et Niveau 2 (Monitorat), Birt Niveau 1, mais aussi Mondrian Niveau 1 et enfin la plate-forme décisionnelle et collaborative SpagoBI.