Silence “Déclaration ... doivent être compatibles” mises en garde en PHP 7
Après la mise à jour de PHP 7 les journaux presque étouffé sur ce genre d'erreurs:
PHP Warning: Declaration of Example::do($a, $b, $c) should be compatible with ParentOfExample::do($c = null) in Example.php on line 22548
Comment puis-je le silence de ces et seulement ces erreurs en PHP 7?
-
Avant de PHP 7, ils ont été
E_STRICT
type de mises en garde qui pourrait être facilement traitée avec des. Maintenant, ils sont tout simplement mises en garde. Depuis que j'ai ne voulez savoir sur les autres mises en garde, je ne peux pas tout simplement désactiver tous les avertissements au total. -
Je n'ai pas la capacité mentale de réécrire ces anciens Api sans parler de tous les logiciels qui les utilise. Devinez quoi, personne ne va payer pour cela. Ni moi, de les développer, en premier lieu, donc je ne suis pas le seul pour le blâme. (Tests unitaires? Pas dans la mode il y a dix ans.)
-
Je voudrais éviter toute la ruse avec
func_get_args
et semblables autant que possible. -
Pas vraiment, je veux passer à PHP 5.
-
J'ai encore envie de connaître d'autres erreurs et les avertissements.
Est-il propre et agréable façon d'accomplir cette?
- Ceux-ci sont
Warnings
, pasErrors
. Et vous ne devriez pas essayer de "silence", mais de résoudre le problème de la place. Le but de l'avertissement est pour vous dire que votre code sera exécuté dans les questions à l'avenir. - il faudrait des jours pour corriger approprié, par conséquent, cette question
- Je suis plutôt de l'espoir, de cet héritage de l'API seront désarmés avant, il y aura des problèmes. Mais ce n'est pas qui va se passer pendant un an ou deux.
- Je ne suis pas sûr que ces commentaires sont vraiment nécessaire ici. C'est vrai, dans un monde idéal, vous aurez tout le temps et l'argent heureusement corrigé du code legacy. Mais dans le monde réel, c'est souvent pas possible, ni même autorisé.
- L'OP stipule clairement que c'est une sous-optimale situation actuellement pas beaucoup peut être fait à ce sujet. Je suis totalement d'accord qu'il peut être tout à fait irréaliste de réimplémenter et ainsi éventuellement refonte complète de l'ensemble de l'API, quand il y a actuellement "pas de problème" en plus d'un supplément de quelques messages de log (gestion de point de vue, évidemment). C'est une question légitime, pas besoin d'être si dure.
- Je suis absolument d'accord et je n'ai jamais dit quoi que ce soit d'autre. Mais cela ne change pas le fait que la situation est ce qu'elle est et est causée par ce que j'ai dit.
- Je sais, ce que j'essaie de dire, c'est que même si vous avez raison, ce n'est pas aider ici. 😉
- Veuillez noter que j'ai écrit des commentaires, pas de réponse 🙂
- Pour obtenir une réponse ici... un gestionnaire d'erreur personnalisé devrait vous permettre la liberté de supprimer sélectivement tout ce que vous voulez; mais il serait sans doute de ne pas être aussi beau une solution, juste un paramètre spécifique à la fonction error_reporting drapeau.
- Pour ajouter un dernier commentaire, je dirais que, si le code n'est pas adapté pour php7 alors il ne devrait pas avoir à être exécuté dans un php7 de l'environnement. OMI code hérité inchangé qui appartient à l'environnement, il a été construit en.
- assurez-vous que vous avez raison, il va rester en cours d'exécution en vertu de PHP5 dans production tandis que PHP5 est pris en charge et mis à jour; mais j'ai obtenu d'être préparé pour la fin de sa vie
- Je veux juste ajouter que ce type de chose est un candidat de choix pour un renforcement de l'application en PHP 8. Je suggère que, quoi que vous fassiez, vous gardez cela à l'esprit.
- pourriez-vous point dans une direction où l'on peut lire à propos de ces nouveaux exécution?
- Il n'y a pas quelque chose de concret pour l'instant, mais si ce code utilisé des interfaces ou des classes abstraites dans l'héritage alors il serait déjà dur d'erreur. J'attends leur comportement pour être unifié dans une version future de PHP, éventuellement PHP 8.
- Vraiment je tiens à contester cette hypothèse, quelque part. Parce que PHP d'ores et déjà défini explicitement les interfaces. Et il y a
func_get_args()
qui permettent couramment interfaces de toute façon.
Vous devez vous connecter pour publier un commentaire.
1. Solution
Puisqu'il n'est pas toujours possible de corriger tout le code vous n'avez pas à écrire, surtout l'héritage d'un...
Ce gestionnaire d'erreur renvoie
true
pour les avertissements début avecDeclaration of
qui en gros dit à PHP qu'un avertissement a été pris en charge. C'est pourquoi le PHP ne sera pas du rapport de cet avertissement ailleurs.De Plus, ce code ne fonctionne qu'en PHP 7 ou supérieur.
Si vous voulez que cela se produise uniquement en ce qui concerne à une base de code, vous pouvez vérifier si un fichier avec un message d'erreur fait partie de la base de code ou d'une bibliothèque d'intérêt:
2. La bonne solution
Que pour, en fait, la fixation de quelqu'un d'autre héritage de code, il y a un certain nombre de cas où cela pourrait être fait entre facile et gérable. Dans les exemples ci-dessous classe
B
est une sous-classe deA
. Notez que vous n'avez pas nécessairement va supprimer toutes les LSP de violations par la suite de ces exemples.Certains cas sont assez faciles. Si dans une sous-classe, il y a un manque d'argument par défaut, il suffit d'ajouter et d'avancer. E. g. dans ce cas:
Vous feriez:
Si vous avez d'autres contraintes ajouté dans une sous-classe, les retirer de la définition, tout en se déplaçant à l'intérieur de la fonction du corps.
Vous souhaiterez peut-être utiliser des assertions ou lever une exception en fonction de la gravité.
Si vous voyez que les contraintes sont utilisées uniquement à des fins de documentation, de les déplacer là où ils appartiennent.
Si vous sous-classe qui a le moins d'arguments que d'une super-classe, et vous pouvez vous rendre facultatifs dans la super-classe, il suffit d'ajouter des espaces réservés dans la sous-classe. Compte tenu de la chaîne d'erreur:
Vous feriez:
Si vous voyez que certains arguments nécessaires dans une sous-classe, de prendre l'affaire en mains.
Parfois, il peut être plus facile de changer la méthode de superclasse pour exclure un argument facultatif au total, pour retomber à
func_get_args
de la magie. N'oubliez pas de document de l'argument manquant.Sûr que cela peut devenir très fastidieux si vous devez supprimer plus d'un argument.
Les choses deviennent beaucoup plus intéressant si vous avez de graves violations du principe de substitution. Si vous n'avez pas tapé arguments, alors il est facile. Juste faire tous les arguments supplémentaires en option, puis vérifier leur présence. Compte tenu de l'erreur:
Vous feriez:
Noter que nous ne pouvions pas utiliser
func_get_args()
ici, car il ne tient pas compte par défaut (non adopté) arguments. Il nous reste seulementfunc_num_args()
.Si vous avez un ensemble de hiérarchies de classes avec une divergence de l'interface, il peut être plus facile divergent encore. Renommer une fonction avec des conflits de définition dans chaque classe. Puis ajouter un proxy de la fonction en un seul intermédiaire parent pour ces classes:
De cette façon LSP serait encore violé, bien que sans un avertissement, mais vous risquez de tout type de chèques que vous avez dans les sous-classes.
if
si l'erreur provient d'une lib trop.Si vous doit silence l'erreur, vous pouvez déclarer la classe à l'intérieur d'un silence, immédiatement invoquées par l'expression de fonction:
Je recommande fortement à l'encontre de cela, cependant. Il est préférable de fixer votre code que pour le silence des avertissements à propos de comment il est cassé.
Si vous avez besoin de maintenir PHP 5 compatibilité, sachez que le code ci-dessus fonctionne uniquement en PHP 7, parce que PHP 5 ne sont pas uniformes de la syntaxe pour les expressions. Pour le faire fonctionner avec PHP 5, vous devez assigner la fonction à une variable avant de l'appeler (ou un nom de fonction):
@(function () {constant('nothing');})();
Pour ceux qui veulent réellement corriger votre code de sorte qu'il ne déclenche plus l'avertissement: j'ai trouvé utile d'apprendre que vous pouvez ajouter d'autres paramètres pour les méthodes de remplacement dans les sous-classes aussi longtemps que vous leur donner des valeurs par défaut. Ainsi, par exemple, tout ce qui va déclencher l'alerte:
Ce ne sera pas:
PHP 7 supprime la
E_STRICT
niveau d'erreur. Info à ce sujet peuvent être trouvées dans le PHP7 notes de compatibilité. Vous pouvez aussi lire le document de proposition où il a été discutée au cours de PHP 7 est en cours d'élaboration.Le simple fait est là: Les
E_STRICT
avis a été introduit un certain nombre de versions en arrière, dans une tentative d'en informer les développeurs qu'ils ont été à l'aide d'une mauvaise pratique, mais d'abord sans essayer de forcer tous les changements. Toutefois les versions les plus récentes et PHP 7, en particulier, sont devenues plus strictes au sujet de ces choses.L'erreur que vous rencontrez est un cas classique:
Vous avez défini une méthode dans votre classe qui substitue une méthode du même nom dans la classe parente, mais votre remplacer la méthode a un autre argument signature.
La plupart des langages de programmation modernes ne permettent cela. PHP utilisé pour permettre aux développeurs de s'en tirer avec des trucs comme ça, mais la langue est de plus en plus stricte avec chaque version, surtout maintenant avec PHP 7 -- ils sont allés avec un nouveau numéro de version majeur spécifiquement afin qu'ils puissent justifier d'apporter des changements importants qui se cassent la compatibilité descendante.
Le problème que vous avez est que vous avez déjà été en ignorant les messages d'avertissement. Votre question implique que c'est la solution que vous souhaitez continuer, mais des messages comme "stricte" et "obsolète" doit être traité comme un avertissement explicite que votre code est susceptible de se rompre dans les futures versions. En les ignorant, depuis nombre d'années, que vous avez placé dans la situation que vous avez maintenant. (Je sais que c'est pas ce que vous voulez entendre, et n'aide pas vraiment la situation, mais il est important de préciser)
Il n'est pas vraiment un travail autour du genre que vous recherchez. Le langage PHP est en pleine évolution, et si vous voulez coller avec PHP 7 votre code devra, lui aussi, évoluer. Si vraiment vous ne pouvez pas corriger le code, alors vous devrez supprimer toutes les mises en garde ou bien vivre avec ces mises en garde d'encombrer vos journaux.
L'autre chose que vous devez savoir si vous envisagez de bâton avec PHP 7 est qu'il y a un certain nombre d'autres compatibilité rompt avec cette version, y compris certains qui sont assez subtiles. Si votre code est dans un état où il a des erreurs comme celle que vous êtes en train, cela signifie qu'il a probablement été autour depuis un certain temps, et a probablement d'autres questions que vous aurez des problèmes en PHP 7. Pour ce code, je suggère de faire une vérification plus précise du code avant de s'engager à PHP 7. Si vous n'êtes pas prêt à le faire, ou ne pas être préparé pour corriger les bugs que l'on trouve (et de l'implication de votre question, c'est que vous n'êtes pas), alors je suggère que PHP 7 est probablement une mise à niveau trop loin pour vous.
Vous avez la possibilité de revenir à PHP 5.6. Je sais que vous avez dit que vous ne voulez pas faire cela, mais comme un court-moyen terme de la solution, il va rendre les choses plus facile pour vous. Franchement, je pense que cela pourrait être votre meilleure option.
func_get_args
car ils vous permettent d'obtenir exactement le même comportement avec "fluent" interfaces? Pourquoi sont-ils en forçant les utilisateurs à renoncer à la clarté des définitions d'interfaces et de recourir à différents cheats? Qui va en bénéficier?func_get_args
est encore autorisé, mais avec l'introduction de variadic les arguments d'une fonction en PHP 5.6, il y a beaucoup moins de cas d'utilisation pour elle. Je ne pense pas que ce sera obsolète n'importe quand bientôt, mais je ne pense pas que beaucoup de développeurs d'écrire du code pour PHP actuel des versions de l'aide beaucoup.Je suis d'accord: l'exemple du premier post est une mauvaise pratique.
Maintenant, si vous en avez l'exemple :
Je crois que c'est légitime de la structure du code, mais ce sera un avertissement dans mes logs parce que le
displayProperties()
n'ont pas les mêmes paramètres. De plus je ne peut pas les faire en option par l'ajout d'un= null
après eux...Suis-je en droit de penser que cet avertissement est mauvais dans cet exemple précis s'il vous plaît?
BirdManager
etDogManager
ne peut plus être utilisé en toute sécurité n'importe où queAnimalManager
peut être utilisé, et aussi ne peut pas être vérifié au moment de la compilation (depuis tout temps, vous avez uneAnimalManager
type, vous pouvez avoir affaire avec l'un de ses sous-classes). Voir en.wikipedia.org/wiki/... et en.wikipedia.org/wiki/Liskov_substitution_principle pour plus de détails.class BirdManager extends AnimalManager { public static function displayProperties(AnimalData $bird) { assert($bird instanceof BirdData);...
J'ai eu ce problème aussi. J'ai une classe qui remplace une fonction de la classe parent, mais le remplacement a num différents paramètres. Je ne peux penser à quelques solutions -, mais ne nécessitent mineur de changement de code.
-ou-
modifier les paramètres de la fonction parent, mais de rendre les paramètres supplémentaires en option (par exemple, la fonction func($var1, $var2=null) - c'est peut être plus simple et nécessite moins de changements de code. Mais peut-être pas la peine de le modifier dans le parent si il est utilisé de nombreux autres lieux. Je suis donc allé avec le n ° 1 dans mon cas.
Si possible, au lieu de passer l'extra params dans la fonction sous-classe, l'utilisation mondiale de tirer dans le supplément params. Ce n'est pas l'idéal de codage; mais une possible band-aid de toute façon.