Pull to refresh

Comments 167

Мне, как бешеному глухому китайскому шаолиню ближе конечно первый вариант, так как он строже — но на самом деле для php больше подойдет второй, так как это одна из основных особенностей php — изменение типов на лету. А что, собираются вводить типизацию скалярных параметров?
Почему имплементация, а не реализация?
Вы считаете себя бешеным, глухим монастырем?
когда ты успел оглохнуть? ;)

на самом деле первый вариант имхо лучше второго вот почему:
<?php
$a= array(0=>'1');
$a= array(0=>'1', 1=>'0');
function x(string $s) {}
x($a);
x($b);

и что это будет?

прошу заметить что в данный момент в php используется тип array и у него есть поведение
<?php
function x(array $a) {}
x('123');

Catchable fatal error: Argument 1 passed to x() must be an array, string given, called in /tmp/1.php on line 3 and defined in /tmp/1.php on line 2

Call Stack:
    0.0005      58256   1. {main}() /tmp/1.php:0
    0.0006      58376   2. x() /tmp/1.php:3


ps опять в php будет бардак…
В обоих случаях будет такая же ошибка, как вы показали с параметром типизированным как массив и передали строку.
Это будет «Array», как и при любой другой попытке привести тип массив к типу строка.
Массив — комплексный тип, отсюда и нестыковки в приведении его к/из скалярных типов, в php нет операций которые сделали-бы из скалярного типа массив побочно, массив можно создать только намерено, через array(), type cast, спец.функции и т.п., соот-но и типизация его жесткая — так как функция ждет в виде параметра намеренно созданный массив. А в случае скалярных типов данных — есть такие операции, которые прозрачно меняют один тип на другой, и если типизация будет строгой — то и шанс поймать Catchable fatal error на типизированном параметре будет ненулевой.
Хочу заметить что он и так будет не нулевой. Просто при строгой типизации шанс будет гораздо больше.
вообще-то в php есть целых два способа сделать из скалярного типа массив.

$a = (array) «string»;
$a = unserialize(чего-то там в нужном виде);
массив можно создать только намерено, через array(), type cast, спец.функции и т.п.
$a = (array)«string»; // type cast
$a = unserialize(чего-то там); // спец.функция

Мистер Трололо?
Вау, а я оказывается пропустил это.
Возможно, конечно, я и несколько невнимательно читал комментарий, но…

Для альтернативноодаренных — обратите внимание на формат хранения объектов и массивов в сессиях.
Надо ли говорить, что записав руками строку в хранилище сессии минуя стандартный механизм, при извлечении данных из $_SESSION у меня есть все шансы получить объект или массив неявно.

Еще вопросы? Нет вопросов?

Тогда у меня встречный вопрос — мистер школьник?
Какой заясь? Какой арёл? :))) Я смотрю вы долго вынашивали коварные планы отмщения :)

Для альтернативнопрочитавшихдокументацию — обратите внимание на конфигурационный параметр session.serialize-handler, который как-бы говорит нам что при записи/чтении данных из массива $_SESSION автоматически происходит сериализация/десериализация данных, по-умолчанию как раз таки через механизм, который используется в функциях serialize/unserialize :) и как-бы неявно миновать стандартный механизм записи в сессию не миновав при этом стандартный механизм чтения — это прямо скажем — довольно явное приведение строки к массиву или объекту :)

Мистер Трололо, ваш ход :)

З.Ы. Мне 25 лет если что, я если честно особо упорно не пытался — но говорят таких в школу повторно не берут :)
Уже 25? Хотя мнение о том, что все только и думаю о вас и вынашивают «планы мести», более чем забавно. Обычно это свойственно школьникам и годам к 20ти выветривается.

Перечитайте еще раз внимательно, что я написал, и что писали вы.
> в php нет операций которые сделали-бы из скалярного типа массив побочно…
> А в случае скалярных типов данных — есть такие операции, которые прозрачно меняют один тип на другой,

Поэтому не надо нам рассказывать тут о прозрачном и автоматическом преобразовании строк в объекты и массивы при их извлечении из сессии, как о явном приведении.
Поскольку записывалась туда строка, а получили мы массив/объект (каким чудом у нас строка оказалась правильно сериализованным объектом/массивом и как она попала в хранилище сессии вас не должно волновать, за исключением того факта, что это произошло явным образом минуя механизм работы с сессиями)
А как еще назвать две недели выжидания, пока топик опустеет чуть более чем полностью, прежде чем дать ответ? :) Вот это как раз таки школьникам свойственно :)
Туда — это куда? Вы определитесь хотя-бы с этим вопросом, если туда — это сессионный массив, и оттуда тоже он — я безусловно признаю что я неправ, но туда — это у вас файл, область памяти, БД, а оттуда-то почему сессионный массив? Сессионному массиву естественно нужно хранить где-то данные, а данные, о чудо!, повсеместно могут быть представлены в виде строки, так как строка, о чудо!, это последовательность байтов :) «Дивись весь мир! Я записал кусок опкодов прямо в область памяти, выделенной для php, в виде строки — а достал...» :)
Какие-то нелепые оскорбления о возрасте, какая-то невнятная аргументация о «чудом попавших в сессию данных» :) ей Богу, жалкая попытка состроить «хорошую мину при плохой игре». Ведь вежливо разговаривает с собеседником и грамотно аргументирует свою позицию ведь только школота, не так-ли мистер Трололо? :)
Да как хотите так и называйте. Надо не страдать теорией всемирного замысла против вас.
Все имеет более тривиальные объяснения. Некоторым они правда, недоступны для понимания.

