Type hinting php что это
Перейти к содержимому

Type hinting php что это

  • автор:

# Type hinting

# Type hinting scalar types, arrays and callables

Support for type hinting array parameters (and return values after PHP 7.1) was added in PHP 5.1 with the keyword array . Any arrays of any dimensions and types, as well as empty arrays, are valid values.

Support for type hinting callables was added in PHP 5.4. Any value that is_callable() is valid for parameters and return values hinted callable , i.e. Closure objects, function name strings and array(class_name|object, method_name) .

If a typo occurs in the function name such that it is not is_callable() , a less obvious error message would be displayed:

Fatal error: Uncaught TypeError: Argument 1 passed to foo() must be of the type callable, string/array given

Nonstatic methods can also be passed as callables in static format, resulting in a deprecation warning and level E_STRICT error in PHP 7 and 5 respectively.

Method visibility is taken into account. If the context of the method with the callable parameter does not have access to the callable provided, it will end up as if the method does not exist.

Fatal error: Uncaught TypeError: Argument 1 passed to r() must be callable, array given

Support for type hinting scalar types was added in PHP 7. This means that we gain type hinting support for boolean s, integer s, float s and string s.

By default, PHP will attempt to cast any provided argument to match its type hint. Changing the call to add(1.5, 2) gives exactly the same output, since the float 1.5 was cast to int by PHP.

To stop this behavior, one must add declare(strict_types=1); to the top of every PHP source file that requires it.

The above script now produces a fatal error:

Fatal error: Uncaught TypeError: Argument 1 passed to add() must be of the type integer, float given

# An Exception: Special Types

Some PHP functions may return a value of type resource . Since this is not a scalar type, but a special type, it is not possible to type hint it.

As an example, curl_init() will return a resource , as well as fopen() . Of course, those two resources aren’t compatible to each other. Because of that, PHP 7 will always throw the following TypeError when type hinting resource explicitly:

TypeError: Argument 1 passed to sample() must be an instance of resource, resource given

# Type hinting classes and interfaces

Type hinting for classes and interfaces was added in PHP 5.

# Class type hint

The above script outputs:

Chris is being enrolled at University of Edinburgh

# Interface type hint

The above example outputs the same as before:

Chris is being enrolled at University of Edinburgh

# Self type hints

The self keyword can be used as a type hint to indicate that the value must be an instance of the class that declares the method.

# Nullable type hints

# Parameters

Nullable type hint was added in PHP 7.1 using the ? operator before the type hint.

Before PHP 7.1, if a parameter has a type hint, it must declare a default value null to accept null values.

# Return values

In PHP 7.0, functions with a return type must not return null.

In PHP 7.1, functions can declare a nullable return type hint. However, the function must still return null, not void (no/empty return statements).

# Type hinting generic objects

Since PHP objects don’t inherit from any base class (including stdClass ), there is no support for type hinting a generic object type.

For example, the below will not work.

And will throw a fatal error:

Fatal error: Uncaught TypeError: Argument 1 passed to doSomething() must be an instance of object, instance of OperationOne given

A workaround to this is to declare a degenerate interface that defines no methods, and have all of your objects implement this interface.

# Type Hinting No Return(Void)

In PHP 7.1, the void return type was added. While PHP has no actual void value, it is generally understood across programming languages that a function that returns nothing is returning void . This should not be confused with returning null , as null is a value that can be returned.

Note that if you declare a void return, you cannot return any values or you will get a fatal error:

However, using return to exit the function is valid:

# Syntax
  • function f(ClassName $param) <>
  • function f(bool $param) <>
  • function f(int $param) <>
  • function f(float $param) <>
  • function f(string $param) <>
  • function f(self $param) <>
  • function f(callable $param) <>
  • function f(array $param) <>
  • function f(?type_name $param) <>
  • function f() : type_name <>
  • function f() : void <>
  • function f() : ?type_name <>
# Remarks

(opens new window) are a defensive programming practice that ensures a function’s parameters are of a specified type. This is particularly useful when type hinting for an interface because it allows the function to guarantee that a provided parameter will have the same methods as are required in the interface.

Passing the incorrect type to a type hinted function will lead to a fatal error:

Fatal error: Uncaught TypeError: Argument **X** passed to **foo()** must be of the type **RequiredType**, **ProvidedType** given

Типобезопасная работа с массивами PHP

Всем привет, расскажу о собственном велосипеде для удобной работы с массивами в PHP.

Type hinting

В PHP7 появились подсказки типов (type hinting), что позволило IDE проводить более качественный статический анализ кода, качество нашего кода улучшилось (или правильно говорит «стало более лучше«? ).

Конечно и раньше можно было для IDE написать подсказку в коментах к коду, но теперь типы стали частью кода и теперь их стало возможным рефакторить и не бояться того что ты что то где то забудешь (рефакторить конечно в смысле переименовывать классы и интерфейсы).

Кроме того, что стало возможным указывать выходной тип, появилась возможность указывать тип входного аргумента.

Но кроме приятных возможностей type hinting накладывает и обязанности, то есть типы переменных действительно должны быть такими как указано в сигнатуре метода.

Если не проверять типы, то можно получить ошибки в методах и конструкторах (особенно радуют ошибки в конструкторах).

Писать проверки вручную утомительно, я решил это дело автоматизировать, но не через проверку, а через приведение к нужному типу.

В моей работе достаточно часто приходиться писать с нуля, обычно это или прототипы, или парсеры, или ETL для нового источника данных, по сути тоже парсер.

Работаешь конечно с массивами (например когда читаешь из *.csv), работать с базой можно через ORM, но для моих задач это слишком громоздко, мне удобно работать с базой через PDO, которое отдаёт тебе данные опять же в массивах. «Любимый» Bitrix не умеет возвращать данные иначе как в массиве.

Как ни крути приходиться извлекать данных из массивов. Поэтому я написал обёртку для работы с массивами.

Что бы не копипастить код из проекта в проект я оформил пакет для Composer:

ValueHandler

Первоё моё требование было — всегда знать значение какого типа я получу. Перед этим значение конечно надо бы ещё получить, наверное по индексу, так мы пришли к тому что нам нужен метод get().

И теперь нужны методы для приведения типа, типов в PHP не много, получились такие методы:

  1. int()
  2. str()
  3. bool()
  4. double()
  • array()
  • asIs()
  • default()

ArrayHandler

Следующим требованием было получить возможность упростить массив из одного значения до ровно этого значения.

Покажу на примере из документации:

Можно конечно бежать по массиву, который вернётся из запроса, и делать такое присваивание:

, но мне так не нравится, пусть это происходит автоматически, так появился метод simplify().

Ну и раз уж у нас есть обёртка над массивом, то добавим метод для проверки наличия индекса — has(), если захочется пробежаться по элементам массива, то поможет метод next().

На этом можно было бы и остановиться, потому что уровень автоматизации достиг комфортного уровня, но иногда приходиться работать с вложенным массивом вложенного массива, и мне удобней сразу получить ArrayHandler для целевого массива, поэтому я добавил метод pull(), который возвращает ArrayHandler для вложенного массива.

Выглядит это так:

Можно конечно и так писать:

, но у меня в глазах рябит от количества квадратных скобок, мне удобней через pull().

Общие рассуждения

Когда код подключается из Композера это очень удобно, кроме того что вы избавляетесь от необходимости копипастить, вы одной командой получаете свою библиотеку и она всегда под рукой.

Перед тем как делать свой пакет я посмотрел аналоги и ни чего подобного не нашёл, есть несколько проектов, которые просто обёртка над array, и в этих проектах просто оборачивают многие методы для работы с массивами, а типобезопасности ни где нет.

Видимо написать (int) или (bool) перед именем переменной всем просто и удобно и ни кто не видит смысла заморачиваться с отдельным репозиторием под это дело.

Возможности библиотеки чуть шире описанных в статье и больше информации можно получить в документации (README.md).

PHP5 ещё не редкость, поэтому у библиотеки есть отдельная версия для PHP5, отличается от версии для PHP7 названием нескольких методов и конечно весь type hinting только в коментах.
Есть версия библиотеки для PHP7.2, отличается только тем что в сигнатуре у метода object() появляется тип возвращаемого значения — object.

