PHP üst sınıftan sınıf çocuk ad alın

5 Cevap php

Ben farklı dosyaları aşağıdaki sınıfları var varsayarsak:

<?php
    namespace MyNS;

    class superclass {

        public function getNamespace(){
            return __NAMESPACE__;
        }
    }
?>

<?php
    namespace MyNS\SubNS;

    class childclass extends superclass { }
?>

Ben "çocuğu olarak" örneğini ve getNamespace ararsanız () it "MyNS" döndürür.

Yöntemi redeclaring olmadan çocuk sınıfından geçerli ad almak için herhangi bir yolu var mı?

Her sınıfta bir statik $ ad değişkeni oluşturma ve kullanma onu referans için super::$namespace başvurdu ettik ama bu sadece çok şık gelmiyor.

5 Cevap

__NAMESPACE__ derleme zamanında sadece yararlı olduğu anlamına, bir derleme zamanı sabittir. Geçerli ad ile kendini yerini alacak takılı bir makro olarak bunu düşünebilirsiniz. Bu nedenle, bir çocuğun sınıfın ad başvurmak için bir süper sınıfta __NAMESPACE__ almak için hiçbir yolu yoktur. Sen zaten yapıyoruz gibi, her çocuğun sınıfta atandığı değişken çeşit başvurmak zorunda olacak.

Alternatif olarak, bir sınıfın ad adını almak için yansıma kullanabilirsiniz:

$reflector = new ReflectionClass('A\\Foo'); // class Foo of namespace A
var_dump($reflector->getNamespaceName());

the PHP manual daha fazla (bitmemiş) belgelerine bakın. PHP 5.3.0 'olmak veya sonraki yansıması kullanmak gerekir unutmayın.

Ayrıca getNamespace () yöntemi yapabilirsiniz:

return get_class($this);

Çocuğu olarak çağrıldığında, sonucu olacaktır:

MyNS\SubNS\childclass

Eğer ucunda sınıf adını istemiyorsanız, sadece son \ dan sonuna kadar her şeyi kesmek.

Benim durumumda, ben bazı sınıfta call_user_func() ile statik yöntemini çağırabilirsiniz üst sınıfta bir yöntem oluşturmak için gerekli. Eğer tam sınıf adını biliyorsanız, call_user_func() hiçbir problemo yapabilirsiniz. Hüner alt sınıf 'ad statik yöntemi çağırmak oldu.

Bu yüzden sahip yani

\MyTools\AbstractParent
\Something\Else\Foo extends \MyTools\AbstractParent
\Something\Else\Bar extends \MyTools\AbstractParent

Biz şimdi AbstractParent bir yöntem gerekir. Altsınıftan adlandırılan bu yöntem, Foo kendi ad prepending tarafından Bar::doMe() çağırmak mümkün olacak.

Burada dinamik çağrı ile bunu nasıl:

namespace MyTools;
abstract class AbstractParent {
    public static method doMe(){}

    public function callSomethingStaticInClass($class){
        // current namespace IS NOT MyTools
        // so you cannot use __NAMESPACE__
        $currentClass = get_class($this);
        $refl = new ReflectionClass($currentClass);
        $namespace = $refl->getNamespaceName();

        // now we know what the subclass namespace is...
        // so we prefix the short class name
        $class =  $namespace . '\\' . $class;
        $method = 'doMe';

        return call_user_func(array( $class, $method ));
    }

};

namespace Something\Else;
class Foo extends AbstractParent { }
class Bar extends AbstractParent { }

$foo = new Foo();
$foo->callSomethingStaticInClass('Bar');

Onun yerine get_class($this) ile statik çağrısı ile iş yapmak için get_called_class()

Umarım bu yardımcı olur.

/* First Namespace */
namespace MyNS {
    class superclass {
        /* Functions to get the current namespace
         *  If $object is null then return the
         *  namespace of the class where the
         *  method exists, if not null, return
         *  the namespace of the class called.
         */
        public static function get_namespace($object = null) {
            if($object !== null) {
                $tmp = (($object != "self") && (get_called_class() != get_class($object))) ? get_class($object) : get_called_class();
                $tmparr = explode("\\", $tmp);
                $class = array_pop($tmparr);
                return join("\\", $tmparr);
            } else {
                return __NAMESPACE__;
            }
        }
        public static function get_current_namespace() {
            return self::get_namespace(self);
        }

        public function call_static_method($class_name, $method_name, $arguments = array()) {
            $class = "\\" . $this->get_namespace($this) . "\\{$class_name}";
            if(method_exists($class, $method_name)) {
                if(count($arguments) > 0) return $class::$method_name($arguments);
                return $class::$method_name();
            }
            return "Method ({$method_name}) Does not exist in class ({$class})";
        }

        public function call_user_method($object, $method_name, $arguments = array()) {
            if(method_exists($object, $method_name)) {
                if(count($arguments) > 0) return $object->$method_name($arguments);
                return $object->$method_name();
            }
        }
    }

    class superclass2 extends superclass {
        public static function foo() {
            return "superclass2 foo";
        }
        public function bar() {
            return "superclass2 bar";
        }
    }
}

/* Second Namespace */
namespace MyNS\SubNS {
    class childclass extends \MyNS\superclass { }

    class childclass2 extends \MyNS\superclass {
        public static function foo() {
            return "childclass2 foo";
        }
        public function bar() {
            return "childclass2 bar";
        }
    }
}

/* Back to Root Namespace */
namespace {
    /* Returns 'MyNS' */
    echo \MyNS\superclass::get_namespace() . "<br />";
    echo \MyNS\SubNS\childclass::get_namespace() . "<br />";

    /* Returns 'MyNS' */
    echo \MyNS\superclass::get_current_namespace() . "<br />";

    /* Returns 'MyNS\SubNS' */
    echo \MyNS\SubNS\childclass::get_current_namespace() . "<br />";


    /* Or this way */


    $super = new \MyNS\superclass();
    $child = new \MyNS\SubNS\childclass();

    /* Returns 'MyNS' */
    echo $super->get_namespace() . "<br />";
    echo $child->get_namespace() . "<br />";

    /* Returns 'MyNS' */
    echo $super->get_namespace($super) . "<br />";

    /* Returns 'MyNS\SubNS' */
    echo $child->get_namespace($child) . "<br />";

    /* Returns 'superclass2 foo' */
    echo $super->call_static_method("superclass2", "foo") . "<br />";

    /* Returns 'superclass2 bar' */
    $super2 = new \MyNS\superclass2();
    echo $super->call_user_method($super2, "bar") . "<br />";

    /* Returns 'superclass2 foo' */
    echo $child->call_static_method("childclass2", "foo") . "<br />";

    /* Returns 'superclass2 bar' */
    $child2 = new \MyNS\SubNS\childclass2();
    echo $child->call_user_method($child2, "bar") . "<br />";
}

Edited in response to Artur Bodera to add 'call' functionality

PHP 5.3 gibi bunu başarmak için get_called_class ve bazı dize işlevlerini kullanabilirsiniz.

substr(get_called_class(), 0, strrpos(get_called_class(), "\\"))