Равно как и недоступен контекст обсуждения. Где речь шла о прямом доступе на запись к хранилищу сессий минуя стандартный API.
И чтении из сессий «в другом месте» используя стандартный API. В результате чего мы получим неявное и прозрачное преобразование строки (или ошибку, если строка будет невалидна)

А чтобы понять так жгущие вас «оскорбления» — вернитесь к началу треда и удостоверьтесь кто и кого оскорблял на пустом месте.

Впрочем, чего я тут бисер мечу.
Вам же как раз внимания и не хватает, отсюда и мысли о том что против вас целых 2 недели чего-то замышляли.
Так что пожалуй я на этом закончу.
Ух, ну прямо-таки Монте Кристо воплоти :) Речь шла «о прямом доступе на запись к хранилищу сессий минуя стандартный API» — нет, речь таки шла не о нем, а о том что в php случайно создать массив нельзя. Написать обертку для сохранения данных в произвольное хранилище можно случайно? Записать туда правильно сформированную сериализованную строку не нарушив при этом структуру данных (а для сериализованных данных — это банально невозможно, так как у массивов/объектов указывается количество дочерних элементов) можно случайно? Приведите мне такой пример. Вся ваша аргументация на уровне «а вот если-бы у бабушки… была-бы она дедушкой» :)

А насчет начала треда — я не вижу несоответствий, как назвать непонимание предмета разговора, непонятно откуда взявшийся поучающий тон, ничем кроме троллинга это быть не может, и не вижу ничего зазорного тролля называть троллем, как в анекдоте «е**ся в жопу можно, а смеяться над этим нельзя?», увольте, я не настолько политкорректен :) Однако-же я не приписывал вам мифические, мне заведомо неизвестные качества :) не вспоминал вашу матушку хорошим словом, не делал догадки насчет вашего возраста, социального положения, физического и психического здоровья, и сексуальной ориентации, все только по существу :)
я говорю о том что поведение должно быть очевидным и однозначным… сейчас если передаваемый аргумент не подходит по типу сыпется Catchable fatal error (для array/object) почему в случае string/int/float должна происходить «магия» мне мало понятно.
лично я не хочу в громадном трейсе разбирать в каком из методов/функций произошло изменение типа переменной потому что «типа так удобнее». пример:
<?php
$x = 1;
function a(string $a){b($a);}
function b(int $b){c($b);}
function c(float $c){d($c);}
function d(string $d){return $d;}


вот задавать несколько типов это было бы здравым решением, а приводить к нужному имхо стоит уже в коде
У тебя есть функция принимающая integer, и в нее за счет типизации придет гарантировано integer, что тебя не устраивает? Я понимаю разговор шел-бы про переменную переданную по ссылке, тогда вызов функции поменял-бы тип переменной, которая может использоваться где-то еще, и да, пришлось-бы искать где конкретно это произошло, но мы-же говорим про локальную переменную, объясни мне глубинный смысл знания того где конкретно произошло приведение типа, до вызова или во время? Результат-то один, в функцию пришло то, что должно было придти.

И «типа так удобнее» тут совершенно не причем, строгая типизация — пожалуйста, я только за, но только пусть ее вводят после того как убьют неявное приведение типов, мне вот лично ни мягкая типизация, ни неявное приведение типов — ну нафиг не сдались, однако-ж они друг на друга завязаны, есть одно — должно быть и второе.
достаточно разрешить функции в качестве идентификаторов типов:

function myFunc( SoftInt $i1, Int $i2, DOM::Document $doc ){...}

соответственно определяем функции
SoftInt — старается преобразовать значение в число, если не получается — бросает исключение
Int — если не число — бросает исключение
DOM::Document — если документ, то так и оставляем, если строка — парсим, иначе — исключение

типа того
+1 идеальный вариант
определить стандартные int, string… и возможность добавить свои с возможностью либо привести к типу, либо выбросить исключение. одних только типов мало, часто нужно целое, больше единицы, стока от 6 до 255 и т.д.
я так в яваскрипте делаю В-)

var widget= new function(){
this.node= FProp( $ )
this.x= FProp( Number )
this.y= FProp( Number )
this.count= FProp( PositiveNumber )
}

function PositiveNumber( val ){
val= Number( val )
if(!( val >= 0 )) throw new Error( 'wrong count' )
return val
}
ну и далее:

widget
.node( 'content' )
.x( 1.1 )
.y( '-2' )
.count( -1 ) // ooops
> if(!( val >= 0 )) throw new Error( 'wrong count' )
if( val < 0 ) throw new Error( 'wrong count' )
не вариант? -))
зачем столько извращений?
а теперь и в пхп: habrahabr.ru/blogs/php/95157/
Мне тоже такой вариант нравится.
Можно использовать либо стандартные функции проверки, либо описать свои.
Например те, которые могут принимать несколько разных типов (массив и целое, строка и флоат)

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

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

function example(int $i) {} — означает, что аргумент должен иметь строго тип int.

