PHP strict type of variables [duplicate] - php

For example, is it possible to write code like this:
int $x = 6;
str $y = "hello world";
bool $z = false;
MyObject $foo = new MyObject();
And is it possible to define functions like this:
public int function getBalance()
{
return 555; //Or any numeric value
}

In PHP 7 are implemented "Scalar Type Declarations", e.g.:
public function getBalance(): int {
return 555;
}
You need to declare, that you will use strict types:
<?php
declare(strict_types=1);
function sum(int $a, int $b): int {
return $a + $b;
}
sum(1, 2);
?>
More information: https://wiki.php.net/rfc/scalar_type_hints_v5

Edit: This answer applies to versions of PHP 5.6 and earlier. As noted in recent answers, PHP version 7.0 and later does have some support for this
Original answer:
No. There is only support for type hinting since php5, but "Type Hints can only be of the object and array (since PHP 5.1) type. Traditional type hinting with int and string isn't supported."
In PHP 7 are implemented "Scalar Type Declarations" see the answer below.
That is as far as php currently goes, and as far as it should go if you ask me.

PHP is not strictly typed, so no. That said, it does support limited type hinting on functions - that's as close as it gets.

Unfortunately NO! I am at the end of a big project now that involves a lot alogorithms (graph theory, circuits etc) and I wish I hadn't choose php.
I have been using php for about 10 years, and still believe it is a good language, however one have to decide! What is bad for me, lack of strict typing might be good for someone else.
In addition, I want to mention, that I often wrote extra code for supporting strict typing, just a plain example is this:
if (is_array($r) && count($r)===0)
and the errors and hidden situations etc that were revealed are beyond explanation.
There were mistakes and situations that I would never been able to think/detect apriori, writing all these extra code was not enjoying but at least it will save me from silly mistakes!
If I would go back, maybe I would chose php for the web part, you know getting and showing data to the user, php is just great for that, handling string, arrays, talking to the database etc etc, but for the main core, algorithms etc I would go for C++, maybe haskell.. don't know, at least something strictly typed.

Something you might try in order to simulate a poor man's strict type checking is using assert() to force the output to be of a particular type before you return it:
/**
* Get Balance
*
* #return int
*/
function getBalance()
{
/* blah blah blah */
$out = 555; //Or any numeric value
assert('is_int($out)');
return $out;
}
So you keep your assertions active all throughout development and testing, sort of like the checks the compiler does at compile-time.
Granted, the assert() page is keen to assert that you shouldn't use assertions to check input parameters, but rather use normal conditionals to check them.
This answer had what I thought was a good rule:
The rule of thumb which is applicable across most languages (all that I vaguely know) is that an assert is used to assert that a condition is always true whereas an if is appropriate if it is conceivable that it will sometimes fail.
If you're simulating strict type-checking (writing your code to viciously maintain types; not trying to validate input from the outside), then you ought to be certain what the type is unless you've made a mistake.
Update:
There's also this: http://hacklang.org/
Facebook's PHP-based language with static typing.

Perhaps you should try this PHP extension https://github.com/krakjoe/strict. Support for the following types is introduced:
string
integer, int
float, double
boolean, bool
resource

You could use h2tp transpiler to transpile HACK code to PHP:
You can do this thanks to Facebook Team and HACK Language.
Visit http://hacklang.org and http://hhvm.com for more info.
If you want to code directly in Hack + HHVM environment you can also use Facebook's internal IDE Nuclide

Since the answer is basically "no", an alternative: A PHP "linter", which should catch some of the things a compile-time check would catch in a staticly-typed language like C. Not the same, but should prevent some sillyness
"Is there a static code analyzer [like Lint] for PHP files" lists many of these.

PHP 7.0 introduced function return type hints, and PHP 7.4 added support for class property type hints. As of PHP 7.4, your code would be:
<?php declare(strict_types=1);
class MyObject
{
}
class TypedStuff
{
public static int $x;
public static string $y;
public static bool $z;
public static MyObject $foo;
}
function getBalance(): float
{
return 555; //Or any numeric value
}
TypedStuff::$x = 6;
TypedStuff::$y = "hello world";
TypedStuff::$z = false;
TypedStuff::$foo = new MyObject();
You can't type-hint one-off variables, but you can type-hint static class properties, which could be used in an almost identical manner. You can also type-hint the return type of stand-alone functions.
More commonly, you'd be defining typed values inside a class using a typed setter, and receiving typed values outside a class using a typed getter, like:
<?php declare(strict_types=1);
class Person {
private $age;
public function __construct(int $age)
{
$this->age = $age;
}
public function setAge(int $age): void { $this->age = $age; }
public function getAge(): int { return $this->age; }
}
$person = new Person(30);
echo sprintf(
'The person is %d years old.',
$person->getAge()
);
This works in PHP 7.0 because property type-hints are not required.

