A présent, nous allons débuter avec l'application la plus simple possible. Commencez par créer la structure de répertoire :
c:\wamp\www\ +-votreapp +-application +-controllers +-views +-scripts +-public
Le répertoire public correspondra à la racine de votre serveur Web sur votre serveur de production. Les feuilles de styles, les images et les scripts Javascript qui sont accessibles directement sans passer par PHP seront placés dans ce dossier. Il comprendra également le fichier index.php qui contiendra le code suivant :
/public/index.php
<?php
require '../application/bootstrap.php';
?>
C'est en fait dans le fichier bootstrap.php que l'on placera le code d'initialisation. Comme ce script est situé à l'extérieur de la racine du serveur Web de production, il est à l'abri d'un problème de configuration qui pourrait accidentellement en révéler le contenu. Nous reviendrons à ce fichier plus tard.
Toutes les requêtes vont passer par ce fichier. Pour cela, il faut configurer le serveur Web pour qu'il réoriente toutes les requêtes ne concernant pas un fichier ou un répertoire statique vers index.php. On utilise pour cela un fichier .htaccess pour Apache qu'on place dans le répertoire public.
/public/.htaccess
# Active la réécriture des adresses RewriteEngine On # Si la requête correspond à un fichier standard dont la taille est supérieure à 0 ... RewriteCond %{REQUEST_FILENAME} -s [OR] # ... ou à un lien symbolique RewriteCond %{REQUEST_FILENAME} -l [OR] # ... ou à un répertoire RewriteCond %{REQUEST_FILENAME} -d # ... on laisse la requête tel quelle (le tiret veut dire pas de substitution) # Drapeau NC (No Case) : comparaison insensible à la casse # Drapeau L (Last) : ne pas interpréter les règles suivantes RewriteRule ^.*$ - [NC,L] # Sinon, on redirige vers index.php RewriteRule ^.*$ index.php [NC,L]
Si vous utilisez Nginx à la place d'Apache, vous devrez utiliser la règle de réécriture suivante :
/etc/nginx/nginx.conf
server { [..] if (!-e $request_filename){ rewrite ^(.*)$ /index.php break; } }
Pour faciliter le déploiement ultérieur sur votre serveur de production, il vaut mieux utiliser des urls similaires sur les deux environnements. Au lieu d'accéder à vos pages avec des urls commençant par http://localhost/, on peut utiliser les hôtes virtuels Apache (virtuals hosts) pour obtenir des urls du type : http://votreapp.tld.
Pour ce faire, ouvrez le fichier C:\wamp\bin\apache\ApacheX.X.XX\conf\extra\httpd-vhosts.conf et ajoutez lui les lignes suivantes :
<VirtualHost *:80> DocumentRoot "C:/wamp/www/votreapp/public" ServerName votreapp.tld ServerAlias votreapp.tld *.votreapp.tld </VirtualHost>
Ce code crée un hôte virtuel dans Apache. Lorsque vous appelerez une URL du domaine votreapp.tld, Apache utilisera le chemin C:/wamp/www/votreapp/public comme racine.
Redémarrez Apache, puis éditez le fichier C:\WINDOWS\system32\drivers\etc\hosts. Ajoutez la ligne suivante :
127.0.0.1 votreapp.tld
Le fichier hosts est utilisé par Windows pour convertir les noms d'hôtes en adresses IP. Comme votre domaine votreapp.tld est factice, vous devez le spécifier dans ce fichier pour que Windows puisse associer le domaine à l'adresse IP locale (127.0.0.1). Si vous ne faites pas cette modification, votre navigateur vous indiquera que le site demandé est introuvable.
A quoi corresponds l'extension .tld ?
tld est l'abréviation de Top Level Domain. Le domaine de premier niveau .tld n'est pas utilisé sur Internet, vous pouvez donc l'utiliser en local sans qu'il y ait de confusion avec un domaine existant réellement sur Internet. Consultez Wikipédia pour en savoir plus sur les noms de domaines.
C'est dans ce répertoire que vous allez placer l'essentiel de votre code. Il y a d'abord le fameux fichier bootstrap.php dont nous avons déjà parlé ci-dessus.
/application/bootstrap.php
<?php
require "Zend/Loader.php";
// Installe le chargeur automatique de classes
Zend_Loader::registerAutoload();
// Récupère une instance du contrôleur frontal
$frontController = Zend_Controller_Front::getInstance();
// On n'utilise pas le plugin ErrorController pour l'instant
$frontController->throwException(true);
// On indique l'endroit où sont placés les contrôleurs
$frontController->addControllerDirectory('../application/controllers');
// Demande au contrôleur de traiter la requête
$frontController->dispatch();
?>
On commence par mettre en place le Zend_Loader qui permet de charger automatiquement les classes, à la manière de la fonction __autoload de PHP. Une fois que cet objet est initialisé, vous n'aurez plus besoin d'utiliser des require ou des include pour charger vos classes. Zend_Loader va analyser le nom de la classe demandée et déterminer automatiquement le chemin menant au fichier. Pour la classe Zend_Db_Table par exemple, Zend_Loader va inclure le fichier Zend/Db/Table.php. Vous pouvez même utiliser cette fonctionnalité pour vos propres classes en respectant la convention de nommage et la structure des fichiers.
On récupère ensuite une instance du contrôleur frontal. Il n'existe qu'un seul contrôleur frontal pour l'application, ce qui explique qu'on crée l'objet par l'intermédiaire d'un patron de conception de type Singleton. Le contrôleur frontal est chargé de transmettre la requête aux autres contrôleurs. Pour qu'il puisse fonctionner, on lui indique le dossier dans lequel il pourra trouver ces derniers.
Par défaut, si on ne spécifie aucun paramètre particulier dans l'URL, le contrôleur frontal transmet la requête au contrôleur nommé IndexController et appelle son action nommée indexAction.
/application/controllers/IndexController.php
<?php
class IndexController extends Zend_Controller_Action
{
// L'action par défaut
public function indexAction()
{
}
}
?>
Dans notre application, on ne va pour l'instant traiter aucune donnée. On laisse donc le corps de la méthode vide et on place notre message dans la vue correspondante :
/application/views/scripts/index/index.phtml
<?php
Salut tout le monde !
?>
Si vous ouvrez alors un navigateur avec l'adresse http://localhost/votreapp/public/, vous verrez alors apparaitre la page suivante :
Voilà, vous avez une première application fonctionnelle. Elle ne vas pas changer le monde, mais c'est un début. Il nous reste un peu de travail, car pour l'instant, on a oublié le M du concept MVC : le modèle. Lancez donc PHPMyadmin, créez une base nommée votreapp et exécutez le code SQL suivant :
CREATE TABLE `contacts` ( `id` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY , `prenom` CHAR( 24 ) NOT NULL , `nom` CHAR( 24 ) NOT NULL , `telephone` CHAR( 14 ) NOT NULL ) ENGINE = MYISAM ; INSERT INTO `contacts` ( `id` , `prenom` , `nom` , `téléphone` ) VALUES ( NULL , 'Pierre', 'QUIMOUSSE', '01.02.03.04.05' ), ( NULL , 'Eva', 'NAISSANCE', '01.23.45.67.89' );
Pour notre exemple, on va créer un petit carnet d'adresse. On va donc travailler sur une table nommée contacts avec 4 colonnes : une clé primaire, le prénom, le nom et le numéro de téléphone.
On insère également quelques données.
A présent, on va préparer une connexion à la base de données. J'utilise le terme préparer car la connexion réelle ne se fera que lorsqu'on interrogera réellement la base.
On ajoute donc le code suivant à bootstrap.php, juste derrière la mise en place du Zend_Loader :
/application/bootstrap.php
<?php
[..]
// On prépare une connexion avec le driver PDO MySQL
$db = Zend_Db::factory('pdo_mysql', array(
'host' => 'localhost',
'username' => 'root',
'password' => '',
'dbname' => 'votreapp'
));
// On place l'instance de la connexion dans le registre
Zend_Registry::set('db', $db);
[..]
?>
Ensuite on ajoute le code suivant à la méthode indexAction du contrôleur :
/application/controllers/IndexController.php
<?php
[..]
// Récupération de l'instance de la connexion depuis le registre
$db = Zend_Registry::get('db');
// Création d'un objet de classe Zend_Db_Select
$select = $db->select()->from('contacts');
// Exécution de la requête et récupération des résultats dans un tableau associatif
$this->view->contacts = $select->query()->fetchAll();
[..]
?>
Puis finalement dans la vue :
/application/views/scripts/index/index.phtml
<?php
<html>
<head>
<title>Contacts</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<?php
foreach ($this->contacts as $contact) {
echo "<div><h4>{$contact['prenom']} {$contact['nom']}</h4>\n<p>Tél. : {$contact['telephone']}</p></div>";
}
?>
</body>
</html>
?>
Le résultat final :
Comments
Anonyme
Mon, 20/10/2008 - 23:59
Permalink
petit bug je crois, Fatal
Maxence
Tue, 02/06/2009 - 14:45
Permalink
J'ai pris mon temps pour
J'ai pris mon temps pour répondre (8 mois quand même), mais mieux vaut tard que jamais. Tu as cette erreur car tu n'as pas de contrôleur de gestion d'erreur. Il faut ajouter $frontController->throwException(true); à ton bootstrap (j'ai mis à jour le tutoriel pour inclure cette information).
Polo_metz (not verified)
Wed, 22/07/2009 - 10:45
Permalink
Merci pour ce tuto sympa pour
Merci pour ce tuto sympa pour les débutants.
Juste une précision concernant le Virtual Host.
Cela dépend peut-être des configs, mais pour ma part j'ai du faire un autre modif :
Décommenter la ligne suivante dans le fichier httpd.conf qui se trouve dans C:\wamp\bin\apache\Apache2.2.11\conf
-> #Include conf/extra/httpd-vhosts.conf
Enlever le # !
Autrement le domaine tld me renvoyait à la racine de Wamp (Wamp/www) et pas sur Wapmp/www/monapp/public comme souhaité.
Bon courage à tous
Maxence
Thu, 23/07/2009 - 17:21
Permalink
Oui, avec certaines versions
Oui, avec certaines versions de Wamp, la config des hôtes virtuels est déportée dans des fichiers séparés.
Chris (not verified)
Sun, 02/08/2009 - 16:33
Permalink
La page Index.phtml
La page Index.phtml n'apparait pas.
J'ai remplacé "votreapp" par "monsite".
J'ai tracé les fichiers en mettant un print"Nom du fichier" dans tous les fichiers qui entrent en jeu. Donc quand j'ouvre la page "http://monsite.tld/public", je vois que les fichiers, index.php, bootstrap.php et loader.php sont bien lus. Apparement, le fichier "IndexController.php" n'est pas lu. Avez-vous une idée ?
Sinon merci pour ce tuto !
Maxence
Wed, 05/08/2009 - 08:30
Permalink
Normalement, tu devrais
Normalement, tu devrais accéder à ton site par l'url http://monsite.tld. Le répertoire public doit être la racine de ton hôte virtuel Apache.
Chris (not verified)
Wed, 05/08/2009 - 19:43
Permalink
Oui, j'accède bien à mon site
Oui, j'accède bien à mon site avec l'url http://monsite.tld, mais la page est vierge. Je ne vois pas apparaître "Salut tout le monde".
Aprés quelques recherches, j'ai modifié un paramètre de php.ini. J'ai mis short_open_tag à "on".
Dans mon fichier IndexController.php j'ai mis ceci :
<?php
print("c'est l index controller");
class IndexController extends Zend_Controller_Action
{
// L'action par défaut
public function indexAction()
{
}
}
Pourtant, j'ai toujours une page blanche !
Je ne sais plus dans quelle direction chercher !
Maxence
Thu, 06/08/2009 - 10:25
Permalink
Tu devrais utiliser un
Tu devrais utiliser un débogueur comme (NetBeans + XDebug) pour tracer l'exécution de ton script.
Chris (not verified)
Sat, 08/08/2009 - 12:18
Permalink
J'ai trouvé l'erreur : Quand
J'ai trouvé l'erreur : Quand j'ai installé wamp, j'avais déjà une version de php. Wamp pointait sur celui-là.
Ensuite, j'ai installé la version 1.7.8 de Zend. La version 1.8 ne marchait pas.
Par contre, il y a une petite erreur de frappe dans le tuto. Il faut rajouter un s à throwException comme ci-dessous:
$frontController->throwExceptions(true);
Je vais enfin pouvoir continuer le tuto !
thomas (not verified)
Sun, 28/03/2010 - 16:34
Permalink
Hello, Pour ceux qui comme
Hello, Pour ceux qui comme moi ce retrouve avec un :
"Notice: Zend_Loader::Zend_Loader::registerAutoload is deprecated as of 1.8.0 and will be removed with 2.0.0; use Zend_Loader_Autoloader instead in C:\wamp\www\lib\library\Zend\Loader.php on line 258",
Il faut sur le Bootstrap.php, remplacer :
"require "Zend/Loader.php";
// Installe le chargeur automatique de classes
Zend_Loader::registerAutoload(); "
par :
"require_once 'Zend/Loader/Autoloader.php';
Zend_Loader_Autoloader::autoload('Zend_Loader_Autoloader_Resource');"
Thomas
Anthony (not verified)
Tue, 20/04/2010 - 15:59
Permalink
Bonjour à tous ! Tout
Bonjour à tous !
Tout d'abord, merci pour ce tuto qui m'a fort aidé dans mes travaux. Cependant, j'ai une erreur récurrente qui ressemble à la 1ère qui vous a été soumise. J'ai bien suivi et re-suivi ce tuto, si quelqu'un a une idée sur l'origine de cette erreur, merci de m'en faire part =)
Fatal error: Uncaught exception 'Zend_Controller_Dispatcher_Exception' with message 'Invalid controller specified (index)' in C:\wamp\www\lib\Zend\Controller\Dispatcher\Standard.php:242 Stack trace: #0 C:\wamp\www\lib\Zend\Controller\Front.php(954): Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http), Object(Zend_Controller_Response_Http)) #1 C:\wamp\www\votreapp\application\bootstrap.php(27): Zend_Controller_Front->dispatch() #2 C:\wamp\www\votreapp\public\index.php(2): require('C:\wamp\www\vot...') #3 {main} thrown in C:\wamp\www\lib\Zend\Controller\Dispatcher\Standard.php on line 242
STEPHANE (not verified)
Sun, 10/10/2010 - 23:28
Permalink
Bonjour, mon application
Bonjour,
mon application marche mais j'ai un petit problème d'affichage au niveau des caractères accentués. En effet, j'ai un caractère étrange ( ? ) à la place du "é" de "Tél"...
Savez-vous comment je peux arranger ça SVP ?
Merci d'avance à ceux qui répondront à mon appel !
Stéphane
STEPHANE (not verified)
Mon, 11/10/2010 - 00:03
Permalink
Re bonjour, finalement après
Add new comment