Skip to content

Latest commit

 

History

History
153 lines (101 loc) · 4.24 KB

strict-types.md

File metadata and controls

153 lines (101 loc) · 4.24 KB

Strict Types

PHP contains by default a lot of magic behavior and checks almost nothing. When particular type is expected, PHP tries to convert given type to the expected one, which can yield unexpected results. Consistence promotes using strict types to achieve more predictable, maintainable and readable code. PHP 7 helped a lot with these problems by introducing strict types, but only for function/method parameters and return types. Following tools should provide additional help:

Strict Object

Objects in OOP are defined as encapsulating data and behavior. In PHP data is represented as object properties and behavior as object methods.

PHP does not check that you defined properties which are used:

<?php

class Foo
{

}

$foo = new Foo();
$foo->bar = 'bar';
var_dump($foo->bar); // 'bar'

This can lead to bugs which are difficult to discover, because there are no errors, warnings or notices and the bug can be introduced just by a typo.

This behavior is part of the PHP's magic methods. Using these methods usually leads to breaking encapsulation of objects. You can stop this by overloading these methods, which is exactly what Consistence does:

<?php

class Foo extends \Consistence\ObjectPrototype
{

}

$foo = new Foo();

// \Consistence\UndefinedPropertyException: Property Foo::$bar is not defined or is not accessible
$foo->bar = 'bar';

There are several ways, how you can use this in your code:

  • ObjectPrototype is abstract class which you can extend by default as showed above, this is the recommended way
  • if you can't (or do not want to) extend, you can use ObjectMixinTrait
  • if you want to override only some magic methods, or need to implement some magic functionality, but want this as a fallback use methods in ObjectMixin

Checking value types

You can't always check types with type hints, sometimes you need to check the types inside of method or need to do a more complex check.

With Type::checkType() you can start with simple check such as:

<?php

use Consistence\Type\Type;

Type::checkType('foo', 'string');

// \Consistence\InvalidArgumentTypeException: int expected, foo [string] given
Type::checkType('foo', 'int');

Usable types are listed in the Consistence Coding Standard.

Also note that for custom type always write the FQN (fully qualified name) and do not use leading \

When checking custom types, subtypes are allowed to be passed in by default, but you can control this by the third parameter:

<?php

use Consistence\Type\Type;

Type::checkType(new DateTimeImmutable(), DateTimeInterface::class);

// \Consistence\InvalidArgumentTypeException: DateTimeInterface expected, DateTimeImmutable#ecc7 [DateTimeImmutable] given
Type::checkType(new DateTimeImmutable(), DateTimeInterface::class, Type::SUBTYPES_DISALLOW);

There is also Type::hasType() which can be used in conditions or anywhere else where you do not want to throw the exceptions.

Arrays/Collections

Arrays/Collections are noted as <type>[]:

<?php

use Consistence\Type\Type;

Type::checkType(
	[
		'foo',
	],
	'string[]'
);

// \Consistence\InvalidArgumentTypeException: string[] expected, 1 [int] given
Type::checkType(1, 'string[]');

This can also be used to check nested arrays:

<?php

use Consistence\Type\Type;

Type::checkType(
	[
		[
			'foo',
		],
		[
			'bar',
		],
	],
	'string[][]'
);

Union types

There are a lot of cases when multiple types can be accepted, this can be represented by union types which are noted with |:

<?php

use Consistence\Type\Type;

Type::checkType('foo', 'string|int');
Type::checkType(1, 'string|int');

Getting types

You can use Type::getType() to get type from value:

<?php

use Consistence\Type\Type;

var_dump(Type::getType('foo')); // string
var_dump(Type::getType(['foo'])); // array
var_dump(Type::getType(new DateTimeImmutable())); // DateTimeImmutable