No. That syntax will not work.
You could, theoretically, come up with a system of objects that enforced their own sort of strict typing, but it wouldn't perform and ...why would you want to, anyway?
If you need strict typing, use a strictly typed language.

Related

PHP 7.1 - Why no warning on void return value?

The PHP manual notes this in its overview of the new void return type added in PHP 7.1:
Attempting to use a void function's return value simply evaluates to NULL, with no warnings emitted. The reason for this is because warnings would implicate the use of generic higher order functions.
What does it mean by "warnings would implicate the use of higher order functions"?
A higher order function (HOF) is a function that follows at least one of the following conditions −
Takes one or more functions as arguments
Returns a function as its result
source
And then From the PHP Void RFC:
Since return; and return null; are technically equivalent in PHP; when a return value isn't specified, PHP will produce null for you. However, choosing one over the other suggests intent. If you specify a value, it suggests the value is significant. In a void function, the return value is insignificant: it's always the same and has no actual usefulness. Specifying it explicitly with return null; is pointless, because it doesn't really matter what value the function is going to return.
(My highlights)
Therefore there's simply no need to provide a warning and it would simply require the usage of another function and additional significant compile-time overhead to notify a return error on a piece of code that is deliberately intended not to return.
Think of it like this:
I will keep lots of sponges on standby just incase the empty milk carton gets knocked over.
The carton will always be empty by intention so there's no need for going down the shop and buying 12 super absorbant sponges!
To view exactly which functions would be called, try exploring the (open source) compile-time error handling logic of PHP 7; to see what functions will be called to process a function that causes a similar error (such as returning an unrecognised or incorrect type).
These functions will be the ones that are not called by silently returning null instead of an error on PHP 7.1 intended void return types.
The problem are cases like these:
class Forwarder {
public $obj; // Some object
public function __call($method, $args) {
return $this->obj->$method(...$args);
}
}
class Obj {
public function returnsVal(): int { return 42; }
public function returnsVoid(): void { return; }
}
$fwd = new Forwarder;
$fwd->obj = new Obj;
// We want both of these calls to work
$val = $fwd->returnsVal();
$fwd->returnsVoid();
This code can handle both void and non-void functions. If using the return value of a void function would warn, then we wouldn't be able to write this code and would have to do something like this instead:
class Forwarder {
public $obj; // Some object
public function __call($method, $args) {
if (returns_void($this->obj, $method)) {
$this->obj->$method(...$args);
} else {
return $this->obj->$method(...$args);
}
}
}
That's a lot of unnecessary boilerplate, not to mention that ''returns_void'' would have to be implemented using expensive reflection calls.
As an addendum to Martin's answer, I believe that the following section from the Void RFC is also useful in clarifying the issue:
Use of void functions in expressions
In some other languages, such as C, a void function can't be used in an expression, only as a statement. Since this RFC adds a way to specify a void function to PHP's syntax, it might be expected the same restriction would now apply in PHP. However, this wouldn't match precedent. PHP has had 'void functions' of a kind since its inception, in the form of built-in functions, which are documented as “void” in the manual. Such functions can be used in expressions, unlike in C.
We could change PHP's rules on void functions and disallow their use in expressions, but this would create a backwards-compatibility issue: it's not inconceivable that existing PHP code relies on being able to call built-in void functions in expressions, and plenty of code assumes that you can take the return value of an arbitrary PHP function (a callback, perhaps).
Moreover, IDEs and other tools can warn the user when the return value of a void function is being used. It isn't strictly necessary for the language itself to cover this.
https://wiki.php.net/rfc/void_return_type#use_of_void_functions_in_expressions
TL;DR
PHP already had void builtins that were allowed to be used in expressions, and changing that now would be a big BC break.

PHP Should all functions check their parameter types first?

