PHP est le langage de programmation du côté serveur.
Il est souple et mature, dispose d'un nombre impressionnant de bibliothèques de fonctions et est disponible chez tous les hébergeurs.
Il permet la programmation orientée objet, même s'il n'est pas un vrai langage objet comme le Javascript.
Toute la programmation serveur de ce site est en PHP, ainsi que celle de ma bibliothèque HoinP.
Cette bibliothèque, mise dans le domaine public sous licence LGPL, est ma « carte de visite » en matière de programation PHP.
Voir un exemple de classe ci-dessous.
On trouvera d'autres exemples de code au chapitre MVC.
<?php
/*
«Copyright 2007 Max Barel a_x@ac-mb.info»
Release : 0.4 ($Rev: 60 $)
$Date: 2007-11-02 14:56:59 +0100 (Ven, 02 nov 2007) $
This file is part of HoP.
HoP is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
HoP is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with HoP; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
//XHTML element.
class Hop_element extends Hop_node {
const INDENT = "\t"; //define the indentation string
//singleton
protected static $n_el = 0; //element count in the pool added for time optimization
public static $pool; //a "flat" container object for all Hop_elements.
//Use it to direct access to an object : Hop_element::$pool->object_id
//See also the commodity function in Hop class
//mandatory properties values
public $type; //string, element type eg. 'div','p'
public $id; //id of this object, automatic generation if not given
//optional properties
public $attributes = null; //stdclass object: html attributes container
public $auto_id = false; //should 'id' html attribute be reflecting the object id
public $auto_name = false; //should 'name' html attribute be reflecting the object id (eg. for input element)
public $empty_el = false; //is this element type empty (otional empty should be set to false)
public $nl = 1; //newlines when rendering: 0 for inline (e.g. <span>),
// 1 for newline before the opening tag (one line elements: <p> or <legend>),
// 2 for newline before the closing tag (container elements : <body>, <div>)
public static $comment_tag = true; //optional comment at closing tag for readability. Global to the whole rendering
//constructor
function __construct($type, $options = null) {
$this->type = $type; // set the element type
//process options
if (is_string($options)) $options = array('id' => $options); // a string option default to the object id
elseif ($options and !is_object($options)) $options = (object) $options; //cast to object for uniform processing
if (isset($options->content) ) {
//content should be handled by setter for correct parent linking
$this->set_content($options->content);
unset ($options->content);
}
if ($options) foreach ($options as $k => $v) $this->$k = $v; //make other options properies of the element
//if (isset($this->$k))
//cast attributes to object for easy access (might be array or simple string)
if ($this->attributes and !is_object($this->attributes)) $this->attributes = (object) $this->attributes;
// if ($this->attributes and !is_object($this->attributes)) settype($this->attributes, 'object');
//if no id (from options) generate one, for the safeness of the pool. The element will then be difficult to address.
if (!$this->id or !is_string($this->id)) $this->id = $type;
self::$n_el ++;
if (isset(self::$pool->{$this->id})) $this->id = "{$type}_" . self::$n_el;
//add self to the pool
self::$pool->{$this->id} = $this;
}
function __clone() {
parent::__clone(); //called before renaming for easier access by name : $parent->child
self::$n_el ++;
$this->id = "{$this->id}_clone_" . self::$n_el;
self::$pool->{$this->id} = $this;
if ($this->attributes) $this->attributes = clone $this->attributes;
}
protected function set_container($node) {
//redefined to add a reverse link from parent to child through an id named property
parent::set_container($node); //=> $this->container = $node;
// if (is_a($node, __CLASS__))
$node->{$this->id} = $this; //cannot be done at node level becaus nodes have no id
}
function cut() {
unset($this->container->{$this->id});
return parent::cut();
}
//rendering function.
function render($indent = '') {
$html_string = '';
if ($this->auto_id and empty($this->attributes->id) ) $this->set_attr('id', $this->id);
if ($this->auto_name and empty($this->attributes->name) ) $this->set_attr('name', $this->id);
if ($this->nl) $html_string .= "\n$indent";
$html_string .= "<$this->type";
if ($this->attributes) {
//cast in case it has been set to a string
if (!is_object($this->attributes)) $this->attributes = (object) $this->attributes;
foreach ($this->attributes as $k => $value) {
if ($k == 'raw' or $k == 'scalar') $html_string .= " $value"; //for raw formatted attributes
else $html_string .= " $k=\"$value\"";
}
}
if ($this->empty_el) {
$html_string .= ' />';
} else {
$html_string .= '>';
$html_string .= parent::render(self::INDENT . $indent);
if ($this->nl > 1) $html_string .= "\n$indent";
$html_string .= "</$this->type>";
//optional, for code documentation
if ($this->nl > 1 and self::$comment_tag and isset($this->attributes->id)) $html_string .= "<!-- {$this->attributes->id} -->";
}
return $html_string;
}
//properties setter
function auto_id($val=true) { $this->auto_id = $val; return $this; }
function auto_name($val=true) { $this->auto_name = $val; return $this; }
function empty_el($val=true) { $this->empty_el = $val; return $this; }
function nl($val=1) { $this->nl = $val; return $this; }
//commodity function to set an attribute
function set_attr($attr, $value=null) {
$this->attributes->$attr = htmlspecialchars($value); //htmlspecialchars htmlentities
return $this;
}
//commodity function to get an attribute
function get_attr($attr) {
return @$this->attributes->$attr;
}
//remove an attribute
function remove_attr($attr) {
unset ($this->attributes->$attr);
return $this;
}
//generic attibute setter
private function __call($setter, $params) {
if (ereg('(set|get|remove)_(.*)', $setter, $e_res)) {
switch ($e_res[1]) {
case 'set': return $this->set_attr($e_res[2], $params[0]);
case 'get': return $this->get_attr($e_res[2]);
case 'remove': return $this->remove_attr($e_res[2]);
}
}
//shortcut setter: $el->class('a_class') <=> $el->set_class('a_class') <=> $el->set_attr('class', 'a_class')
else return $this->set_attr($setter, $params[0]);
// else throw new Exception("invalide function call : $setter");
}
//specific class methods
public function add_class($class = null) {
if ($class) $this->set_attr('class', (($c = $this->get_attr('class')) ? "$c " : '') . "$class");
return $this;
}
public function remove_class($class = null) {
if ($class) $this->set_attr('class', trim(ereg_replace(" *$class", '', $this->get_attr('class'))));
return $this;
}
}
?>