Осторожно, in_array
3 сентября 2011
Такая функция как in_array
используется очень часто. Однако, есть особенности, на которые сегодня обратил моё внимание aktuba, дав мне вот такой кусочек кода:
$array = array(0, 'one', 'two'); var_dump(in_array('three', $array));
Работает он немного неожиданно — выдаёт true
. Всё дело в том, что строка three
приводится к типу элемента массива перед сравнением. В нашем случае интересно приведение к числу.
Если такое поведение нежелательно, можно заставить сравнивать элементы ещё и по типу, передав третий параметр:
$array = array(0, 'one', 'two'); var_dump(in_array('three', $array, true));
Комментарии RSS по email OK
Ага, такой вопрос есть в тесте от мамбы =) Ещё из интересностей PHP. Есть приватный или защищённый метод класса. Он него инстанциируется объект. К этому методу может получить доступ другой инстанцированный объект от этого же класса =) Много узнал, когда готовился к Zend Certification. =)
Не совсем вменяемый пример, имхо. Чаще всего бывает вот так:
Вот вам тоже задачка:
Каков результат?
Есть еще один интересный пример, хотя он и описан в документации, но все же. Нельзя проверять строки на пустоту функцией empty();
NickSun, по логике вещей должны переиндексироваться неассоциативные ключи массива.
holdmann
Ну это как раз стандартное поведение...
Все это выведет true
Я понимаю, что это стандартное поведение, впрочем как и в случае NickSun'a. Как это часто бывает, из-за банальной невнимательности, возникает трудноотлавливаемая ошибка.
Поэтому надо либо на 100% понимать что делаешь, либо использовать более подходящие под конкретный тип данных функции.
http://phplens.com/phpeverywhere/node/view/52 (6 пункт).
@stamm Не совсем понял про ООП. Поясни еще раз, плиз!
@dV, имеется ввиду, что в PHP все private и protected методы по умолчанию являются class friend'ами в стиле C++ для своего же класса.
Вот этот код отработает верно, без ошибок и выдаст двойку, а затем единицу:
Комментарий: testMethod одного экземпляра класса вызывает testMethod другого экземпляра класса, игнорируя права доступа (private, в данном случае).
@resurtm К сожелению, PHP не дает возможности вызывать защищенный метод класса из контекста другога класса, если они ИМПЛЕМЕНТИРУЮТ один интерфейс. Более того, если они наследуют общий класс, все равно не помагает объкету одного класса вызывать защищенный метод объекта другога класса! Только и только если объекты принадлежат ОДНОМУ классу, либо объект, кот вызывает защищенный метод может принадлежать классу, кот ОБЯЗАТЕЛЬНО НАСЛЕДУЕТСЯ от класса того объекта, чей метод вызывает.
Я много думал о friend-методах в стиле С++ для PHP, когда рассуждал о парретне State. В случае смены состояний у контекста конкретным состоянием, этот метод должен быть защищенным и friend'ом конеткрному состоянию (общему интерфейсу всех конкретных состояний). Другими словами, когда клиент использует контекст он не может явно менять состояние контекста, но котекст должен задавать другое состояние контексту.
Может быть кто-нибудь может внятно объяснить эту особенность и её применение? Еще лучше, если поделитесь ссылкой.
Спасибо.
Практического применения получается, что и нет, если учесть, что для интерфейсов и/или наследования это не работает.
По поводу отсутствия friend в PHP — согласен, немного напрягает. :(
№5294
Касательно моего комментария, конечно же я имел ввиду:
Другими словами, когда клиент использует контекст он не может явно менять состояние контекста, но ОДНО СОСТОЯНИЕ должено задавать ДРУГОЕ СОСТОЯНИЕ контексту.
Про модификаторы я как-то тоже озадачивался.
Натыкался на такое в switch значений из GET
поэтому перешёл с него на if ($value === 1) ...
Хотелось бы поднять тему из старого топика
Вызываем:
Получем: Strict standards: Non-static method A::getClassName() should not be called statically Fatal error: Using $this when not in object context
Тут все ясно.
Вызываем:
Получем: Strict standards: Non-static method A::getClassName() should not be called statically, assuming $this from incompatible context B
PHP говорит, что конечно неправильно вызывать нестатический метод статически, да и $this использует не из подходящего контекста, НО ответ дает как буд-то класс B наследуется от A, WTF??? Я напомню, что E_STRICT войдет в E_ALL лишь в PHP 6!
Как мне кажется, это совершенно недопустимое поведение. У кого-нить есть мысли на этот счет?
dV, интерпретатор пишет, что нестатический метод можно вызывать только в контексте класса, к которому он относится. $this это магичная ссылка на экземпляр класса, в котором метод определен. Соответственно, интерпретатор находит контекст в виде экземпляра класса B, но не находит A. Поскольку классы в совершенно разных деревьях - не содержат общего кода - то возникает ошибка, что метод вызывается вне контекста.
Почему требуется родной контекст? Ровно по тому же принципу, как болт м8 не сможет держать гайку м6. Экземпляр обьекта - это область памяти, содержащая описанные классом данные. Например,
class Foo{ int32 number; char8 name; }
Экземпляр будет занимать 32бита (int32)+ 8 * 8 бит (char8)+ 32бит(ссылка на описание класса). описание класса будет просто хранить описание своих переменных, типа name это int, длиной 32 бита, отступ 0 бит, и т.п.
Когда класс наследуется и расширяется, этот участок памяти будет расширен новыми переменными, и расширится описание обьекта. Что делает с этим интерпретатор, когда пытается вызвать класс A в контексте класса B? Просто смотрит описание класса текущего контекста - т.е класса B - и сравнивает ссылку на описание класса контекста с ссылкой на класс A. Помимо прочего, проверяется иерархия класса B, на случай, если A есть в этой иерархии. А его нет, вот вам и стрикт еррор.
@mitallast
Я отлично понимаю почему так происходит, меня удивляет, что эта ошибка уровня E_STRICT. Я видел много программистов, кот пишут код c error_reporting E_ALL.
Если угодно, это логическая ошибка на уровне языка!
А по теме - ну реально, пример омерзительного интерфейса. Я на работе сталкиваюсь постоянно с кривыми api, которые сознательно портят из-за недостатков языковых средств, что уже вводит в бешенство :@ Посмотрите на тесты к zend sertifier engineer - over 900 вопросов, так или иначе связанными с костылями на уровне стандартной библиотеки.
Мне нравятся статически типизированные языки, и динамические. Но я терпеть не могу эту чертовую магию, связанную с преобразованием типов черт знает по какой логике! Такого, как в c++ совершенно не хочется - просто тронуться можно, пишут библиотеки для type cast!!! ИМХО, магичная динамическая типизация порождает больше проблем, чем создает.
@dV обоснуйте, почему логическая? Безусловно, может существовать метод, не требующий контекста класса и не являющийся статическим. Тогда компилятор действительно может дать поблажку, и ошибка будет на уровне varning, если не ошибаюсь.
@mitallast
Если существует метод вне контекста класса - то $this в нем неуместен.
Мы вызываем метод класса A из класса B (напомню никак не связанных между собой), но интерпретатор считает, что хоть $this не в своем контектсе, все равно берет неверное значение. И да, при error_reporting E_ALL все работает без ошибок - поэтому логическая ошибка
Представьте, что мы находимся у меня дома. Вы выкидываете ключи от своего дома в форточку, но при этом оказывается, что это мои ключи (потому что ключи в неверном контексте) и это все без ошибок :)
Ух как тема пошла в ход)) И никто не ожидал такого разворота событий))))