I've built up a collection of string functions that do various things and I've noticed that I don't actually have any internal function checks that make sure the variable is a string before something is done with it.
So on a few occasions during development I've accidentally passed something other than a string resulting in an error.
Now, I'm wondering if this is this something I should be doing all the time. First checking to make sure the correct type of data has been sent/check for things that could potentially go wrong first, log them in some way, then if all is okay, do something with it.
Is this something I should be sticking to?
You can see this is a somewhat debatable topic. This is my take:
Type Hinting
Use type hinting when possible. Type hints are not possible in PHP for primitive types, so yes, you should check to ensure you've received valid arguments. If you have not, your function can throw an Exception or return some default value like null or false.
Defensive Programming
The idea of writing testable code is that failures are not silent or mysterious. There's no reason to avoid explicit argument validation: be verbose and your code is more clear and usable.
On top of validating your arguments, you can implement an error handler to catch the edge cases. But you should be validating most arguments, especially if they have an effect on persistent data (like your database).
Murphy's Law is in full effect, therefore you must contend with as many predictable bugs as you can. An invalid argument is an easily predictable bug -- failure to validate it is a timebomb in your code. Calling is_string, for example, is easy and diffuses the bomb.
Boxing
Another consideration is to "box" your variables. This leads to very verbose code, but it does have the advantage of allowing type hints for primitives.
I've never seen anyone actually do this though their entire codebase, but it is out there. There are SPL classes available for primative types, so you'd wind up like this:
function stringThing (\SplString $myString) { ... }
stringThing(new \SplString('This is my string'));
SplTypes enforce the primitive type and throw exceptions when it is misused. From the documentation:
$string = new SplString("Testing");
try {
$string = array(); // <----------this will throw an exception
} catch (UnexpectedValueException $uve) {
echo $uve->getMessage() . PHP_EOL;
}
SplTypes is a PECL extension, and not always a part of a standard PHP install, so check your extensions before using it. The extension is also considered experimental, though it has been in around for some time now.
You can also create your own box fairly simply:
class myStringBox {
private $string = '';
public function __construct($string=null) {
if ($string)
$this->set($string);
}
public function set($val) {
if (!is_string($string)) throw new \InvalidArgumentException();
$this->string= $val;
}
public function __toString() {
return $this->string;
}
public function trim() { return trim($this->string); } // extend with functions?
}
... but this has a major functional difference in that you cannot directly set a new string value like this:
$stringBox = new myStringBox('hello world! ');
echo $stringBox; // "hello world![space]"
echo $stringBox->trim(); // "hello world!"
$stringBox = 'A new string';
echo $stringBox->trim(); // Error: Call to a member function trim() on a non-object
Instead, you have to use a setter method:
$stringBox = new myStringBox('hello world! ');
echo $stringBox; // "hello world![space]"
echo $stringBox->trim(); // "hello world!"
$stringBox->set('A new world');
echo $stringBox->trim(); // "A new world"
This all leads us back to type hinting, which is probably the most efficient way to NOT have to validate your arguments.
Related Reading
Spl types - http://www.php.net/manual/en/book.spl-types.php
Type hinting in PHP - http://php.net/manual/en/language.oop5.typehinting.php
Defensive programming - http://en.wikipedia.org/wiki/Defensive_programming
Currently, PHP doesn't have type hinting for scalars, this was planned for PHP 5.4 but was removed due to the dynamic nature of PHP variables.
A PHP RFC request is now open and it's a planned feature for PHP 6
https://wiki.php.net/rfc/scalar_type_hinting_with_cast
Some workarounds are available:
The set_error_handler method:
Described at: http://edorian.github.io/2010-03-30-typehints-hack-for-literal-values-in-php/
function typehint($level, $message) {
if($level == E_RECOVERABLE_ERROR && preg_match(
'/^Argument (\d)+ passed to (?:(\w+)::)?(\w+)\(\) must be an instance of (\w+), (\w+) given/', $message, $match)
) {
if($match[4] == $match[5]) {
return true;
}
}
return false;
}
set_error_handler("typehint");
PHPTypeSafe method
Another workaround is PHPTypeSafe. This is an old library for 5.3, but a definite slowdown on the PHP execution:
class Foo
{
public static function bar(string $msg, int $counter)
{
echo "$counter. run: $msg\n\n";
}
}
$postCount = 0;
Foo::bar('test', ++$postCount);
echo "The next run will result in an an ErrorException: \n\n";
Foo::bar(false, ++$postCount);
You can read the full example at:
https://github.com/max-horvath/PHPTypeSafe/blob/master/src/examples/php/com/maxhorvath/phptypesafe/SimpleExample.php
SPL Types method
This is the most standard and recomended method, the problem is that you must wrap your variables with objects. This is part of the SPL extension: http://www.php.net/manual/en/book.spl-types.php
This is a little example:
function myFunction(SplInt $int) {
//foo
}
$int = new SplInt(94);
myFunction($int);
You can find a more extensive info about SPL Types at Chris answer
For the sake of completeness: Some time ago, Ms. Sara Golemon, one of the best PHP contributors, tried to make autoboxing for scalar variables similar to SPL Types. It's a little extension in a very alpha state:
https://github.com/sgolemon/objectifier
Regards
In the absense of real type hinting for scalar variables, you can use doc-comments for it. If you use a decent IDE, you'll get reasonable type warnings from the IDE; even if PHP itself doesn't enforce them, that's usually enough to stop you making any howlers.
For example:
/**
* #param int custID
*/
function loadCustomer($custID) {
....
}
Given the above, a decent IDE will give you code completion/type hints for the argument as if it was constrained as an integer. It won't completely stop you from passing a string, by mistake, but if it knows that you're passing the wrong type, it will warn you.
No, except for edge cases, you do not.
I suggest you use http://php.net/manual/en/class.errorexception.php instead of the default PHP error handler. ErrorException will stop script execution even in case of notice.
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}
set_error_handler("exception_error_handler");
I prefer this approach because it allows to catch all unxepected cases in the long term and write the appropriate condition to handle them.
I'd suggest accepting all user input into your functions and casting the parameters to strings (to be sure) wherever an error would occur otherwise. There's really no reason to not, for example, call one of the functions with an int and have it treated using its string representation.
function foo($bar) {
$str = (string)$bar;
return strlen($str);
}
This will even work on classes that implement the __toString() method..
use is_string() validation for function params

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?
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
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).
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.
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.
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?
Because people are sick of using the is_* functions to validate parameters.
Reduction of redundant coding for defensive coders.
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..
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.
Here is short syntax for forcing a boolean value out of a passed in parameter. If $state is true, then $this->is_active is set to true. For all other types of values it is set to false.
function set_active ( $state ) {
$this->is_active = true === $state;
}
I guess you don't need type hinting for PHP because you're given type checking functions such as is_bool(), is_string() etc etc, so you could check whatever your trying to put into an argument against these functions before actually making it an argument, although the method they use to check array and object types would be much cleaner.

Is it possible to write strictly typed PHP code?

For example, is it possible to write code like this:
int $x = 6;
str $y = "hello world";
bool $z = false;
MyObject $foo = new MyObject();
And is it possible to define functions like this:
public int function getBalance()
{
return 555; //Or any numeric value
}
In PHP 7 are implemented "Scalar Type Declarations", e.g.:
public function getBalance(): int {
return 555;
}
You need to declare, that you will use strict types:
<?php
declare(strict_types=1);
function sum(int $a, int $b): int {
return $a + $b;
}
sum(1, 2);
?>
More information: https://wiki.php.net/rfc/scalar_type_hints_v5
Edit: This answer applies to versions of PHP 5.6 and earlier. As noted in recent answers, PHP version 7.0 and later does have some support for this
Original answer:
No. There is only support for type hinting since php5, but "Type Hints can only be of the object and array (since PHP 5.1) type. Traditional type hinting with int and string isn't supported."
In PHP 7 are implemented "Scalar Type Declarations" see the answer below.
That is as far as php currently goes, and as far as it should go if you ask me.
PHP is not strictly typed, so no. That said, it does support limited type hinting on functions - that's as close as it gets.
Unfortunately NO! I am at the end of a big project now that involves a lot alogorithms (graph theory, circuits etc) and I wish I hadn't choose php.
I have been using php for about 10 years, and still believe it is a good language, however one have to decide! What is bad for me, lack of strict typing might be good for someone else.
In addition, I want to mention, that I often wrote extra code for supporting strict typing, just a plain example is this:
if (is_array($r) && count($r)===0)
and the errors and hidden situations etc that were revealed are beyond explanation.
There were mistakes and situations that I would never been able to think/detect apriori, writing all these extra code was not enjoying but at least it will save me from silly mistakes!
If I would go back, maybe I would chose php for the web part, you know getting and showing data to the user, php is just great for that, handling string, arrays, talking to the database etc etc, but for the main core, algorithms etc I would go for C++, maybe haskell.. don't know, at least something strictly typed.
Something you might try in order to simulate a poor man's strict type checking is using assert() to force the output to be of a particular type before you return it:
/**
* Get Balance
*
* #return int
*/
function getBalance()
{
/* blah blah blah */
$out = 555; //Or any numeric value
assert('is_int($out)');
return $out;
}
So you keep your assertions active all throughout development and testing, sort of like the checks the compiler does at compile-time.
Granted, the assert() page is keen to assert that you shouldn't use assertions to check input parameters, but rather use normal conditionals to check them.
This answer had what I thought was a good rule:
The rule of thumb which is applicable across most languages (all that I vaguely know) is that an assert is used to assert that a condition is always true whereas an if is appropriate if it is conceivable that it will sometimes fail.
If you're simulating strict type-checking (writing your code to viciously maintain types; not trying to validate input from the outside), then you ought to be certain what the type is unless you've made a mistake.
Update:
There's also this: http://hacklang.org/
Facebook's PHP-based language with static typing.
Perhaps you should try this PHP extension https://github.com/krakjoe/strict. Support for the following types is introduced:
string
integer, int
float, double
boolean, bool
resource
You could use h2tp transpiler to transpile HACK code to PHP:
You can do this thanks to Facebook Team and HACK Language.
Visit http://hacklang.org and http://hhvm.com for more info.
If you want to code directly in Hack + HHVM environment you can also use Facebook's internal IDE Nuclide
Since the answer is basically "no", an alternative: A PHP "linter", which should catch some of the things a compile-time check would catch in a staticly-typed language like C. Not the same, but should prevent some sillyness
"Is there a static code analyzer [like Lint] for PHP files" lists many of these.
PHP 7.0 introduced function return type hints, and PHP 7.4 added support for class property type hints. As of PHP 7.4, your code would be:
<?php declare(strict_types=1);
class MyObject
{
}
class TypedStuff
{
public static int $x;
public static string $y;
public static bool $z;
public static MyObject $foo;
}
function getBalance(): float
{
return 555; //Or any numeric value
}
TypedStuff::$x = 6;
TypedStuff::$y = "hello world";
TypedStuff::$z = false;
TypedStuff::$foo = new MyObject();
You can't type-hint one-off variables, but you can type-hint static class properties, which could be used in an almost identical manner. You can also type-hint the return type of stand-alone functions.
More commonly, you'd be defining typed values inside a class using a typed setter, and receiving typed values outside a class using a typed getter, like:
<?php declare(strict_types=1);
class Person {
private $age;
public function __construct(int $age)
{
$this->age = $age;
}
public function setAge(int $age): void { $this->age = $age; }
public function getAge(): int { return $this->age; }
}
$person = new Person(30);
echo sprintf(
'The person is %d years old.',
$person->getAge()
);
This works in PHP 7.0 because property type-hints are not required.
No. That syntax will not work.
You could, theoretically, come up with a system of objects that enforced their own sort of strict typing, but it wouldn't perform and ...why would you want to, anyway?
If you need strict typing, use a strictly typed language.

Implicit Type Conversion for PHP Classes?

Is there a way to tell the php complier that I want a specific implicit conversion from one type to another?
A simple example:
class Integer
{
public $val;
}
function ExampleFunc(Interger $i){...}
ExamFunc(333); // 333 -> Integer object with $val == 333.
[edit]... someone asked for an example. Here's an example from c#. This is a boolean type that changes value after it has been accessed once.
/// <summary>
/// A Heisenberg style boolean that changes after it has been read. Defaults to false.
/// </summary>
public class hbool
{
private bool value;
private bool changed = false;
public hbool()
{
value = false;
}
public hbool(bool value)
{
this.value = value;
}
public static implicit operator bool(hbool item)
{
return item.Value;
}
public static implicit operator hbool(bool item)
{
return new hbool(item);
}
public bool Value
{
get
{
if (!changed)
{
value = !value;
changed = true;
return !value;
}
return value;
}
}
public void TouchValue()
{
bool value1 = Value;
}
public static hbool False
{
get { return new hbool(); }
}
public static hbool True
{
get { return new hbool(true); }
}
}
[Test]
public void hboolShouldChangeAfterRead()
{
hbool b = false;
Assert.IsFalse(b);
Assert.IsTrue(b);
Assert.IsTrue(b);
hbool b1 = false;
Assert.IsFalse(b1);
Assert.IsTrue(b1);
Assert.IsTrue(b1);
hbool b2 = true;
Assert.IsTrue(b2);
Assert.IsFalse(b2);
Assert.IsFalse(b2);
bool b3 = new hbool();
Assert.IsFalse(b3);
Assert.IsFalse(b3);
Assert.IsFalse(b3);
}
PHP5 has type hinting, with limitations:
http://ca2.php.net/manual/en/language.oop5.typehinting.php
Specified types must be objects or array, so built in types such as string and int are not allowed.
This is not a conversion, but will throw an error if an object of the specified type is not passed to the method or function, as in your example.
Long answer:
I think it is very difficult (read impossible) for PHP to do an implicit conversion in this case.
Remember: the fact that you call your class Integer is a hint to the human reader of the code, PHP does not understand that it actually is used to hold an integer. Also, the fact that it has an attribute called $val is a hint to a human reader that it should probably contain the value of your integer. Again PHP does not understand your code, it only executes it.
At some point in your code you should do an explicit conversion. It might be possible that PHP has some nice syntactig sugar for that, but a first attempt would be something like:
class Integer
{
public $val;
function __construct($val) { $this->val = $val; }
}
function ExampleFunc($i){
if (is_numeric($i)) { $iObj = new Integer($i); }
...
}
ExamFunc(333); // 333 -> Integer object with $val === 333.
This is not as cool as you would like it, but again, it is possible that PHP has some syntactic sugar that will hide the explicit conversion more or less.
Short version:
In one way or another, you will need an explicit conversion
Actually this possible with the SPL_Type extension. It defines classes for primitive types whose objects operate interchangeably with the PHP's primitive types (booleans, enums, ints, floats and strings).
You first example would work by simply inheriting from SplIt as follows:
class Integer extends extends \SplInt{}
function ExampleFunc(Interger $i){...}
ExamFunc(333); // 333 -> Integer object with $val == 333.
The problem is that the code of the SplTypes extension hasn't been maintained since 2012, and by the moment of this post, it hasn't ported to PHP 7, nor there is a plan for such.
UPDATE
I have found the following unnofficial port of SPL Types to PHP 7. Use at your own risk: https://github.com/esminis/php_pecl_spl_types
Basic installation instructions:
Clone code: https://github.com/esminis/php_pecl_spl_types.git
Generate the configure file. Inside the code directory type:phpize.
Generate make file: ./configure
Compile code and install: make && make install
Add the module to your PHP configuraiton. At Ubuntu, type echo "extension=spl_types.so" > /etc/php7/conf.d/spl_types.ini
Restart your PHP-FPM (if using it): service php7.0-fpm restart
No, PHP is not a strongly typed language.
Are you asking how to type cast? You can do:
$ php -r 'var_dump("333");'
string(3) "333"
$ php -r 'var_dump((int)"333");'
int(333)
Otherwise PHP is weakly typed, so in general you don't need to do it. It's implied by the language. Eg. if a function takes a numeric argument, then that number can be string, integer or float all the same; The value is converted if needed. That's why you can for example echo 33 without an error.
PHP is not strongly typed.
You want something like, whenever you pass an hbool instance into a function that expects a bool it would convert automatically using your implicit conversor.
What happens is that no function "expects" a bool, it's all dynamically typed.
You can force an explicit conversion by calling (int)$something but if that's the case you can then pass $something->to_otherthing() instead for non-automatic conversions.
PS: I'm sure im not being clear here. I will try to edit this answer after I eat something :)
This question is very old, but I would like to give a solution.
This behaviour is called boxing which can be done in PHP, but the inverse of this, unboxing see:
function a(int $a){...}
a(new Integer(1));
is not possible currently. If you want a framework which offers you this and even more, look at the BlazeFramework which has such wrapper classes.
Operation overloading does not work either in php. The implementation is maybe a bit too much to write, but I give you a hint! PHP calls the callback set with set_error_handler() with the error level E_RECOVERABLE_ERROR and debug_backtrace() delivers information about the function/method call.
If you don't get that, look at the implementation of the method blaze\lang\System#systemErrorHandler(), but possibly it is better to just use the framework if you want more of such features.

Categories