web-dev-qa-db-fra.com

PHP indice de type aux valeurs primitives?

Je voudrais savoir si on peut dactylographier une méthode pour attendre des types primitifs?

Quelque chose comme ça:

public function someMethod(string $str)
                         //^^^^^^

Ou:

private function anotherMethod(int $num)
                             //^^^

de la même manière que vous le feriez:

private function otherMethod(Person $rambo)
                           //^^^^^^

Est-ce possible en php?

70
Felipe Almeida

Dans PHP 7, ils ont ajouté ce qui suit:

Les déclarations de type autorisent les fonctions à exiger que les paramètres soient d'un certain type au moment de l'appel. Si la valeur donnée est de type incorrect, une erreur est générée: dans PHP 5, il s'agira d'une erreur fatale récupérable, tandis que PHP 7 lève une exception TypeError.

Référence: http://php.net/manual/fr/functions.arguments.php#functions.arguments.type-declaration


Lorsque cette réponse a été posée, PHP 5 était la dernière et disait ce qui suit:

PHP 5 introduit les conseils de type. Les fonctions sont maintenant capables de forcer les paramètres être des objets (en spécifiant le nom de la classe dans le prototype de fonction), des interfaces, des tableaux (depuis PHP 5.1) ou appelables (depuis PHP 5.4). Cependant, si NULL est utilisé comme valeur de paramètre par défaut, il sera autorisé comme argument pour tout appel ultérieur.

Si class ou interface est spécifié en tant qu'indicateur de type, tous ses enfants ou implémentations sont également autorisés.

Les indicateurs de type ne peuvent pas être utilisés avec des types scalaires tels que int ou string. Les ressources et les traits ne sont pas autorisés non plus.

Référence: http://php.net/manual/en/language.oop5.typehinting.php

82
afuzzyllama

Nan. Vous ne pouvez pas taper l'indice pour les primitives car PHP dispose de conversions automatiques pour les primitives. Voir http://bugs.php.net/bug.php?id=29508 . Cela ne changera jamais, à moins que l'équipe PHP ne change soudainement de cœur (ce qui est douteux, elle est plutôt têtue).

28
Rafe Kettler

Oui, maintenant c'est possible, Après une longue discussion, une proposition visant à implémenter l'indication de type pour les paramètres de fonction scalaire et les valeurs renvoyées vient d'être approuvée avec le nombre de votes le plus élevé jusqu'à présent, vérifiez les détails: 

Les indications de type scalaire consistent à déclarer les types de paramètres de fonction et à renvoyer des valeurs pouvant être des types int, float, string et bool.Ceci permet au moteur d’exécution PHP de vérifier si les types de valeurs passés au paramètre les fonctions et les valeurs de retour sont des types attendus afin de détecter d'éventuelles erreurs de programmation . Les indications de type pour les objets, les tableaux et les callables étaient déjà autorisées dans le passé PHP versions . L'implémentation actuelle en introduit cinq nouveaux mots réservés: int, float, bool, string et numeric. Celles-ci n'étaient pas réservées auparavant, car le casting est un cas particulier dans le lexer.

Example :
function test(float $a) {
    var_dump($a); 
}

test(1); // float(1)
test("1"); // float(1)
test(1.0); // float(1)
test("1a"); // E_RECOVERABLE_ERROR
test("a"); // E_RECOVERABLE_ERROR
test(""); // E_RECOVERABLE_ERROR
test(1.5); // float(1.5)
test(array()); // E_RECOVERABLE_ERROR
test(new StdClass); // E_RECOVERABLE_ERROR

Vous avez également la possibilité de déclarer dans le fichier source où vous pouvez autoriser les indications de type Scaler. Il doit s'agir de la 1ère ligne de votre script de configuration et ne peut pas être déclaré ailleurs dans le même fichier.

Like : declare(strict_types=1);

Au moment de l'exécution, lorsque le moteur PHP essaie de renvoyer une valeur, il vérifie s'il ne correspond pas à la déclaration. Une erreur fatale, telle que, .__, est renvoyée. Erreur fatale: l'argument 1 transmis à increment () doit être du type entier, chaîne donnée

Avec ces nouvelles fonctionnalités de déclaration, vous pouvez écrire des applications plus robustes en détectant les erreurs de programmation précoces causées par le transfert de valeurs de types incorrects à des fonctions.

Des changements automatiques de types peuvent également se produire. Par exemple, les types int peuvent être modifiés automatiquement en paramètres de type float,

function test(float $x){
    var_dump($x);
}
test(10); // works fine

Déclarer le type de retour

Nous pouvons déclarer les types de retour en ajoutant deux points, suivis du type attendu, entre la dernière parenthèse et le premier crochet de la déclaration de fonction.

Pour les fonctions qui ne renvoient aucune valeur, rien ne doit être ajouté dans la section de déclaration du type de retour.

function mustReturnInt(): int { ... }
function mustReturnString(): string { ... }
function mustReturnBool(): bool { ... }
function mustReturnFloat(): float { ... }
function doesNotReturnAnything() { ... }

Exemple un peu plus complexe

declare(strict_types=1);  
class StrictTypesTestingClass {  
public function returnSameInt(int $value): int {   return $value;  }   
public function returnSameFloat(float $value): float {   return $value;  }  
public function returnSameString(string $value): string {   return $value;  }   
public function returnSameBool(bool $value): bool {   return $value;  } }  
$check = new StrictTypesTestingClass();  // calls that work  print $check->returnSameInt(10); 
print $check->returnSameFloat(10.0); 
print $check->returnSameString("test"); 
print $check->returnSameBool(true) ? 'true' : 'false';  // calls that throw exceptions 
print $check->returnSameInt("10"); 
print $check->returnSameFloat("10.0"); 
print $check->returnSameString(10);
print $check->returnSameBool("true");

Comportement de la vérification de type faible et de la conversion de type: le mode de vérification de type faible peut être utilisé avec l'instruction declare (strict_types = 0); ou l'absence de la déclaration de types stricte. Il existe quelques points à prendre en compte: Les appels de type faible contrôlés à une extension ou à une fonction intégrée PHP ont le même comportement que dans les versions précédentes PHP. .Les règles de vérification de type faible pour les nouvelles déclarations de type scalaire sont généralement les mêmes que celles d’extension ou intégrées PHP functions . NULL est un cas à part afin d’être cohérent avec les déclarations de type actuelles pour les classes, les callables et les tableaux. NULL n'est pas accepté par défaut, sauf s'il s'agit d'un paramètre et si une valeur par défaut de NULL lui est explicitement donnée, par exemple: function sample (int $ a = NULL);

Cette approche présente de nombreux avantages. Vous obtenez le type de sécurité. Ce qui signifie que vous pouvez enfin analyser le code de manière statique! Vous pouvez détecter les bogues qui vous empêchent de prendre une chaîne d’une fonction et de la transmettre sous forme d’entier à une autre. Pour mon compte, un développeur qui utilise PHP et voit dans Java une référence pour OOP langages, c’est un grand progrès pour PHP.

15
Purushottam

Tout le monde l'a déjà dit, vous ne pouvez pas faire un indice de type pour les primitives car PHP ne le supporte pas. La raison derrière cela n'est pas seulement liée aux conversions automatiques, mais également à la réaction de la communauté.

Jusqu'à présent, je me souviens que, en mai 2010, la prise en charge des indications de type scalaire avait été ajoutée à la malle PHP. Mais en raison de la réaction de la communauté, cette fonctionnalité n’a pas été intégrée à la version 5.4.

Il y avait un peu de controverse à ce sujet. Ceux qui se sont opposés au changement ont affirmé que ce soutien irait à l'encontre des conceptions fondamentales de PHP. PHP est considéré comme un langage faiblement typé. En gros, cela signifie que PHP ne vous oblige pas à déclarer les types de données. Les types de données sont toujours associés aux variables, mais vous pouvez effectuer des actions radicales, telles que l’ajout d’une chaîne à un entier, sans générer d’erreur.

IMHO: Des astuces de types scalaires devraient être ajoutées dans PHP dès que possible, c'est une fonctionnalité dont nous avons tous besoin, je respecte vraiment le fait que PHP soit un langage mal typé, mais pour le développement et la production haut de gamme, spécialement dans les contextes OO, l'indication de type scalaire est indispensable. Nous pouvons avoir les deux alternatives en PHP, tout comme procédurale et OO.

5
TCB13

Oui c'est possible.

http://ru2.php.net/manual/ru/language.oop5.typehinting.php#83442

Attention: il y a une faute de frappe dans le manuel d'origine: resro uce au lieu de resou rce

Les gens posent souvent des questions sur les empreintes scalaires/de base. Voici un exemple de classe que j'utilise dans mon framework MVC et qui permettra aux typographes d'utiliser un gestionnaire d'erreurs personnalisé.

Remarque: Vous devez inclure ce code au-dessus de tous les autres codes de vos en-têtes d'inclusion. Si vous utilisez la fonction set_error_handler (), vous devez savoir qu'il l'utilise également. Vous devrez peut-être chaîner votre set_error_handlers ()

Pourquoi?

  1. Parce que les gens en ont assez d’utiliser les fonctions is_ * pour valider les paramètres.
  2. Réduction du codage redondant pour les codeurs défensifs. 
  3. Les fonctions/méthodes sont auto-définissant/documentant quant à la saisie requise.

Aussi .. Suivez la discussion sur les astuces de type dans PHP 6.0 sur les tableaux PHP Internals.

<?php

define('TYPEHINT_PCRE', '/^Argument (\d)+ passed to (?:(\w+)::)?(\w+)\(\) must be an instance of (\w+), (\w+) given/');

class Typehint
{

    private static $Typehints = array(
        'boolean'   => 'is_bool',
        'integer'   => 'is_int',
        'float'     => 'is_float',
        'string'    => 'is_string',
        'resource'  => 'is_resource'
    );

    private function __Constrct() {}

    public static function initializeHandler()
    {

        set_error_handler('Typehint::handleTypehint');

        return TRUE;
    }

    private static function getTypehintedArgument($ThBackTrace, $ThFunction, $ThArgIndex, &$ThArgValue)
    {

        foreach ($ThBackTrace as $ThTrace)
        {

            // Match the function; Note we could do more defensive error checking.
            if (isset($ThTrace['function']) && $ThTrace['function'] == $ThFunction)
            {

                $ThArgValue = $ThTrace['args'][$ThArgIndex - 1];

                return TRUE;
            }
        }

        return FALSE;
    }

    public static function handleTypehint($ErrLevel, $ErrMessage)
    {

        if ($ErrLevel == E_RECOVERABLE_ERROR)
        {

            if (preg_match(TYPEHINT_PCRE, $ErrMessage, $ErrMatches))
            {

                list($ErrMatch, $ThArgIndex, $ThClass, $ThFunction, $ThHint, $ThType) = $ErrMatches;

                if (isset(self::$Typehints[$ThHint]))
                {

                    $ThBacktrace = debug_backtrace();
                    $ThArgValue  = NULL;

                    if (self::getTypehintedArgument($ThBacktrace, $ThFunction, $ThArgIndex, $ThArgValue))
                    {

                        if (call_user_func(self::$Typehints[$ThHint], $ThArgValue))
                        {

                            return TRUE;
                        }
                    }
                }
            }
        }

        return FALSE;
    }
}

Typehint::initializeHandler();

?>

An are some examples of the class in use:

<?php

function teststring(string $string) { echo $string; }
function testinteger(integer $integer) { echo $integer; }
function testfloat(float $float) { echo $float; }

// This will work for class methods as well.

?>

Vous obtenez l'image ..

3
Sergii Smirnov

Selon la documentation PHP les indicateurs de type ne sont pas pris en charge pour les types primitifs.

Il est cependant supporté pour les classes et les interfaces.

Edit: j'ai oublié de mentionner qu'il est également pris en charge pour les tableaux.

1
Luc M

Voici une courte syntaxe pour forcer une valeur booléenne à sortir d'un paramètre passé. Si $state est vrai, alors $this->is_active est défini sur true. Pour tous les autres types de valeurs, il est défini sur false.

function set_active ( $state ) {
    $this->is_active = true === $state;
}
0
Lee Blue