function example(~int $i) {} — аргумент должен быть таким, чтобы была возможность прямого приведения его к типу int. Например, «2» к int приводится (поскольку это именно число в виде строки), а «2qwerty» (в строке не только число) — нет (в последнем случае — т. е. в случае невозможности приведения — выбрасывается соответствующее исключение).
а если надо только числа больше 0?
для этого есть другие типы в других языках, а в php будите проверять сами.
Это к теме не относится.

function example(int $i) { // $i обязан иметь тип int (если не обязан, то int просто не пишем)
    if ($i <= 0) { // Внутри функции делаем какие угодно проверки
        throw new Exception('…');
    }
}
и везде, где нужен «идентификатор товара» прописывать проверку на его неотрицательность?
С вашим вариантом в виде функции как идентификатора типа, насколько я вижу, никто не спорит :)
Это было бы крайне удобно.

Но речь идет именно об ограниченной реализации type hinting
т.е. если я указываю int — то только int и никаких приведений.
Если я допускаю приведения — то просто опускаю указание типа и оставляю упоминание о нем в phpDoc, если мне так уж потребуется приведение, я сделаю это внутри функции.
с тем же успехом и на инт можно проверять внутри функции
Можно. В этом весь и вопрос.

Разница между теми кто ратует за 1 и за 2й вариант, как я вижу только в одном.
Первые фильтруют и валидируют данные на этапе ввода и до обработки.

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

P.S. но собственные типы с автоматическим кастингом — хочу.
Ну не правда, я лично проверку пишу на входе. И валидирую, и фильтрую :)
Но я вижу что проблемы будут и когда мы выбрали данные из базы с известной структурой и типами полей, и нам сперва придётся в PHP коде сделать ручное приведение типов, ибо не дай бог по пути передадим числовое поле функции/методу, которые ожидают int или float — из базы же string приехал…
Нет проблем при выборке данных из базы. Есть проблемы с руками.

Источник данных для конечной логики должен быть неважен и именно в ней должна быть типизация 1го варианта.
Откуда и как мы получили данные ей(этой логике) должно быть абсолютно безразлично.
Поэтому приведением типов пусть занимаются соответствующие слои работы с БД или с пользовательским вводом.

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

Именно этот момент ограничивает размер и сложность приложений.

Поэтому 2й вариант это вода на мельницу мелких приложений для облегчения контроля ввода и т.п.
Но это и костыль в гроб для крупных приложений. Поскольку Zeev Suraski правильно написал — реализовывать два варианта это свидетельство о невозможности договориться.
а разве тут возможно договориться? ;-)
Ну пытаться можно.
Просто по результатам договоренностей как раз будет видно, есть ли у php какой-то шанс в сложных приложениях или проще забить.
Одной из основополагающих особенностей PHP всегда было неявное преобразование скалярных типов. Т.е. строки, числа, логические значения всегда могли быть преобразованы друг в друга. При этом, от отсутствия возможностей явного преобразования PHP никогда не страдал — всегда можно проверить какой тип имеет переменная, так же всегда можно явно привести переменную к нужному типу.

Для PHP-программиста, вообще не должно быть разницы, как именно в его функцию передается, например, числовое значение: 8421 или «8421». При этом, ведь всегда можно проверить, что «8421», действительно, представляет собой число, а не, скажем, строку «842l».

Я за то, чтобы была возможность указывать ожидаемый тип, но чтобы это был тип, к которому должны быть преобразованы аргументы функции. Разумеется, это должна быть именно возможность, а не обязанность. Например, если я пишу:

function myFunc(string $x1, int $x2, $x3) {}

то это должно означать, что в качестве $x1 может выступать как «just string», так и 8421, при этом, 8421 должно быть автоматически преобразовано в «8421». В качестве $x2 может выступать не только 8421, но и «8421», и «8421str», но строки должны быть автоматически преобразованы в int по правилам PHP.
Ерунда какая-то получается — если указан int, то int и должен быть, а если вам нужно, чтоб функция была «всеядной», то укажите просто $x2 и воспользуйтесь явным приведением типа.
А какая разница, как к Вам придет число, как «1000» или как 1000? Чем первое не подойдет? Тем более, если Вы точно будите знать, что пришло именно число, а не, скажем, "` OR 1=1".

В PHP вся прелесть в том и заключается, что можно писать как 2 + 2, так и «2» + 2, и «2» + «2» — результат будет одинаковым. Да, привыкнув к языкам со строгой типизацией, как C++ или Pascal, такой подход может казаться странным и нелогичным, и тем не менее, это PHP. Хотите строгую типизацию — используйте другой язык.

Однако, с Вами я все же соглашусь в том плане, что при объявлении int-аргумента, строки, которые не представляют собой числа, т.е. например «9ttt571», скорее всего должны вызывать хотя бы warning.
> Однако, с Вами я все же соглашусь в том плане, что при объявлении int-аргумента, строки, которые
> не представляют собой числа, т.е. например «9ttt571», скорее всего должны вызывать хотя бы warning.
Так я же именно об этом и говорю. Не имею ничего против динамической типизации, да и PHP не единственный язык с таким подходом.
Если тебе всё равно, то пиши просто function func( $x ), а если уж ты хочешь быть уверен, что приходит аргумент конкретного типа и никакого другого, то должно проверятся его соответствие как это уже реализовано:
function func( array $x )
function func( ClassName $x )
Не путайте классы и масивы с базовыми типами. Массив или Класс нельзя просто прозрачно сконвертировать скажем в string или int. Зато int <=> string легко. Речь о том, что бы простейшие типы могли преобразоыватся между собой, при учёте, что преобразование будет полным, т.е. «100» => 100, но не «100.1» => 100 — это вызывает ошибку.
в класс с методом __toString() можно прозрачно конвертировать в string, а потом, может, и в int.

