declaration of should be compatible with php 7

Comments

gunnicom commented Nov 23, 2016

Issue

In apache error.log there are many log entries like:

They are all over the code and thus making it impossible to debug with the apache error log.
Disabling

STRICT in php.ini is not enough.

Expected Behavior

Theses warnings should not be there if programming is correct.

Actual Behavior

Too much Warnings in the error log, to debug «real» errors.

Possible Fix

Functions from derived classes should be compatible with parent class.
(Most are easy fixes with adding optional parameters and not using this parameter, or changing pass by ref to pass by value. Email->save(. ) seems a bit more complicate to fix. )

Steps to Reproduce

Context

As it does not affect function directly, does not need to be high prio.

Your Environment

The text was updated successfully, but these errors were encountered:

We are unable to convert the task to an issue at this time. Please try again.

The issue was successfully created but we are unable to update the comment at this time.

gunnicom commented Nov 23, 2016

Patterns i found so far:
Function saveOptions needs type hint «array»:

Function displayInput should have parameter passed by value:

Declaration of SugarWidgetFielduser_name::displayInput(&$layout_def) should be compatible with SugarWidgetFieldVarchar::displayInput($layout_def) in /var/www/sugar/include/generic/SugarWidgets/SugarWidgetFielduser_name.php

Function process should have the optional parameter «$id=null» added:

These should be the low hanging fruits. Functions like Email->save(. ) need some more look to find a solution.

Источник

С переходом на PHP 7 лог ошибок по многим старым проектам оказался забит под завязку сообщениями подобного вида:

Это только один пример ошибки. Вариантов таких ошибок может быть множество.

Усложняют проблему следующие моменты:

С учётом вышесказанного, как можно освободить логи сервера только от этих ошибок?

3 ответа 3

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

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

Вы захотите использовать assert или кидать исключение, в зависимости от серьезности ошибки.

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

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

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

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

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

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

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

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

Такие ошибки как были предусмотрены с PHP 5.0 и самого появления type hinting в PHP так и остались.

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

Источник

после обновления до PHP 7 журналы почти задохнулись от такого рода ошибок:

как заставить замолчать эти и только эти ошибки в PHP 7?

у меня нет умственной способности переписывать эти устаревшие API, даже не упоминая все программное обеспечение, которое их использует. Знаешь что, за это тоже никто не заплатит. Ни я не развиваю их в первую очередь, поэтому я не виноват. (Модульные тесты? Не в моде десять лет назад.)

Я хотел бы избежать любой обман С func_get_args и похож как бы вероятный.

на самом деле я не хочу переходить на PHP 5.

Я все еще хочу знать о других ошибках и предупреждениях.

есть ли чистый и приятный способ достичь этого?

6 ответов

1. Решение

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

этот обработчик ошибок возвращает true для предупреждения начинаются с Declaration of что в основном говорит PHP о том, что было сделано предупреждение. Вот почему PHP не будет сообщать об этом предупреждении в другом месте.

кроме того, этот код будет работать только в PHP 7 или выше.

если вы хотите это чтобы это произошло только в отношении конкретной кодовой базы, вы можете проверить, принадлежит ли файл с ошибкой этой кодовой базе или библиотеке:

Читайте также:  К чему снится щекотание во сне

2. Правильное решение

некоторые случаи довольно просты. Если в подклассе отсутствует аргумент по умолчанию, просто добавьте его и двигайтесь дальше. Е. Г. в этом случае:

вы могли бы сделать:

если в подклассе добавлены дополнительные ограничения, удалите их из определения, перемещаясь внутри тела функции.

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

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

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

вы могли бы сделать:

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

иногда может быть проще изменить метод суперкласса, чтобы полностью исключить необязательный аргумент, возвращаясь к func_get_args магия. Не забудьте задокументировать отсутствующий аргумент.

уверен, это может стать очень утомительным, если вам нужно удалить более одного аргумента.

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

вы могли бы сделать:

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

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

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

Если вы должны тишина ошибку, вы можете объявить класс внутри притихли, сразу-вызывается функция выражения:

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

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

PHP 7 удаляет E_STRICT ошибка. Информацию об этом можно найти в PHP7 совместимость Примечания. Вы также можете прочитать предложение документ где это обсуждалось во время разработки PHP 7.

простой факт заключается в следующем: E_STRICT уведомления были введены несколько версий назад, в попытке уведомить разработчиков о том, что они используют плохую практику, но первоначально без попытки принудительных изменений. Однако недавно версии, и PHP 7 в частности, стали более строгими в отношении этих вещей.

ошибка, которую вы испытываете, является классическим случаем:

вы определили метод в своем классе, который переопределяет метод с тем же именем в родительском классе, но ваш метод override имеет другую сигнатуру аргумента.

проблема заключается в том, что вы уже игнорировали предупреждающие сообщения. Ваш вопрос подразумевает, что это решение, которое вы хотите продолжить, но такие сообщения, как «strict » и» deprecated», должны рассматриваться как явное предупреждение о том, что ваш код, вероятно перерыв в будущих версиях. Игнорируя их в течение последних нескольких лет, вы фактически ставите себя в ситуацию, в которой находитесь сейчас. (Я знаю, что это не то, что вы хотите услышать, и на самом деле не помогает ситуации сейчас, но важно, чтобы это было ясно)

на самом деле нет такой работы, которую вы ищете. язык PHP развивается, и если вы хотите придерживаться PHP 7, ваш код тоже должен будет развиваться. Если вы действительно не можете исправить код, тогда вам придется либо подавить все предупреждения, либо жить с этими предупреждениями, загромождающими ваши журналы.

еще одна вещь, которую вам нужно знать, если вы планируете придерживаться PHP 7, заключается в том, что есть ряд других разрывов совместимости с этой версией, в том числе некоторые из них довольно тонкие. Если ваш код находится в состоянии, когда у него есть ошибки, подобные той, о которой вы сообщаете, это означает, что он, вероятно, был довольно долго и, вероятно, имеет другие проблемы, которые вызовут вас проблемы в PHP 7. Для такого кода я бы предложил сделать более тщательный аудит кода перед фиксацией на PHP 7. Если вы не готовы сделать это или не готовы исправить найденные ошибки (и вывод из вашего вопроса заключается в том, что вы этого не делаете), я бы предположил, что PHP 7, вероятно, является обновлением слишком далеко для вас.

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

Я согласен : пример в первом посте-это плохая практика. Теперь что если у вас есть такой пример :

Читайте также:  Twcu что это за процесс

Я считаю, что это законная структура кода, тем не менее это вызовет предупреждение в моих журналах, потому что «displayProperties» не имеют одинаковых параметров. Кроме того, я не могу сделать их необязательными, добавив после них «= null».

Если возможно, вместо передачи дополнительных параметров в функции подкласса используйте global для извлечения дополнительных параметров. Это не идеальное кодирование; но возможный пластырь в любом случае.

Источник

Тишина «Декларация. должна быть совместимой» в PHP 7

После обновления до PHP 7 журналы почти задохнулись от таких ошибок:

Как отключить эти и только эти ошибки в PHP 7?

До появления PHP 7 они были E_STRICT типа предупреждений с которыми можно было легко справиться. Теперь они просто старые предупреждения. Поскольку я do хочу знать о других предупреждениях, я не могу полностью отключить все предупреждения.

У меня нет умственной способности переписывать эти устаревшие API, даже не упоминая все программное обеспечение, которое их использует. Угадайте, что, никто не заплатит за это тоже. Я не разрабатываю их, в первую очередь, поэтому я не виноват. (Единичные тесты? Не в моде десять лет назад.)

Я хотел бы избегать любых обманщиков с func_get_args и, насколько это возможно, как можно больше.

На самом деле я не хочу перейти на PHP 5.

Я все еще хочу узнать о других ошибках и предупреждениях.

Есть ли чистый и хороший способ выполнить это?

ОТВЕТЫ

Ответ 1

1. Обходной путь

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

Этот обработчик ошибок возвращает true для предупреждений, начинающихся с Declaration of которое в основном говорит PHP, что предупреждение было обработано. Вот почему PHP не будет сообщать об этом предупреждении в другом месте.

Кроме того, этот код будет работать только в PHP 7 или выше.

Если вы хотите, чтобы это происходило только в отношении конкретной кодовой базы, то вы можете проверить, принадлежит ли файл с ошибкой той кодовой базе или интересующей библиотеке:

2. Правильное решение

Что касается фактического исправления другого унаследованного кода, существует ряд случаев, когда это можно сделать между простым и управляемым. В приведенных ниже примерах класс B является подклассом A Обратите внимание, что вы не обязательно удалите любые нарушения LSP, следуя этим примерам.

Некоторые случаи довольно просты. Если в подклассе отсутствует аргумент по умолчанию, просто добавьте его и двигайтесь дальше. Например, в этом случае:

Если в подкласс добавлены дополнительные ограничения, удалите их из определения, перемещаясь внутри тела функции.

Вы можете использовать утверждения или выдать исключение в зависимости от серьезности.

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

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

Если вы видите некоторые аргументы, требуемые в подклассе, возьмите дело в свои руки.

Конечно, это может стать очень утомительным, если вам нужно удалить более одного аргумента.

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

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

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

Ответ 2

Если вы должны отключить эту ошибку, вы можете объявить класс внутри принудительного выражения с немедленным вызовом:

Я бы настоятельно рекомендовал против этого. Лучше исправить свой код, чем отключить предупреждения о том, как он сломался.

Если вам нужно поддерживать совместимость с PHP 5, имейте в виду, что приведенный выше код работает только в PHP 7, потому что PHP 5 не имеет единого синтаксиса для выражений. Чтобы заставить его работать с PHP 5, вам нужно назначить функцию переменной перед ее вызовом (или сделать ее именованной функцией):

Ответ 3

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

Ответ 4

Простой факт: уведомления E_STRICT были введены несколько версий назад, в попытке уведомить разработчиков о том, что они используют плохую практику, но изначально без каких-либо изменений. Однако последние версии и PHP 7, в частности, стали более строгими в отношении этих вещей.

Вы определили метод в своем классе, который переопределяет метод с тем же именем в родительском классе, но ваш метод переопределения имеет другую сигнатуру аргумента.

Проблема заключается в том, что вы уже игнорировали предупреждающие сообщения. Ваш вопрос подразумевает, что это решение, которое вы хотите продолжить, но сообщения типа «строгое» и «устаревшее» следует рассматривать как явное предупреждение о том, что ваш код, вероятно, сломается в будущих версиях. Путем игнорирования их в течение последних нескольких лет вы фактически поставили себя в ситуацию, в которой вы сейчас находитесь. (Я знаю, что не то, что вы хотите услышать, и на самом деле не помогает сейчас, но важно четко прояснить)

Читайте также:  Sony или asus что лучше

На самом деле не существует той работы, которую вы ищете. Язык PHP развивается, и если вы хотите придерживаться PHP 7, ваш код также должен развиваться. Если вы действительно не можете исправить код, вам придется либо подавить все предупреждения, либо жить с этими предупреждениями, загромождающими ваши журналы.

Другое, что вам нужно знать, если вы планируете придерживаться PHP 7, заключается в том, что с этой версией существует ряд других разрывов совместимости, в том числе некоторые, которые довольно тонкие. Если ваш код находится в состоянии, в котором он имеет ошибки, подобные тому, который вы сообщаете, это означает, что он, вероятно, довольно долгое время, и, вероятно, имеет другие проблемы, которые вызовут проблемы в PHP 7. Для такого кода, Я бы предложил провести более тщательный аудит кода, прежде чем совершать PHP 7. Если вы не готовы сделать это или не готовы исправить найденные ошибки (и подразумевается, что ваш вопрос таков, что вы не являетесь), то я бы предположил, что PHP 7, вероятно, слишком сильно для вас.

У вас есть возможность вернуться к PHP 5.6. Я знаю, что вы сказали, что не хотите этого делать, но в краткосрочной перспективе это облегчит вам жизнь. Честно говоря, я думаю, это может быть вашим лучшим вариантом.

Ответ 5

Я считаю, что это законная структура кода, тем не менее это вызовет предупреждение в моих журналах, потому что «displayProperties» не имеют одинаковых параметров. Более того, я не могу сделать их необязательными, добавив после них «= null».

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

Ответ 6

Если возможно, вместо передачи дополнительных параметров в функции подкласса, используйте global, чтобы вытащить дополнительные параметры. Это не идеальное кодирование; но возможная полосовая помощь в любом случае.

Источник

С переходом на PHP 7 лог ошибок по многим старым проектам оказался забит под завязку сообщениями подобного вида:

Это только один пример ошибки. Вариантов таких ошибок может быть множество.

Усложняют проблему следующие моменты:

С учётом вышесказанного, как можно освободить логи сервера только от этих ошибок?

Ответы (3 шт):

Не всегда возможно исправить старый код, который вы, к тому же, не писали. Например, берёте какую-нибудь библиотеку из PEAR и наслаждаетесь. Про код, не знавший тестов, просто молчу. Потому можно сделать так:

Этот обработчик ошибок помечает предупреждения как обработанные, возвращая истину для всех сообщений, начинающихся с указанной строки. Такие обработанные преду­преж­де­ния не пойдут на запись в лог. Код будет работать только в PHP 7 и более поздних.

Если же проблема возникает только в какой-то части кода, которую можно выделить по ката­логу или путям до файлов, то можно глушить эти ошибки только для определённых файлов:

Такие ошибки как были предусмотрены с PHP 5.0 и самого появления type hinting в PHP так и остались.

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

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

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

Вы захотите использовать assert или кидать исключение, в зависимости от серьезности ошибки.

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

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

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

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

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

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

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

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

Источник

Образовательный портал