déclarer le type des variables (edit)

Mammouth du PHP | 514 Messages

31 oct. 2006, 15:43

Question toute simple, j'imagine ...

Je ne déclare jamais le type de mes variables, puisque php le trouve de lui même.

Mais là ça m'prend, j'aimerais bien les typer manuellement. Ca se fait, à mon avis.

Mais comment ?

(en l'occurence, c'est pour les propriétés d'une classe).
Ne jamais repousser à demain ce qu'on peut faire après demain ...

ViPHP
ViPHP | 3607 Messages

31 oct. 2006, 17:27

pour tout ce qui est du typage des caractères, tu peux faire comme ceci:
$var=(int) "2";
echo gettype($var);//affiche int;
en remplaçant int par le type de variable que tu veux...
tu as aussi des fonctions dédiées à ce type de tâches, comme intval() ou strval()...
ensuite, pour des tests, tu as pleins de fonctions du type: is_TYPE(),
où TYPE est un type tel que int, array, bool, et bien d'autres...
un petit exemple:
$var="2";
echo is_string($var);//affiche true
echo is_int($var);//affiche false
echo is_int((int)$var);//affiche true
echo is_int(intval($var));//affiche true
voilà en espérant que ça t'ai servi... :wink:

Mammouth du PHP | 19672 Messages

31 oct. 2006, 19:04

J'ajouterais qu'en fait, le seul endroit où tu pourrais typer des variables, ce serait dans les arguments de fonctions, mais tu ne pourras pas typer les propriété à l'exception des tableaux. Par exemple :
<?php
class maClasse
{
    /**
     * Enter description here...
     *
     * @var Int
     */
    private $unNombre;
    /**
     * Enter description here...
     *
     * @var String
     */
    private $uneChaine;
    /**
     * Enter description here...
     *
     * @var Array
     */
    private $unTableau = array();
    
    /**
     * Enter description here...
     *
     * @param Int    $Nombre
     * @param String $Chaine
     * @param array  $Tableau
     */
    public function mafonction(Int $Nombre, String $Chaine, Array $Tableau)
    {
        $this->unNombre  = $Nombre;
        $this->uneChaine = $Chaine;
        $this->unTableau = $Tableau;
    }
}
?>
Ceci dit, je ne suis pas certain que ça t'empècherait d'envoyer une chaîne dans une variable attendant un tableau ou un entier dans une attendant un tableau :-k

Je saisis mal le but poursuivi de vouloir se priver de la souplesse qu'offre le faible typage de PHP.

Par exemple, tu pourrais avoir une fonction qui attend un argument dont le type sera testé pour faire appel à une méthode de traitement appropriée selon le type avant de retourner un résultat.
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

31 oct. 2006, 19:11

Pour précision, il me semble qu'il n'est pas possible de typer des variables en PHP. C'est l'une des bases du langage.

Celà comporte des inconvénient (obligation de vérifier le type, ...) mais également des avantages (une variable peut contenir plusieurs types de variables, ...)

Une solution élégante est de ne passer que par des accesseurs/mutateurs qui vérifient la validité du type ...
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

Mammouth du PHP | 983 Messages

01 nov. 2006, 00:29

Pour précision, il me semble qu'il n'est pas possible de typer des variables en PHP. C'est l'une des bases du langage.

Celà comporte des inconvénient (obligation de vérifier le type, ...) mais également des avantages (une variable peut contenir plusieurs types de variables, ...)

Une solution élégante est de ne passer que par des accesseurs/mutateurs qui vérifient la validité du type ...
Pas tout à fait zeus ;)
PHP est permissif et permet de ne pas typer les variables. MAis il est tout à fait possible de les typer (via settype() ).
Dans le cas d'une classe, tu peux utiliser le "type hinting" (je ne vois pas la traduction francaise..) comme te l'as expliqué cyrano.

C'est assez pratique quand les propriétés de ta classe sont elles-mêmes des objets ou des tableaux.
Cependant, plusieurs inconvénients :
- si tu passes un objet null, une exception est levée
- seuls les types array et les classes sont reconnues.

Autrement, mets toutes tes propriétés private ou protected afin d'obliger à passer par des setters. Dans ces setters, tu transtype à ton goût. Voici comment je procède :
<?php

class UserGroup {}
class Toto
{
	/**
	 * Nom du toto
	 * @var string
	 */
	private $_nom = null;
	
