ti-enxame.com

É possível sobrescrever uma função em PHP

Você pode declarar uma função como esta ...

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

E então redeclare um pouco assim ...

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

É possível sobrescrever uma função dessa maneira?

De qualquer forma?

57
Mark Lalor

Editar

Para endereçar comentários que esta resposta não endereça diretamente a pergunta original . Se você chegou aqui de uma pesquisa no Google, comece aqui

Existe uma função disponível chamada override_function que realmente se encaixa na conta. No entanto, dado que esta função é parte da extensão The Advanced PHP Debugger , é difícil fazer um argumento que override_function() seja destinado ao uso em produção. Portanto, eu diria "Não", não é possível sobrescrever uma função com a intenção que o questionador original tinha em mente.

Resposta Original

É aqui que você deve aproveitar a OOP, especificamente o 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();
89
Peter Bailey

Patch de Macaco no namespace php> = 5.3

Um método menos evasivo do que modificar o interpretador é o patch de macaco.

Macaco de patch é a arte de substituir a implementação real com um "patch" semelhante de sua preferência. 

Habilidades ninja

Antes de você poder fazer um patch como PHP Ninja primeiro precisamos entender os namespaces dos PHPs.

Desde PHP 5.3 nós fomos introduzidos a namespaces que você pode, à primeira vista, denotar como sendo algo parecido com pacotes Java, mas não é exatamente o mesmo. Namespaces, em PHP, é uma maneira de encapsular o escopo criando uma hierarquia de foco, especialmente para funções e constantes. Como este tópico, fallback para funções globais , pretende explicar.

Se você não fornece um namespace ao chamar uma função, PHP primeiro procura no namespace atual e depois desce a hierarquia até encontrar a primeira função declarada dentro daquele namespace prefixado e executa naquela. Para nosso exemplo, se você estiver chamando print_r(); de namespace My\Awesome\Namespace; What PHP é procurar primeiro por uma função chamada My\Awesome\Namespace\print_r(); depois My\Awesome\print_r(); depois My\print_r(); até encontrar o PHP função interna no namespace global \print_r();.

Você não poderá definir um function print_r($object) {} no namespace global porque isso causará uma colisão de nomes, já que uma função com esse nome já existe.

Espere um erro fatal para pessoas como:

Fatal error: Cannot redeclare print_r()

Mas nada impede que você faça exatamente isso dentro do escopo de um namespace.

Remendando o macaco

Digamos que você tenha um script usando várias chamadas print_r();.

Exemplo:

<?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);

Mas, mais tarde, você muda de ideia e deseja a saída envolvida em tags <pre></pre>. Já aconteceu com você? 

Antes de você ir e mudar cada chamada para print_r(); considere o patch do macaco.

Exemplo:

<?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);
    }

Seu script agora estará usando MyNamespace\print_r(); em vez do global \print_r();

Funciona muito bem para testes de unidade de simulação.

nJoy!

57
nickl-

Dê uma olhada em override_function para substituir as funções.

override_function - Substitui funções embutidas

Exemplo:

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

a resposta curta é não, você não pode sobrescrever uma função uma vez que está no escopo da função PHP.

o seu melhor de usar funções anônimas como assim

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

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

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

13
RobertPitt

Você não pode redeclarar quaisquer funções no PHP. Você pode, no entanto, substituí-los. Check out substituindo funções bem como renomeando funções para salvar a função que você está sobrescrevendo se você quiser.

Portanto, lembre-se de que, ao substituir uma função, você a perde. Você pode querer considerar mantê-lo, mas em um nome diferente. Apenas dizendo.

Além disso, se essas forem funções em classes que você deseja substituir, basta criar uma subclasse e redeclarar a função em sua classe sem precisar rename_function e override_function.

Exemplo:

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

Eu incluiria todas as funções de um caso em um arquivo include, e as outras em outro include.

Por exemplo, simple.inc conteria function boofoo() { simple } e really.inc conteria function boofoo() { really }

Ajuda a legibilidade/manutenção do seu programa, tendo todas as funções do mesmo tipo no mesmo inc.

Então, no topo do seu módulo principal

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

Você poderia usar a extensão PECL

mas isso é uma má prática na minha opinião. Você está usando funções, mas confira o padrão de design Decorator . Pode emprestar a idéia básica disso.

3
Gordon

Não, isso será um problema. PHP Funções Variáveis ​​

1
Chris

Uma solução para o caso relacionado em que você tem um arquivo de inclusão A que pode ser editado e deseja substituir algumas de suas funções em um arquivo de inclusão B (ou no arquivo principal):

Arquivo principal:

<?php
$Override=true; // An argument used in A.php
include ("A.php");
include ("B.php");
F1();
?>

Incluir Arquivo A:

<?php
if ([email protected]$Override) {
   function F1 () {echo "This is F1() in A";}
}
?>

Incluir Arquivo B:

<?php
   function F1 () {echo "This is F1() in B";}
?>

Navegar para o arquivo principal exibe " isto é F1 () em B ".

1
David Spector

Dependendo da situação em que você precisa disso, talvez você possa usar funções anônimas como esta:

$greet = function($name)
{
    echo('Hello ' . $name);
};

$greet('World');

... então você pode definir uma nova função para a variável dada a qualquer momento

0
esud