PHP bir sınıfın dışından özel yöntemler ve özel çağrı özellikleri

7 Cevap php

Ben çok nadir özel durumlarda sınıfları dışından özel yöntemleri ve değişkenlere erişmek istiyorum.

Ben introspection kullanılmasına rağmen bu mümkün olmadığını gördüm.

Belirli bir vaka sonraki biridir:

Ben böyle bir şey istiyorum:

class Console
{
    final public static function run() {

        while (TRUE != FALSE) {
            echo "\n> ";
            $command = trim(fgets(STDIN));

            switch ($command) {
                case 'exit':
                case 'q':
                case 'quit':
                    echo "OK+\n";
                    return;
                default:
                    ob_start();
                    eval($command);
                    $out = ob_get_contents();
                    ob_end_clean();

                    print("Command: $command");
                    print("Output:\n$out");         

                    break;
            }
        }
    }
}

Bu yöntem, bu gibi kod enjekte edilmesi mümkün olmalıdır:

Class Demo
{
    private $a;

    final public function myMethod()
    {
        // some code
        Console::run();
        // some other code
    }

    final public function myPublicMethod()
    {
        return "I can run through eval()";
    }

    private function myPrivateMethod()
    {
        return "I cannot run through eval()";
    }
}

(Bu sadece bir sadeleştirme olduğunu. Gerçek bir bir soket geçer, ve daha bir sürü şey uygulamak ...)

Yani ...

Eğer sınıf Demo örneğini ve () $ demo-> myMethod ararsanız, bir konsol alırsınız: bu konsol gibi bir komut yazarken ilk yöntemi erişebilirsiniz:

> $this->myPublicMethod();

Ama başarılı ikinci bir koşamam:

> $this->myPrivateMethod();

Eğer herhangi bir fikrin var mı, ya da bunu yapmak için izin verir PHP için herhangi bir kütüphane varsa?

Thanks a lot!

7 Cevap

Sadece yöntem kamuoyuna. Eğer zor almak istiyorsanız Ama (PHP 5.3) Bu deneyebilirsiniz:

class LockedGate
{
    private function open()
    {
        return 'how did you get in here?!!';
    }
}

$reflector = new ReflectionClass('LockedGate');
$reflector->getMethod('open')->setAccessible(true);
$unlockedGate = $reflector->newInstance();
echo $unlockedGate->open();

Ben bu sorunların da bazen, ancak benim kodlama standartları aracılığıyla etrafında almak var. Özel veya korumalı fonksiyonları bir önek çizgi yani ile belirtilir

private function _myPrivateMethod()

Sonra ben sadece fonksiyon kamuoyuna.

public function _myPrivateMethod()

Işlevi kamu olmasına rağmen Yani adlandırma kuralı kamu iken özel ve gerçekten kullanılmaması gerektiğini bildirim verir.

Sorman gereken ilk soru sınıfın dışından erişmek için gerekiyorsa, neden bunu özel beyan mi, nedir? Bu kod değilse, orijinal muhtemelen özel beyan için iyi bir nedeni vardı ve doğrudan erişen bir very kötü (ve büyük ölçüde unmaintainable) uygulamadır.

EDIT: Adam V. yorumların işaret ettiği gibi, onu çağırmadan önce özel yöntem erişilebilir hale getirmek gerekir. Kod örneği bu içerecek şekilde güncellenmiş. Gerçi, bunu test değil - sadece cevabını güncel tutmak için buraya ekleyerek.

O dedi edilerek, sen Reflection Bunu gerçekleştirmek için kullanabilirsiniz. ReflectionClass, çağrı getMethod for the method you want to invoke, and then call invoke on the returned ReflectionMethod örneğini.

Bir kod örneği (ben henüz denemedim ama, bu yüzden hatalar olabilir) gibi görünebilir

$demo = new Demo();
$reflection_class = new ReflectionClass("Demo");
$reflection_method = $reflection_class->getMethod("myPrivateMethod");
$reflection_method->setAccessible(true);
$result = $reflection_method->invoke($demo, NULL);

İşte bu tür aramaları bir hat yapmak için kullanılabilecek diğer yanıtları bir varyasyonu:

public function callPrivateMethod($object, $methodName)
{
    $reflectionClass = new \ReflectionClass($object);
    $reflectionMethod = $reflectionClass->getMethod($methodName);
    $reflectionMethod->setAccessible(true);

    $params = array_slice(func_get_args(), 2); //get all the parameters after $methodName
    return $reflectionMethod->invokeArgs($object, $params);
}

Ben gerçekten bazı özel yöntemler yürütmek istiyorsanız ReflectionClass tek alternatif olduğunu tahmin. Sadece privat veya korumalı özelliklere okuma erişimi gerekiyorsa neyse, bu kodu kullanabilirsiniz:

<?php
class Demo
{
    private $foo = "bar";
}

$demo = new Demo();

// Will return an object with public, private and protected properties in public scope.
$properties = json_decode(preg_replace('/\\\\u([0-9a-f]{4})|'.get_class($demo).'/i', '', json_encode((array) $demo)));

?>

Eğer yöntemi tanımlanır sınıfında bir yöntem eklendi mümkün iseniz, () dahili call_user_method kullandığı yöntem ekleyebilirsiniz. Bu PHP 5.2.x ile de çalışıyor

<?php
class SomeClass {
    public function callprivate($methodName) {
         call_user_method(array($this, $methodName));
    }

    private function somePrivateMethod() {
         echo 'test';
    }
}


$object = new SomeClass();
$object->callprivate('somePrivateMethod');

Yanıt yönteme kamu konur. Yapacaksın ne olursa olsun hile o adam geliştiricileri anlaşılır olmaz. Örneğin bazı diğer kod bu işlevi Demo sınıfa bakarak kamu olarak erişilmiş olduğunu bilmiyorum.

Bir şey daha. that console can access the first method writing a command like: . Bu nasıl mümkün olabilir? Konsol $ this ile demo sınıf fonksiyonları erişemiyor.