Код полностью покрыт тестами, но в принципе так и ломать не чему 🙂

Пользуйтесь на здоровье!

Ещё один пример использования

Смотреть во время отладки на JSON в котором числа это числа, логические значения — логические, мне намного приятней чем только на строки.

Type hinting php что это

Type hinting is a concept that provides hints to function for the expected data type of arguments.

For example, If we want to add an integer while writing the add function, we had mentioned the data type (integer in this case) of the parameter. While calling the function we need to provide an argument of integer type only. If you provide data of any other type, it will throw an error with clear instructions that the value of an integer type is needed.

Advantages of type hinting:

  • Type hinting helps users debug the code easily or the code provides errors very specifically.
  • It is a great concept for static kind of programming/data.

Disadvantages of type hinting:

  • Functions only take one type of data.
  • The dynamicity of data or argument is not there.

Example 1: In the following example, $var1 of type “cls” class is passed to the display() function. It displays the text of the class “cls”.

Error Proof Your PHP with Type Hints and Return Types

Beth Rogers

PHP seems to be everyone’s favorite language to criticize. Its dismissed as buggy, irrelevant and an overall terrible choice. However PHP still powers a large portion of the web. WordPress, the most used CMS platform is powered by PHP. A large portion of Facebook is also built with PHP.

Despite the frequent Quora questions it is still very relevant. Its also had a ton of updates in the past few years. If you tried to learn PHP back in 2002 and hated it I would encourage you to give it another chance. It is possible to create well designed, maintainable, non-trivial applications with PHP.

It is true that its very easy to write bad PHP. The barrier to entry is low and often developers who are new to the language just start mixing PHP into their HTML. Some popular CMSs even encourage this bad behavior.

For trivial side projects and for those new to the language mixing PHP into HTML isn’t too bad. And truthfully this is a legitimate way to start learning PHP. But if you want to build any non-trivial application mixing PHP into your HTML will lead to heartache. Its messy, sloppy and just plain ugly. Plus it can make life difficult for front-end developers and designers who want to make updates without wading through piles of PHP.

In this article I’m going to address a simple and relatively painless way to make your PHP more resilient and less error prone using type declarations.

Many software developers who are used to working with languages like Java often complain that PHP does not offer any type declarations. But type declarations for complex data types have been around for a while. And with PHP7 we finally got type hints and return types for scalars! So not only can you type class instances, now you can type integers, strings and booleans.

Strong vs. Loosely Typed Languages

Java is the most popular example of a strongly typed programming language. All types must be explicitly declared. If your code does not conform to the declared types it will not compile.

JavaScript is an example of a popular loosely typed programming language. If your code does not conform to the expect types it will usually fail silently. This can lead to some pretty nasty and difficult to resolve bugs.

One common type error in JavaScript occurs when you are trying to get an integer from a form input. If you don’t coerce the form input to an integer it will be processed as a string. So 1 + 1 will be 11 instead of 2. Not fun!

So Why Is This Important?

Eliminates a whole class of tests

I maintain a large Laravel (PHP framework) application which had quite a few tests to check that model methods were returning the expected instances. Since some functionality is only available Eloquent collections I was constantly need to make sure that the expected collection instances were returned. Otherwise I could run into some nasty errors.

Adding return type declarations eliminated the need for all of these tests. Now all of my tests can focus on actual functionality and logic instead of verifying instances of return values.

Additional documentation

Adding type declarations makes your code self documenting. You know exactly what a function expects as input and what the expected output will be. This may sound trivial but your teammates and your future self will be grateful.

Prevents hard to track down bugs

Since many type errors result in silent failures debugging can be very painful. The time it takes to add type declarations to your code is nothing compared to the time and misery you are saving down the road.

It forces you to think about what your methods are actually doing.

This is another benefit that may sound trivial but its important to know what your methods are actually doing. Especially if you are using a framework in your development. If you are copy/pasting from your framework’s documentation you probably aren’t thinking the code through.

Adding type declarations will force you to think about what your methods are actually doing. This will help you gain a deeper understanding of your code base.

Bonus: You’ll be able to learn strongly typed languages faster.

If at some point you have to learn Java you will already be in the habit of using type declarations in your code!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *