Bonjour.
Travaillant actuellement sur un projet décrit ci-dessous, je crée ce sujet pour savoir plusieurs choses.
- Tout d'abord qu'en pensez vous de ce projet ? L'idée est-elle intéressante ? Utile ? Allez-vous essayer d'utiliser les fruits de ce projet s'il aboutit un jour ?
- Est-ce qu'il existe déjà des projets similaires ?
- Souhaitez-vous éventuellement collaborer pour ce projet ?
Description générale du projet
Extended Hypertext Preprocessor (EHP) vise à combler un certain nombre de lacunes du PHP, en fournissant un langage avec une syntaxe plus proche du C# ou du Java. Les fichiers écrits dans ce langage peuvent être ensuite transformés en PHP natif pour être déployés sur tout serveur supportant PHP.
Malgré un certain nombre d'avantages, PHP possède de grands inconvénients rendant son utilisation difficile, souvent énervante.
- Les noms des fonctions natives de PHP n'ont aucune consistance : (needle, haystack) ou (haystack, needle), ou some_function(), ou function_some(), ou someFunction(), et sont pour certains mal "decouvrables" (par exemple PHP_EOL ou DIRECTORY_SEPARATOR, qu'il est indispensable d'utiliser à la place de "[\r]\n" ou de "\" ou "/" pour tout projet sérieux, mais que peu de gens utilisent, car ne savent pas que ça existe).
- PHP ne permet pas de typage strict pour un certain nombre de types.
- PHP n'est pas réellement orienté objet.
- PHP n'encourage ni oblige la séparation entre business logic et HTML.
- Les fichiers PHP sont fournis en clair. Les produits permettant d'obscurcir (traduction libre d'obfuscate) le code sont soit de très mauvaise qualité, soit très chers.
- PHP force d'écrire des choses inutiles. Exemple : le mot "function" pour designer une méthode dans une classe.
En revanche, il y a des hypothèses où le site final doit tourner avec PHP (à commencer par le "parce que le client le veut").
Le projet EHP tente de résoudre ces difficultés en apportant une syntaxe différente. Dans l'ordre :
- Les noms des méthodes natives de EHP correspondent à des spécifications clairement déterminées. Pour l'instant, je me suis inspiré du .NET Framework (exemple : String.Replace(inWhat, what, byWhat)), mais d'autres standards peuvent être posés, pourvu que l'ensemble soit cohérent.
- EHP permet le typage fort des arguments. [Le typage des variables est en cours de réflexion].
- [L'ajout des formes d'OOP sont en cours de réflexion.]
- Les fichiers EHP ne peuvent contenir que du code. Il est nettement plus difficile (mais possible) de mélanger EHP et HTML que de passer par des templates.
- Le code PHP natif produit à partir de PHP peut être obscurci si besoin, avec refractoring des noms des variables/méthodes, suppression basique de whitespace et des commentaires, inlining des méthodes si ceci optimise/accélère le code, etc. Un certain nombre d'optimisations est d'ailleurs faite, comme par exemple la possibilité de joindre plusieurs fichiers pour ne former qu'un seul (par exemple chaque page du site utilise forcement vingt classes. Pour la clarté du code, chaque classe va se situer forcement dans un fichier EHP propre, mais les vingt fichiers vont former un seul fichier PHP natif).
- EHP permet de ne pas spécifier les choses suffisamment explicites.
Exemple : le code PHP suivant :
1 2 3 4 5 6 7 8 9
| <?php
public function GetHello($name)
{
$a = 'Hello ' . $name . '!';
return str_replace('e', '', $a);
}
echo GetHello('My name here');
?> |
peut être écrit en EHP ainsi :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| namespace MyCompany.MyGreatApplication
{
// Here my great application classes.
public partial static class MyBusiness
{
// Gets hello string for a user name.
public string GetHello(string $name)
{
$a = String.Concat('Hello ', $name, '!');
return String.Replace($a, 'e', String.Empty);
}
}
// Main class.
public static class WebApplication
{
// Main entry point, called to generate page contents.
public void GetResponse()
{
WebOutput.Write(MyBusiness.GetHello('My name here'));
}
}
} |
et sera transformé en PHP natif (pas destiné à être lu) en mode debug sans inline sous une forme similaire à :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| <?php
require_once('ehp/extensibility.php');
static class MyCompany_MyGreatApplication_a
{
public function a($a)
{
if (!is_string($a)) throw new ArgumentException('source/demo.ehp', 7, 'MyCompany.MyGreatApplication.MyBusiness.GetHello', 'The argument "name" of method GetHello expects string, current type is ' . gettype($a));
$b = 'Hello ' . $name . '!';
$c = str_replace('e', '', $b);
if (!is_null($c) && !is_string($c)) throw new Exception('source/demo.ehp', 10, 'MyCompany.MyGreatApplication.MyBusiness.GetHello', 'The method "GetHello" must return string.');
return $c;
}
}
static class mep
{
public function _mep()
{
$a = MyCompany_MyGreatApplication_a::a('My name here');
if (!is_object($a) || method_exists($a, '__toString'))
{
print_r((string)$a);
}
else
{
throw new ArgumentException('source/demo.ehp', 20, 'MyCompany.MyGreatApplication.WebApplication.GetResponse', 'The argument "text" of method Write expects object convertissable to string. Implement ToString() method in the object passed as argument.');
}
}
}
mep::_mep();
?> |
ou bien en release sans inline sous une forme plus compacte (pour les plus maso), réduisant, si besoin, les messages des exceptions afin d'obscurcir/racourcir davantage le code :
<?php require_once('ehp/extensibility.php');static class MyCompany_MyGreatApplication_a{public function a($a){if(!is_string($a))throw new ArgumentException('source/demo.ehp',7,null,'The argument expects string, current type is '.gettype($a));$b='Hello '.$name.'!';$c=str_replace('e','',$b);if(!is_null($c)&&!is_string($c))throw new Exception('source/demo.ehp', 10, null, 'The method must return string.');return $c;}}static class mep{public function _mep(){$a = MyCompany_MyGreatApplication_a::a('My name here');if(!is_object($a)||method_exists($a,'__toString')){print_r((string)$a);}else{throw new ArgumentException('source/demo.ehp', 20, null, 'The argument expects object convertissable to string. Implement ToString() method in the object passed as argument.');}}}mep::_mep(); ?>
À noter une particularité. L'utilisation d'EHP tend à n'enlever aucune fonctionnalité du PHP natif. Par exemple, si dans un contexte précis le typage strict est inadapté, il est toujours possible de déclarer un type comme étant dynamique (l'analogue de dynamic en .NET 4.0). Un autre exemple, le "debogage" avec les __FILE__ et __LINE__ ne doit pas poser problème, vu que EHP introduit __SOURCEFILE__, __SOURCELINE__ etc. qui seront convertis automatiquement en chaines de caractères ou nombres correspondants au nom du fichier ou le numéro de la ligne lors de la transformation en PHP natif.
Le code est certainement plus long (à la fois le code EHP et le code PHP natif produit).
Composition du projet
Compte tenu des travaux actuels, je comptais aboutir à une composition tripartite suivante.
- Un convertisseur de code EHP vers du PHP natif, c'est-à-dire un exécutable permettant, à partir d'un ou plusieurs fichiers EHP, former un fichier de code brut. [Partiellement fait]
- Une intégration dans Visual Studio. [Bloqué au tout début]
- Une bibliothèque d'extensibilité pour PHP, comportant des méthodes qui n'existent pas en PHP (comme String.IsNullOrEmpty) ou des différentes choses (comme ArgumentException).
Alternatives au projet
Il y avait un certain nombre d'alternatives que j'ai décidé d'écarter.
- Le fait de créer plusieurs assemblies .NET reprenant les fonctions natives de PHP à la manière du .NET (exemple : File.ReadAllText comme alias de file_get_contents), mais juste les noms, sans écrire de code à l'intérieur. Ensuite, tout sera écrit en C#/VB.NET sur la base de ces assemblies, puis converti en PHP natif. Cette solution me parait particulièrement tordue, et ne permettra pas de bénéficier de tous les avantages de la syntaxe de PHP.
- Le fait d'avoir un framework pur PHP reprenant les fonctions natives de PHP à la manière du .NET. L'inconvénient, c'est que ceci ne résout pas tous les problèmes, mais uniquement celui de la consistance des noms des méthodes.
Conclusion
Il s'agit donc à travers ce projet de créer "quelque chose" permettant (du moins c'était l'idée d'origine) d'écrire un code syntaxiquement plus proche à C#/Java.
En revanche, travaillant seul sur le projet, j'ai l'inconvénient de ne pas avoir de points de vue d'autres développeurs, ni de pouvoir accomplir le projet rapidement.
C'est pour ces deux raisons que j'expose ce projet ici, voulant savoir ce que vous en pensez.
Merci à tous les courageux qui ont lu.
Partager