	/**
	 * Age du toto
	 * @var int
	 */
	private $_age = null;
	
	/**
	 * Groupe du toto
	 * @varUserGroup
	 */
	private $_group = null;
	/**
	 * @return string le nom du toto
	 */
	public function getNom()
	{
		return $this->_nom;
	}
	
	/**
	 * @param string $nom
	 */
	public function setNom($nom)
	{
		self::checkType($nom);
		$this->_nom = $nom;
	}
	/**
	 * @return int
	 */
	public function getAge()
	{
		return $this->_age;
	}
	
	/**
	 * @return UserGroup
	 */
	public function getGroup()
	{
		return $this->_group;
	
	}
	
	/**
	 * @param UserGroup $group
	  */
	public function setGroup($group)
	{
		self::checkClass($group, 'UserGroup');
		$this->_group = $group;
	}
	/**
	 * @param int $age
	 */
	public function setAge($age)
	{
		self::checkType($nom,'int');
		$this->age = $age;
	}
	
	/**
	 * Méthode utilitaire à mettre dans une autre classe pour la factoriser
	 *
	  * @param mixed @var variable dont on doit vérifier le type
	 * @param string $type type de la variable 
	 * 
	 * @throws InvalidArgumentException
	 */
	public static function checkType($var, $type = 'string')
	{
		if(gettype($var) !== $type)
		{
			//type non attentu, on leve une exception
			throw new InvalidArgumentException("Argument de type $type attendu");
		}
	}
	
	/**
	 * Méthode utilitaire à mettre dans une autre classe pour la factoriser
	 *
	 * @param mixed $var variable dont ondoit vérifier la classe
	 * @param string $class la classe de la variable
	 * @param bool $nullAlloed null est-il permis?
	 *
	 * @throws InvalidArgumentException
	 */
	public static function checkClass($var, $class, $nullAllowed = true)
	{
		if( !$nullAllowed && is_null($var) )
		{
			throw new InvalidArgumentException("Argument null interdit");
		}
		elseif(!is_object($var) || !($var instanceof $class) )
		{
			//classe non attendue, on leve une exception
			throw new InvalidArgumentException("Argument de la classe $class attendu");
		}
	}
}

C'est assez contraigant mais oblige le développeur final à respecter le contrat des méthodes.

Autrement, tu peux transtyper les arguments ainsi :
<?php

class UserGroup {}
class Toto
{
	/**
	 * Nom du toto
	 * @var string
	 */
	private $_nom = null;
	
	/**
	 * Age du toto
	 * @var int
	 */
	private $_age = null;
	
	/**
	 * Groupe du toto
	 * @varUserGroup
	 */
	private $_group = null;
	/**
	 * @return string le nom du toto
	 */
	public function getNom()
	{
		return $this->_nom;
	}
	
	/**
	 * @param string $nom
	 */
	public function setNom($nom)
	{
		$this->_nom = (string)$nom;
	}
	/**
	 * @return int
	 */
	public function getAge()
	{
		return $this->_age;
	}
	
	/**
	 * @return UserGroup
	 */
	public function getGroup()
	{
		return $this->_group;
	
	}
	
	/**
	 * @param UserGroup $group null n'est pas permis à cause du type hinting
	  */
	public function setGroup(UserGroup $group)
	{
		$this->_group = $group;
	}
	/**
	 * @param int $age
	 */
	public function setAge($age)
	{
		$this->age = (int)$age;
	}
}
Il reste le problème des objets composants qui ne pourront être null. Si tu n'utilisaes pas du tout le type hinting, tu ne peux pas savoir si l'argument passé est bien null ou de la classe attendue, il faut donc passer par une méthode qui le vérifie...

Je te renvoie sur http://www.derickrethans.nl/typehints_f ... _types.php , où Derick Rethans explique son patch pour autoriser le type hinting sur les types scalaires.
Patch que j'aimerais bien voir inclus par défaut dans les prochaines builds de PHP...

Mammouth du PHP | 514 Messages

02 nov. 2006, 10:33

Désolé pour le retard, je n'avais pas d'accès internet avant aujourd'hui.

Je m'étais laissé dire que, question performances, on pourrait y gagner un peu.

Merci de vos réponses, je vais voir ce que je peux en faire.
Ne jamais repousser à demain ce qu'on peut faire après demain ...