а как быть с конвертацией string(int) в bool?
__toString() для type hinting не работает. Это только для явного приведения типов.
Такая конвертация уже давно работает на тысячах проектов. Имеем: таблица в БД с полем типа INT, в котором хранятся флаги 0/1. При выборке в PHP приходит строка '0'/'1' и он благополучно кастит ее в булев тип в выражениях типа if ($row['flag']).

int отлично конвертируется в boolean даже во многих строго типизированных языках.
Я не путаю, наоборот пытаюсь объяснить, что
Например, если я пишу:
function myFunc(string $x1, int $x2, $x3) {}

то это должно означать, что в качестве $x1 может выступать как «just string», так и 8421, при этом, 8421 должно быть автоматически преобразовано в «8421». В качестве $x2 может выступать не только 8421, но и «8421», и «8421str», но строки должны быть автоматически преобразованы в int по правилам PHP.
смысла не имеет.
Судя по красной цифре, объяснить не получилось.
8421str для $x2 вызывает ошибку. Это недопустимое значение, т.к оно не может быть сконвертировано в int без потери части данных.
я не про это: в отквоченном тексте говорится не о правилах приведения типа, а про приведении типа аргумента в момент его передачи в функцию, что, в описанном виде, мне кажется абсолютно излишним.
то есть речь там не совсем о type hinting.
Такова специфика PHP и если не делать приведение типов автоматом, всплывёт такое кол-во кода, которое делает приведение типов, что ахтунг.
А какое это, простите, имеет отношение к динамической типизации?
Именно так и задумано

function a(int $int) {}
a(1000);
a(«1000»);
a(«1000a»); — BOOM! Warning или Fatal error
А разве в случае мягкого задания так не произойдет?
Преобразование же должно происходить при передаче параметра, т.е. он в теле функции уже «честным» int-ом быть должен.
А как же быть с объектами классов у которых определён метод __toString? С одной стороны эти объект адаптированы к тому, чтобы преобразовываться в строки, с другой стороны если придерживаться «строгого типизирования» передать их в функцию function foo(string $str) не получится!

Что за чепуха?
Здесь важем zval type. Если это объект, а вы ждёте string — фига вам, а не type casting.
Если вы ждёте string, а передаваемый объект преобразуем к string, то PHP должен преобразовать его в string и передать string.

Ведь если я напишу echo $object, то PHP ругаться не будет.
И если $x = 123; и потом $str = 'abc'.$x; то PHP тоже ругаться не будет.

Т.е. когда надо PHP к нужному типу приводить умеет (если это возможно), а строгая типизация подразумевает обратное.

Какие-то двойные стандарты получаются.
Опять таки: что за чепуха?
Не путайте приведение типов и type hinting. Type hinting это немного из другой оперы, он проверяет того ли типа вы передали переменную. Просто из за специфики PHP нужно сделать исключение с автоматическим тайп кастингом между integer, bool, float и string типами, и только в случае, если это приведение не отбросит часть данных как это делается при ручном type casting.
ри этом, от отсутствия возможностей явного преобразования PHP никогда не страдал — всегда можно проверить какой тип имеет переменная, так же всегда можно явно привести переменную к нужному типу.
(int) $a — это и есть явное преобразование. Оно есть в PHP.
наконец-то…

а в какой версии это добавится?

я бы еще очень хотел, чтобы добавился магический метод __cast bugs.php.net/46128

а если уж делать так, то не изобретать новые типы, а или делать строгую типизацию, или приведение такое, как в оригинальном пхп с учетом __call
__toArray => есть же ArrayObject Interface, правда, не работает со встроенными array_-функциями, но в большинстве случаев это не критично
__toBool, __toInt => вроде бы хватает и __toString

а где вам требуется __cast?
в том то и дело, что не работает со встроеными array-функциями и __toString не хватает. А ArrayObject — это вообще какое-то издевательство, а не интерфейс.

был бы инструмент (а код то уже даже написан) а где его применить — я найду)
ну я и попросил вас привести примеры, где вам не хватает __toString

из array_-функций я использую в основном только array_merge & array_keys, но от совместимости ArrayObject с ними не отказался бы. Ну и в случае необходимости можно написать их аналоги, которые будут работать с ArrayObject.

А чем не устраивает ArrayObject? Я им активно пользуюсь. Он, правда, с foreach медленно работает, но это довольно просто исправляется.
в первом случае количество неработающего кода окажется катастрофическим, во втором, если рассматривать его как начало реформирования всей парадигмы написания кода на пхп — вполне рационально, только я сильно сомневаюсь что начинание будет продолжено
а какой эот код оказжется неработающим? пример. не представляю акого
и что? будет работать как и раньше. приведение типов обсуждается только при вызове функции, если в её объявлении указан какой-то тип
вы хотите сказать, что не поняли моей мысли, и мне надо было написать тут функцию, которая принимает integer, а в нее «приходит» string? по-моему довольно прозрачно

