¿Es posible sobrescribir una función en PHP?

7 minutos de lectura

Puedes declarar una función como esta…

function ihatefooexamples(){
  return "boo-foo!";
};

Y luego redeclarar es algo así…

if ($_GET['foolevel'] == 10){
  function ihatefooexamples(){
    return "really boo-foo";
  };
};

¿Es posible sobrescribir una función de esa manera?

¿De todos modos?

  • posible duplicado de Php redefine Class Methods OR Class, ¿es posible reemplazar una función en php (como el correo) y hacer que haga otra cosa?

    – fuera

    10 de febrero de 2012 a las 17:14


  • … ¿Es posible reemplazar las funciones de PHP (monkeypatch)?

    – fuera

    10 de febrero de 2012 a las 17:21


  • Sería maravilloso si PHP se extendiera para que ‘unset’ pudiera usarse para eliminar una definición de función preparatoria para redefinirla usando ‘function’.

    –David Spector

    5 de junio de 2019 a las 12:51

¿Es posible sobrescribir una funcion en PHP
pedro bailey

Editar

Para abordar los comentarios de que esta respuesta no aborda directamente la pregunta original. Si llegaste aquí a partir de una búsqueda en Google, comienza aquí

Hay una función disponible llamada anular_función que realmente encaja a la perfección. Sin embargo, dado que esta función es parte de El depurador avanzado de PHP extensión, es difícil argumentar que override_function() está diseñado para uso de producción. Por lo tanto, diría “No”, no es posible sobrescribir una función con la intención que tenía en mente el autor de la pregunta original.

Respuesta Original

Aquí es donde debes aprovechar la programación orientada a objetos, específicamente el polimorfismo.

interface Fooable
{
    public function ihatefooexamples();
}

class Foo implements Fooable
{
    public function ihatefooexamples()
    {
        return "boo-foo!";
    }
}

class FooBar implements Fooable
{
    public function ihatefooexamples()
    {
        return "really boo-foo";
    }
}

$foo = new Foo();

if (10 == $_GET['foolevel']) {
    $foo = new FooBar();
}

echo $foo->ihatefooexamples();

  • +1 por resolver el problema real, en lugar de simplemente tratar de responder la pregunta exacta…

    – ircmaxell

    1 de septiembre de 2010 a las 17:52

  • El único cambio que haría sería poner el $foo = new Foo() en un else bloque, en caso de que el constructor (a) sea costoso o (b) tenga efectos secundarios.

    – Austin Hyde

    1 de septiembre de 2010 a las 18:02

  • @Gordon Estás analizando demasiado. Creo que está bastante claro que esto es solo un ejemplo.

    –Peter Bailey

    1 de septiembre de 2010 a las 20:34

  • No estoy de acuerdo, con esta respuesta, la pregunta dice claramente “función”, no “método”, está claro que el contexto no es una Clase. Vine aquí de una búsqueda en Google, en este momento estoy usando una biblioteca heredada que no es OO y esta respuesta es simplemente inútil.

    – mastazi

    18 de agosto de 2015 a las 3:36

  • @mastazi Gracias por señalarme que esta es una de las principales respuestas dadas por las búsquedas de Google sobre esta pregunta. He actualizado la respuesta con información que debería ayudar a futuros buscadores de respuestas con objetivos similares a los tuyos.

    –Peter Bailey

    11/10/2016 a las 14:17

1646751674 135 ¿Es posible sobrescribir una funcion en PHP
Nickl-

Parche de mono en el espacio de nombres php> = 5.3

Un método menos evasivo que modificar el intérprete es el parche de mono.

Monkey patching es el arte de reemplazar la implementación real con un “parche” similar propio.

Habilidades ninja

Antes de que puedas parchear como un PHP Ninja, primero tenemos que entender los espacios de nombres de PHP.

