Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP type-hinting to primitive values?

I'd like to know whether one can type-hint a method to expect primitive types?

Something like this:

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

Or:

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

the same way you would:

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

Is that possible in php?

like image 855
Felipe Avatar asked Apr 20 '11 01:04

Felipe


People also ask

Should I use type hinting in PHP?

Apparently 'type hinting' in PHP can be defined as follows: "Type hinting" forces you to only pass objects of a particular type. This prevents you from passing incompatible values, and creates a standard if you're working with a team etc.

Which data types can be declared with type hinting in PHP?

In simple word, type hinting means providing hints to function to only accept the given data type. In technical word we can say that Type Hinting is method by which we can force function to accept the desired data type. In PHP, we can use type hinting for Object, Array and callable data type.

Which data types can be declared with type hinting?

With Type hinting we can specify the expected data type (arrays, objects, interface, etc.) for an argument in a function declaration. This practice can be most advantageous because it results in better code organization and improved error messages.

Which is the right way to type hint a function PHP?

To add a type hint to a parameter, you place a type in front of it like this: <? php function my_function(type $param1, type param2, ...) { // ... }

What is type hinting in PHP?

Scalar type hinting consists of declaring the types of function parameters and return values that can be of the types int, float, string and bool.This allows the PHP runtime engine to check if the types of values passed to parameter functions and return values are of the expected types in order to detect eventual programming mistakes.

What are primitive types and checking functions in PHP?

Let explore PHP primitive types and checking functions. Type determines the way that data can be managed in your scripts. You use the string type to display character data, for example, and manipulate such data with string functions. Integers are used in mathematical expressions; Booleans are used in test expressions, and so on.

What is an integer data type in PHP?

An integer data type is a non-decimal number between -2,147,483,648 and 2,147,483,647. In the following example $x is an integer. The PHP var_dump () function returns the data type and value:

What are primitive data types in programming?

Primitive data types refers to the type of data that can be held in a variable or constant. They are called primitive because the data type is fundamental to the language and cannot be broken down any further. This includes strings of text, numbers, booleans, and more. Let's go over each one and see how they're used.


6 Answers

In PHP 7 they added the following:

Type declarations allow functions to require that parameters are of a certain type at call time. If the given value is of the incorrect type, then an error is generated: in PHP 5, this will be a recoverable fatal error, while PHP 7 will throw a TypeError exception.

Reference: http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration


When this answer was asked, PHP 5 was the latest and said the following:

PHP 5 introduces type hinting. Functions are now able to force parameters to be objects (by specifying the name of the class in the function prototype), interfaces, arrays (since PHP 5.1) or callable (since PHP 5.4). However, if NULL is used as the default parameter value, it will be allowed as an argument for any later call.

If class or interface is specified as type hint then all its children or implementations are allowed too.

Type hints cannot be used with scalar types such as int or string. Resources and Traits are not allowed either.

Reference: http://php.net/manual/en/language.oop5.typehinting.php

like image 77
afuzzyllama Avatar answered Oct 14 '22 14:10

afuzzyllama


Nope. You can't type hint for primitives because PHP has automatic conversions for primitives. See http://bugs.php.net/bug.php?id=29508. This will never change, unless the PHP team has a sudden change of heart (which is doubtful, they're pretty stubborn).

like image 33
Rafe Kettler Avatar answered Oct 14 '22 14:10

Rafe Kettler


Yes, Now its possible, After a long discussion, a proposal to implement type hinting for scalar function parameters and return values was just approved with the highest vote count so far, check for details :

Scalar type hinting consists of declaring the types of function parameters and return values that can be of the types int, float, string and bool.This allows the PHP runtime engine to check if the types of values passed to parameter functions and return values are of the expected types in order to detect eventual programming mistakes. Type hinting for objects, arrays and callables was already allowed in past PHP versions. The current implementation introduces five new reserved words: int, float, bool, string and numeric. These were not previously reserved, because casting is a special case in the 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

You have also an option to declare into source file where you can allow Scaler type hinting.It must be 1st line of your config script and can’t be declared elsewhere in the same file.

Like : declare(strict_types=1);

At runtime, when the PHP engine tries to return a value, it will check if doesn’t match as declared it will throw a fatal error like, Fatal error: Argument 1 passed to increment() must be of the type integer, string given

With this new features of declaration, you can write more robust applications by detecting early programming mistakes caused by passing values of the wrong types to functions.

Automatic changes of types may also happen. For example, int types can be change into float type parameters automatically,

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

Declaring the Return Type

We can declare the return types adding a colon followed by the expected type between the last parenthesis and the first bracket in the function declaration.

For functions that do not return any value, nothing should be added in the return type declaration section.

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

A Little Bit more Complex Example

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");

Behavior of Weak Type Checking and Type Conversion : The weak type checking mode can be used with the statement declare(strict_types=0); or the absence of the strict types declaration. There are a few of points to take into account: Weak type checked calls to an extension or built-in PHP function have the same behaviour as in previous PHP versions The weak type checking rules for new scalar type declarations are mostly the same as those of extension or built-in PHP functions. NULL is a special case in order to be consistent with the current type declarations for classes, callables and arrays. NULL is not accepted by default, unless it is a parameter and is explicitly given a default value of NULL, for instance: function sample(int $a = NULL);

There are a lots of advantages to this approach. You get type safety. Which means that you can finally statically analyze code! You can detect bugs where you accidentally take a string from one function and pass it as an integer to another.For me, a developer that uses PHP on a daily basis and sees Java as a reference for OOP languages, this is great progress for PHP.

like image 24
Purushottam Avatar answered Oct 14 '22 13:10

Purushottam


Everyone already said it, you can't do type hint for primitives because PHP doest not support it. The reason behind this is not only related to automatic conversions but also to community reaction.

So far, I can remember that in May of 2010 support for scalar type hinting was added to the PHP trunk. But because of community response this feature didn't make it into the 5.4 release.

There was a bit of controversy about this. Those who opposed the change argued that this support would go against the fundamental designs of PHP. PHP is considered to be a weak typed language. In essence, this means that PHP does not require you to declare data types. Variables still have data types associated with them but you can do radical things like adding a string to an integer without resulting in an error.

IMHO: Scalar type hinting should be added into PHP ASAP, it's a feature we all need, I really respect that PHP is weak typed language, but for high end development and production, specially on OO contexts, scalar type hinting is a must have. We can have both alternatives in PHP, just like procedural and OO.

like image 23
TCB13 Avatar answered Oct 14 '22 13:10

TCB13


Yes, it is possible.

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

Warning: there is a typo in original manual: resrouce instead of resource

People often ask about scalar/basic typehints. Here is a drop in class that I use in my MVC framework that will enable typehints through the use of a custom error handler.

Note: You should include this code above all other code in your include headers and if you are the using set_error_handler() function you should be aware that this uses it as well. You may need to chain your set_error_handlers()

Why?

  1. Because people are sick of using the is_* functions to validate parameters.
  2. Reduction of redundant coding for defensive coders.
  3. Functions/Methods are self defining/documenting as to required input.

Also.. Follow the discussion for typehints in PHP 6.0 on the PHP Internals boards.

<?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.

?>

You get the picture..

like image 44
Serhii Smirnov Avatar answered Oct 14 '22 14:10

Serhii Smirnov


Accordind to PHP documentation type hinting is not supported for primitive types.

It's supported for classes and interfaces though.

Edit: I forgot to mention that's also supported for arrays.

like image 34
Luc M Avatar answered Oct 14 '22 13:10

Luc M