вдогонку могу сказать, что строгое типизирование со временем можно было бы применять во всех случаях, в том числе в вышеуказанном
да, я не понял вашей мысли, какой код при введении возможного тайпхинтинга в аргументах функции может сломаться? напишите явный пример и указите, в каком месте он сламается
И мамонты умирают, и говнокод воняет.
Когда-то же срезали register_globals и ничего, все счастливы теперь.
на многих хостингах до сих пор php4 + php5 стоит, на больших так вообще консерваторы спасают пользователей как могут, хотя и соглашусь с вами, что многие счастливы, разработчики движков постарались и вовремя внесли необходимые изменения

p.s. только откомментил, уже в карму успели насрать :)
Это бизнес хостеров.
Ну представьте — стоит старенький сервачок, держит доменчики и какой-то софт.
За домены платят, за хостинг платят — копейки прибыли капают. Снести железо и поставить новый софт, никто на эти параметры не пойдёт, всем уже нужные другие мощности. А со стареньких каждый месяц с кредитки снимают бабло.
Вот оно и стоит пока не здохнет.
Главное не хостинги в этом уравенеии, а разработчики. Хостеры всегда пойдут на поводу у разработчиков. А ещё хостеры сами обновят софт как только он попадёт в стабильные пакеты операционных систем.

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

>>> А нужно это для того, что бы не приходилось заниматся ручной конвертацией типов каждый раз, когда мы что-то выбираем из базы данных.

А может стоит завести нормальные драйвера для бд? Чтоб они этим занимались.
А если данные не из БД, а например из XML?
А как же POST и GET?

Согласен, что первый вариант правильнее по сути, но, как мне кажется, не попадает под идеологию языка.
Для _POST и _GET вы тоже пишете драйвера.

>>> $a = intval($_POST['example']);

В принципе, для любого хранилища данных все равно пишутся драйвера. Будь то POST или XML, или БД.
Строгое типизирование параметров позволит немного сократить код и заставить людей следить таки за входными данными.
Первый. Потому что это дорога к преверке типов во время компиляции, а не в рантайме. А с этой проверкой в рантайме PHP потом приходится заниматься дурной оптимизацией — из прокшн версии их вырезать, что бы быстрее работала…
Интересно, как вы сделаете оптимизацию на этапе компиляции, если все данные приходят из вне в скрипта, и они в 90% случаев string?
Обработка входных данных (проверка и приведение их к нужному типу) в PHP коде, который мне приходилось писать составляло примерно 1%-2% от логики работы приложения. При этом в большинстве случаев эти данные потом приводились к нужному типу через (int) и прочие подобные преобразования. Так что код этот у меня все равно был. Потому что как не крути, а даже для строковых данных проверки на XSS никто не отменял.
Мы не говорим о пользовательском вводе — там проверки и type casting никуда не денется вообще. А вот когда данные приходят с базы — валидацию мы же не делаем. Да и тайп кастингом заниматся особо не хочется, особенно если много integer/decimal колонок.
Я делаю :-) Я вообще стараюсь использовать типизированные transfer objects между двумя уровнями. А для генерации уровня доступа к данным использовать генератор, который сам генерит нужный код со всеми приведениями типов, которые он вычитывает из метаданных базы. SELECT-ы тоже лучше вручную не составлять, только самые сложные. А для парочки таких написать таблицу соответствия полей rowset-а и полей в базе является весьма несложным (а часто и полезным) занятием, особенно если в результате получать такие плюшки как атоматическое форматирование представлением поля на основе метаданных (там скока нулей после запятой, каким цветом отрицательные значения, какой заголовок колонки грида и прочие мелочи).
ORM всё же частный случай, а не 90% того, что работает на PHP в том контексте, который вы имеете ввиду :)
Я за строгую типизацию. Haskell доказал насколько она полезна
Абсолютно бессмысленная дискуссия.

В этом случае проще будет сделать форк и иметь два языка — PHP Classic и PHP Strong.

Неявное приведение типов всегда было одной из основ языка…
PHP classic, PHP medium, PHP lite, PHP super lite, PHP slims.
Главное пусть уберут что 1 == '1тралала'
=) Остальное переживем.
Для таких случаев есть ===
В чем проблема-то?
Спасибо, Кэп. Для каких случаев? === это сравнение без type hinting, а топик про то как правильно реализовывать type hinting.
Зачем его реализовывать _именно_ в PHP?

Для желающих есть миллион других языков.
И без строгой типизации как-нибудь проживём, лучше бы строки быстрее в юникод перевели.
Попробуйте при помощи mbstring полноценно упорядочить массив UTF-8-строк. А на досуге попробуйте осознать, как происходит получение UTF-8-подстроки при помощи mb_substr. Успехов. ;-)
Второй вариант разумеется.
Автоматическое преобразование типов всегда было одной из основ, это одна из причин, по которой язык настолько гибок.
А говнокод можно писать на любом языке…

В PHP есть предостаточно методов, чтобы явно привести тип, узнать тип или сравнить с учетом типа (операторы === и !==).

Зачем пытаться сделать из PHP нечто другое?
Учитывая последние изменения, а ещё если вдруг будет строгая типизация, странные мысли посещают. Ощущение такое что к версии РНР-99.9.99 мы вернёмся к C++

Вопрос только зачем…
Интерпретатор Си, написанный на Си — это же так увлекательно!

Такое чувство, что у языка нет идеолога. Хотя почему «чувство», так оно и есть.
Я думаю, что Вы сами сможете ответить на этот вопрос, если хорошо подумаете. Для улучшения мыслительной деятельности попробуйте предствить что вы пишите CMS на С++ и хостите пару сотен клиентов, её использующих.
>>попробуйте предствить что вы пишите CMS на С++
Попробуем:
Скорость загрузки страниц уменьшится с 1,1 до 0,8 секунды.
Время разработки увеличиваем в 5 раз.
Любое изменение (вы же собираетесь выпускать апдэйты, чтобы латать дыры и добавлять новые фичи?) будет занимать в 10 раз больше времени.
Клиенты будут привязаны к моему хостингу, а значит большинство пройдёт мимо кассы…
Чойта? Например мой движок больше 0.02 не выполняется. Это вопрос прямых рук, а не языка.
Простите, виноват, значит с 1,1 до 1,08 секунды :)
Я же говорю не про время рендеринга страницы на сервере, а про время загрузки страницы у пользователя, между кликом по ссылке и появлением страницы на экране.
Ну наши столичные интернеты позволяют грузить страничку куда быстрее… я даже не задумывался никогда что скорость передачи странички решает что-то… при скоростях в 10 мбит.
UFO just landed and posted this here
ВЫ успели написать много наработак с ифспользованием function qqq(int $value) ???
почитайте статью и проникнитесь идеей. для старого кода _ничего_ не поменяется.
Я бы выбрал первый вариант, но второй победит =)
По мне, так лучше оба варианта, чтобы программер мог изменить это настройкой. Тогда убиваются сразу два зайца, с одной стороны имеем старый работающий код, с другой стороны новое поколение будет приучатся писать правильно и без ошибок.
старый работающий код будет в обоих случаях, а оба варианта сделают огромную неразбериху — скрипты будут работать при одних условиях, и не работать при других
Мы это уже проходили с register_globals, в итоге правильный подход победил и переход был мягким.
если победит второй вариант — значит пора завязывать с PHP
А можно аргументировать?
я имел ввиду себя самого — слишком много «если» для меня
Вот вам для разогревания дискусии несколько вопросов:

  • Аргументируйте, почему вы за ту или иную систему тайпхинтинга
  • Опишите как будет происходить работа с типичными задачами с вами выбранной системой тайп хинтинга (т.е. GET/POST/COOKIE обработка параметров, запрос к базе данных, работа с XML/RSS)
  • Почему вы считаете злом возможность прозрачного приведения типов при тайпхинтинге, когда оно может быть сделано без потери точности данных (т.е. «10» => 10)?
Чёрд, парсер съел теги списка :(
Это не парсер, а стили такие, хм, клёвые. Ваш список как таковой на месте (взгляните в HTML-код страницы).
Второй вариант.
Автоматическое приведение типа очень удобно, а вот польза от строгой типизации в PHP абсолютно неочевидна.
И наконец-то можно будет не указывать тип скалярного параметра в @param :)
ну-ну… ищите потом скрытые ошибки :)
function a(int $s) { if ($s == 123) return true; return false; } var_dump(a('123 traktor'));
Думается, что те, кто использует тайпхинтинг, в курсе про способ сравнения if($a === 123)
Такая конвертация не допускается. Ясно же написано — конвертируется только тогда, когда это не повлияет на то, что находится в переменной. Т.е. в вашем варианте a('123') работает, a('123 ') уже не работает, ну а a('123 traktor') и подавно не пашет.
Да чтож вы творите то с PHP… Ничего ведь из первоначальной философии не останется :(
что плохого в том, что язык станет лучше?
А никто и не говорит что язык станет лучше, я, возможно, не правильно выразился, я имел ввиду то, что строгая типизация не попадает под идеологию гибкого языка.
«hinting» означает, что указание типа необязательно. удобно вам — используете, неудобно — не используете.
Теперь понятно, спасибо за разъяснение :)
… станет хуже*, простите, очепятка.
Он станет не лучше, а копией десятка других языков. РНР чем и завоевал свою популярность что был не таким как все, и именно это из него пытаются убрать…
а остальные прям все клоны? х) если язык не будет впитывать в себя удачные решения из других языков, то более молодые языки его быстро задавят.
Он это делает, просто редко когда в таком виде, как это в других языках. Специфика языка накладывает свой отпечаток и фитчи как правило подгоняются под реалии PHP и его область применения.
Чего именно не останется? Я заметил только что не придется писать каждый раз $id = (int)$id;
Второй вариант лучше для поддержки старого кода. Допустим указал я тип аргументов для функции, подчистил ее тело, убрал оттуда явные преобразования. А вот сотни вызовов этой функции поменять будет сложнее.
И здесь второй вариант выигрывает.
В python вот изначально типизация строгая (хоть и динамическая). И «сие есть круть несусветная», т.к. явное всегда лучше неявного.
Если мне понадобится строгая типизация — уйду в C#. Можно и на С# использовать в качестве аргументов функций общий тип object, получив при этом какое-то подобие неявности типов. Однако это так же бессмысленно, как в PHP вводить строгую типизацию. Каждый язык хорош по своему для своих задач. Имхо.
Понятное дело, что если вводить то «мягкий» вариант, в принципе лишним не будет. Однако…
Что за бред придумывать новые правила на каст? если уж вводить такой вариант, то использовать вариант 1 в 1 с явным преобразованием. Т.е.
(int) «123ab» == 123

Иначе это все только усложнит и запутает.

Надеюсь, если заапрувят, не забудут поправить ReflectionParameter для доступа к типу.
Какраз наоборот — если до функции дошло 123ab — значит где то забыли добавить проверку. Ведь на самом деле прозрачное приведение типов нужно не для того, что бы забить на валидацию данных, а для того, что бы не нужно было бы мудохатся с конвертацией когда данные приходят строго известных типов (к примеру из реляционной БД, где структура и типы данных фиксированы). Если не делать прозрачной конвертации, то будет слишком много кода, который будет выглядеть так:
$data = $result->fetch_assoc();
settype('integer', $data['id']);
settype('float', $data['price']);
....
и так для каждого числового типа. А с boolean вообще будет странно, типа такого:
$data['bool_flag'] = (bool)$data['bool_flag'] === '1';


Грань тут довольна тонка, но мы, те кто знает что и как нужно делать, её чуствуем и редко переступаем. А говнокодеры, они дажа не будут про хинты знать :)
К тому же type hints опциональны, а не обязательны.
неее, я про другое, я про то, что придумывать новые правила приведения, когда уже одни существуют, — глупо. Это все только усложнит язык, а наша цель таки облегчить его =)

ЗЫ на счет була
$data['bool_flag'] = $data['bool_flag'] === '1';//Сравнение итак выдает булеан значение, как бы приведение к (bool) там лишнее.

Можно еще вот так
(bool) (int) $data['bool_flag'];


Всё на самом деле очень просто. Во всех интерпретируемых языках должна быть утиная типизация, потому что они на то и интерпретируемые, что перед запуском скрипта не выполняются проверки всех зависимостей и компилируемого исходного кода на валидность. Таким образом строгая типизация не реализуема т.к. просто невозможно отловить все некоректно испольуемые вызовы, пока не наткнёшься на них при тестировании.

При этом утиная типизация обеспечит хотя бы минимальный контроль соответствия интерфейсов для нейтрализации совсем уж незаметных ошибок, когда что-то во что-то неявно сконвертировалось и выпало неизвестно куда.

Python и Ruby — правильные в этом плане языки, PHP — несовсем.

По поводу конвертации скалярных типов в PHP скажу вам, как программист на этом языке с пятилетним стажем: по мне так это просто жуть. Я знаю ещё с пяток других различных языков на среднем уровнем и могу сказать, что такой неявной эквилибристки конвертации типов не видел нигде. Также нигде нет такого сильно разделения скалярных и пользовательских типов, что на самом деле является двойным стандартом.

Выводы делайте сами.

Прошу воспринимать этот комментарий, не как троллинг PHP, а как субъективный анализ существующих моделей проверки типов в современных интерпретируемых языках.
Знаете, вот есть PHP — он ни похож ни на один язык. И это прекрасно! Лично мне он нравится вот такой вот своей нетривиальностью. Он может очень много, но нужно потратить много времени на изучение особенностей и выработки правильных подходов по работе на PHP. Действительно хороших программистов на PHP на самом деле гораздо меньше, чем кажется, и найти их задача очень сложная.
В этом весь PHP :) Велосипед, такой велосипед. Кому-то это нравиться, но большинству просто не хочется осваивать более сложные модели, дабы дальше тешить собственную манию величия илюзией всемогущества и незаменимость(ввиду нетривиального кода на нетрививальном языке).
Вот насчёт нелогичности кода не надо ля-ля. Я больше ужасаюсь большинству фреймворков с их огромными структурами, MVC в которое напихана чуть ли не вся книга банды четырёх, завёрнутые до полуумия шаблонные системы и прочие «прелести». Вот почему у меня получается простой и понятный код, который с лёгкостью пишется и довольно быстро? Все почему то забываю главный принцип KISS — Keep It Simple Stupid. Не предназначен он для того, что из него многие пытаются вылепить. Другой он. Задача стоит, или вы не понимаете PHP такой, какой он есть, хотите тянутся к светлому и прекрасному — ну чёрт возьми — сделайте задачу на Python/Ruby/C#/Java/C/C++/.NET — вот кто мешает? А в итоге что? — «Мыши давились, плакали — но жрали кактус» — и орут какой PHP плохой.
В общем не зря есть пословица — горе от ума. Обчитаются умных вещей, которое делают в других языках и пытаются втеснить в PHP. Хорошо хоть разработчики идут своим путём и развивают язык не путём копирования всего подряд.
Моё мнение не мотивируется тем, что я «обчитался» там чего-то. Да, прочёл я много. Но никто сейчас не говорит про паттерны проектирования. Это тема другого топика.
Ну так дело в том, что пытаются применить паттерны эти и натыкаются на то, что язык чего-то не может. И начинают хаять язык за то, что он не умеет, хотя он просто не предназначен для того, что на нём пытаются сделать. Вы видели хоть одну жалобу на то, что PHP не позволяет сделать простые вещи? Я — нет. А вот когда наворачивают невесть что, пытаются из него пытаются выжать то, для чего он не задумывался вообще — хочется стукнуть по голове и отправить писать на чём то другом.

Ведь в основе PHP ой как не зря лежит принцип KISS (Keep It Simple Stupid — для тех кто не знает) — на нём не то что нельзя, а не нужно делать очень сложные вещи. Вот facebook использует PHP и очень им доволен. И они не жалуются на него. Они прекрасно понимают как нужно его использовать и не пытаются на его плечи переложить то, чего он не подымит.
Да кстати, еще одна вещь о которой здесь не упомянули — отсутствие в php типизации возвращаемого значения, что в принципе сводит на нет такую вещь как интерфейсы. Да, отлично, метод принимает два аргумента, целочисленный и строковой, а возвращает? А что он возвращает уже одному Богу известно :) Ну и туда-же указание выкидываемых исключений, и т.д. и т.п., при грамотном подходе к процессу мы на выходе должны получить Java'у :)
Тут беда в том, что в PHP нет адекватной базовой иерархии исключений, поэтому каждый придумывает свою, что приводит к тому, что подключив библиотеку использующую исключения мы натыкаемся на то, что не знаем как то или иное из них, обрабатывать.

В итоге наш респонс на неизвестное исключение либо сожрать его с аутпутом в лог, либо выкинуть фатал, что мало отличается от стандартного поведения классической системы NOTICE/WARNING/FATAL ERROR :)
Только беда опять в том, что SPL в PHP с боку припёку и его никто не использует :)
Вы несколько неправы.

Итераторы SPL местами активно используются в Zend Framework.

При этом документация php в разделе установки SPL сообщает нам, что:
===
This extension is available and compiled by default in PHP 5.0.0.

Note: As of PHP 5.3.0 this extension can no longer be disabled and is therefore always available.
===
Т.е. не то чтобы сбоку, а by default.

Сплю и вижу как все бросились его использовать после того как исчезла возможность его отключить :) Кажется реализацией(и включением по умолчанию) этого расширения Zend пытается искупить вину за реализацию других фич.
Почему бы просто не использовать, например, phpdoc?
Ну наверное потому что phpdoc — это документация, и носит уведомительный характер, и то что в интерфейсе задокументировано что метод возвращает определенный тип — для реализации на самом деле ничего не значит, и вернуться может что заблагорассудится разработчику.
Вы правы, но зачем нужна такая документация? =)
Как вы верно заметили, ввод типизации для скалярных типов этой проблемы тоже не решит.
Не решит покуда понятие интерфейс не будет реализовано полностью, с типизацией возвращаемого значения и исключений, не выдирайте фразы из контекста. Типизация выходного значения, так-же как и входных параметров — дает уверенность в том что при нормальном ходе работы программы из функции вернется то, что в ней заявлено, или ход выполнения программы прервется с ошибкой/исключением. А с phpdoc я могу с легкостью сделать посередине свое культовое:
throw $this; // не ждали?
Кто мне запретит? Соот-но такое понятие как интерфейс в php не дает никакой сколько-нибудь значимой гарантии того что ход работы программы не будет прерван сложением DOMDocument и SOAPServer, потому как несмотря на то что класс реализует интерфейс
interface Sum {

  /**
   * @return integer
   **/
  getFirstSummand();

  /**
   * @return integer;
   **/
  getSecondSummand();

}
В программу вполне могут вернуться именно они.
согласен, тогда можно будет отказаться от костыля phpdoc
Ну phpdoc на самом-то деле не костыль, он используется как костыль различными IDE для автоматической подстановки кода, а основное его предназначение — создание документации по API — останется.
В Jav'е-же на самом деле все вышеперечисленное уже присутствует, однако-же javadoc, прародитель phpdoc — появился именно там, хотя там естественно теги @return и @throws не указываются, так как они присутствуют в коде, также как теперь являются устаревшими теги phpdoc'а @access и @static — так как в php5 они присутствуют в самом коде.
Мне наоборот первый вариант нравится больше. То, что приходится все приводить к нужному типу это совершенно нормально и в этом нет ничего плохого. Все входные данные (буть то база, http или аргументуы) должны проходить валидацию на корректность, которая как раз и включает приведение к типу.

Так же мне не очень понятно, почему для bool должны работать «традиционые правила PHP», а для отсальных преобразований — нет.
Я уже давным давно этого жду. Ещё с PHP3. А то запарило плодить кучу лишнего кода:

function getById($userID) {
$userID = (integer) $userID;
// Постоянно делаю мягкое типизирование. Всегда! Всех параметров! Как обдолбанный тибетский монах.

}
Мне нравится такой вариант: для функций, в которых вы уверены в значениях переменных (они провалидированы, приведены к нужным или конвертируемым типам и отфильтрованы где-то ранее) можно не использовать типизацию.

Для функций, у которых уверенности в правильном типе данны быть не может, но в итоге нужна — использовать типизацию. По всем стандартным типам языка + пользовательским объектам — наследникам пользовательских классов.

Да, там где ваша функция (метод) в качестве аргумента должна однозначно получать ваш какой-нибудь наследник SqlSelectClass, логично написать

fucntion processSQL(SqlSelectClass $sqlQuery,…, ..)

не так ли?

Будущим коллегам — разработчикам это, кстати, может здорово облегчить жизнь. Я уж молчу о возможностях phpDoc — генерации в том же NetBeans ;)

И, да, отсутствие возможности типизации (со встроенным приведением типов, вот чего захотел) по скалярным типам в описании пользовательских функций php5 меня несколько огорчило. А могло бы быть оченнно полезно.

Вплоть до ты ему крутой Query-object с методом toString() на вход, а в описании функции — string, и войдет в функцию после преобразования типов таки string.
было бы не плохо ещё предусмотреть двойной тип или/или.

function str_replace(
string|array $from, // или строка или массив строк.
string|array $to,
string|array $string
)
Sign up to leave a comment.

Articles