Desde PHP 5.3, nos presentaron los espacios de nombres que, a primera vista, podría indicar que son equivalentes a algo como paquetes de Java, pero no es exactamente lo mismo. Los espacios de nombres, en PHP, son una forma de encapsular el alcance mediante la creación de una jerarquía de enfoque, especialmente para funciones y constantes. Como este tema, respaldo a las funciones globalespretende explicar.

Si usted no proporcione un espacio de nombres al llamar a una función, PHP primero busca en el espacio de nombres actual y luego baja en la jerarquía hasta que encuentra la primera función declarada dentro de ese espacio de nombres prefijado y la ejecuta. Para nuestro ejemplo, si está llamando print_r(); desde namespace My\Awesome\Namespace; Lo que hace PHP es buscar primero una función llamada My\Awesome\Namespace\print_r(); luego My\Awesome\print_r(); luego My\print_r(); hasta que encuentre la función incorporada de PHP en el espacio de nombres global \print_r();.

No podrá definir un function print_r($object) {} en el espacio de nombres global porque esto provocará una colisión de nombres ya que ya existe una función con ese nombre.

Espere un error fatal como:

Fatal error: Cannot redeclare print_r()

Sin embargo, nada le impide hacer exactamente eso dentro del alcance de un espacio de nombres.

Parcheando al mono

Digamos que tiene un script que usa varios print_r(); llamadas

Ejemplo:

<?php
     print_r($some_object);
     // do some stuff
     print_r($another_object);
     // do some other stuff
     print_r($data_object);
     // do more stuff
     print_r($debug_object);

Pero luego cambia de opinión y desea que la salida esté envuelta en <pre></pre> etiquetas en su lugar. ¿Alguna vez te ha pasado?

Antes de ir y cambiar cada llamada a print_r(); considere parchear a los monos en su lugar.

Ejemplo:

<?php
    namespace MyNamespace {
        function print_r($object) 
        {
            echo "<pre>", \print_r($object, true), "</pre>"; 
        }

        print_r($some_object);
        // do some stuff
        print_r($another_object);
        // do some other stuff
        print_r($data_object);
        // do more stuff
        print_r($debug_object);
    }

Su secuencia de comandos ahora estará usando MyNamespace\print_r(); en lugar del mundial \print_r();

Funciona muy bien para burlarse de las pruebas unitarias.

¡Alegría!

  • ¡Un enfoque realmente valioso! Gracias por compartir

    –Nico Haase

    21 de marzo de 2016 a las 14:54

  • ¡Esta es una respuesta increíblemente útil para aquellos que están atascados con bibliotecas heredadas que no son oo!

    – mastazi

    11/10/2016 a las 21:32

  • No puedo hacer que esto funcione cuando las funciones A, B y C están definidas en un archivo de inclusión grande existente (no quiero cambiarlos, porque otras páginas los usan) y quiero anular solo la función B en el principal archivo, donde B se define en un archivo de inclusión separado. Supongo que los espacios de nombres no funcionan en este caso.

    –David Spector

    22 de octubre de 2018 a las 14:03

  • @DavidSpector necesita el espacio de nombres donde se vuelve a declarar lo que desea hacer en un archivo de inclusión separado, por ejemplo. namespace SeparateInclude {} luego, en el archivo principal, puede volver a usar el espacio de nombres namespace MainFile {}incluye el nuevo archivo create monkey patch function B() de nuevo en el archivo principal que llama \SeparateInclude\B();. Cuando usted llama B(); en el archivo principal ahora llama \MainFile\B(); que llama \SeparateInclude\B(); evitando con éxito \B(); del archivo de inclusión grande/original.

    -nickl-

    5 de junio de 2019 a las 5:18

  • ¿Realmente baja los espacios de nombres porque no parece hacerlo? Parece que A\B\C tratando de usar una “f” buscará \A\B\C\f o \f (“nivel superior f”) solamente, los \ son LITERALMENTE nombres con \ al principio solo teniendo significado especial (como concatenar o no el espacio de nombres actual como prefijo, o no hacer esto): ¿puede confirmarlo? ¡Porque tendría sentido si lo hiciera! Pero es PHP, por lo que no harán eso (lo intenté y leí mucho, esto me dio un rayo de esperanza: ¡aplasta o muéstrame lo que me perdí, por favor! PHP5 sería genial para la respuesta, por cierto)

    – Alec Teal

    7 sep 2019 a las 19:54

Mira esto override_function para anular las funciones.

override_function — Anula las funciones integradas

Ejemplo:

override_function('test', '$a,$b', 'echo "DOING TEST"; return $a * $b;');

  • este es un buen punto, pero si la función es grande, ¡no es bueno pasar cadenas tan largas! :(, ¡otro punto es que esto solo se puede usar para funciones integradas y no definidas por el usuario!

    – RobertPitt

    1 de septiembre de 2010 a las 17:39


  • @RobertPitt: De acuerdo, esto es lo que tenemos en este momento y su solución se ve bien, pero eso depende de la versión de php que se use.

    – Sarfraz

    1 de septiembre de 2010 a las 17:41

  • ¿Por qué no querrías estar en una versión de php <5.3.0? a menos que esté creando un guión que se venderá al por menor/lanzará al público, entonces tiene un punto válido.

    – RobertPitt

    1 de septiembre de 2010 a las 17:44

  • @RobertPitt: estoy usando 5.3 y espero que OP también esté usando lo mismo 🙂

    – Sarfraz

    1 de septiembre de 2010 a las 17:46


  • Intenté usar la función de anulación, pero es parte de PECL y PECL debe configurarse primero.

    usuario379888

    28 de diciembre de 2017 a las 10:19

La respuesta corta es no, no puede sobrescribir una función una vez que está en el alcance de la función PHP.

lo mejor de usar funciones anónimas como esta

$ihatefooexamples = function()
{
  return "boo-foo!";
}

//...
unset($ihatefooexamples);
$ihatefooexamples = function()
{
   return "really boo-foo";
}

http://php.net/manual/en/functions.anonymous.php

No puede volver a declarar ninguna función en PHP. Sin embargo, puede anularlos. Verificar anular funciones así como también funciones de cambio de nombre para guardar la función que está anulando si lo desea.

Por lo tanto, tenga en cuenta que cuando anula una función, la pierde. Es posible que desee considerar mantenerlo, pero con un nombre diferente. Solo digo.

Además, si estas son funciones en clases que desea anular, solo necesitaría crear una subclase y volver a declarar la función en su clase sin tener que hacer rename_function y override_function.

Ejemplo:

rename_function('mysql_connect', 'original_mysql_connect' );
override_function('mysql_connect', '$a,$b', 'echo "DOING MY FUNCTION INSTEAD"; return $a * $b;');

  • Esto requiere la extensión APD PECL y está desactualizado. La última versión es de 2004. pecl.php.net/paquete/apd

    – jperelli

    26 de julio de 2013 a las 14:32


1646751675 167 ¿Es posible sobrescribir una funcion en PHP
Deja Vu

Incluiría todas las funciones de un caso en un include archivo, y los demás en otro include.

Por ejemplo simple.inc contendría function boofoo() { simple } y really.inc contendría function boofoo() { really }

Ayuda a la legibilidad/mantenimiento de su programa, teniendo todas las funciones del mismo tipo en el mismo inc.

Luego, en la parte superior de su módulo principal

  if ($_GET['foolevel'] == 10) {
    include "really.inc";
  }
  else {
    include "simple.inc";
  }

  • Esto requiere la extensión APD PECL y está desactualizado. La última versión es de 2004. pecl.php.net/paquete/apd

    – jperelli

    26 de julio de 2013 a las 14:32


1646751675 814 ¿Es posible sobrescribir una funcion en PHP
gordon

Podrías usar la extensión PECL

pero eso es una mala práctica en mi opinión. Estás usando funciones, pero echa un vistazo a la Patrón de diseño de decorador. Puede tomar prestada la idea básica de ella.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad