Domanda

Nell'usare le classi DOM di PHP (DOMNode, DOMEElement, ecc.) ho notato che possiedono proprietà di sola lettura. Ad esempio, posso leggere la proprietà $ nodeName di un DOMNode, ma non posso scrivergli (se faccio PHP genera un errore fatale).

Come posso creare le mie proprietà di sola lettura in PHP?

È stato utile?

Soluzione

Puoi farlo in questo modo:

class Example {
    private 

Puoi farlo in questo modo:

<*>

Utilizzalo solo quando ne hai davvero bisogno - è più lento del normale accesso alle proprietà. Per PHP, è meglio adottare una politica di utilizzo dei soli metodi setter per modificare una proprietà dall'esterno.

_readOnly = 'hello world'; function __get($name) { if($name === 'readOnly') return $this->__readOnly; user_error("Invalid property: " . __CLASS__ . "->$name"); } function __set($name, $value) { user_error("Can't set property: " . __CLASS__ . "->$name"); } }

Utilizzalo solo quando ne hai davvero bisogno - è più lento del normale accesso alle proprietà. Per PHP, è meglio adottare una politica di utilizzo dei soli metodi setter per modificare una proprietà dall'esterno.

Altri suggerimenti

Ma le proprietà private esposte solo usando __get () non sono visibili alle funzioni che enumerano i membri di un oggetto - json_encode () per esempio.

Passo regolarmente oggetti PHP su Javascript usando json_encode () in quanto sembra essere un buon modo per passare strutture complesse con molti dati popolati da un database. Devo usare proprietà pubbliche in questi oggetti in modo che questi dati vengano popolati attraverso il Javascript che li utilizza, ma ciò significa che tali proprietà devono essere pubbliche (e quindi correre il rischio che un altro programmatore non sia sulla stessa lunghezza d'onda (o probabilmente me stesso dopo una brutta notte) potrei modificarli direttamente). Se li rendo privati ??e utilizzo __get () e __set (), json_encode () non li vede.

Non sarebbe bello avere un " di sola lettura " parola chiave di accessibilità?

Vedo che hai già ricevuto la tua risposta, ma per quelli che stanno ancora cercando:

Dichiara tutto " in sola lettura " variabili come private o protette e utilizzare il metodo magico __get () in questo modo:

/**
 * This is used to fetch readonly variables, you can not read the registry
 * instance reference through here.
 * 
 * @param string $var
 * @return bool|string|array
 */
public function __get ($var)
{
    return ($var != "instance" && isset($this->$var)) ? $this->$var : false;
}

Come puoi vedere ho anche protetto la variabile $ this- > istanza poiché questo metodo consentirà agli utenti di leggere tutte le variabili dichiarate. Per bloccare più variabili usa un array con in_array ().

Ecco un modo per rendere tutte le proprietà della tua classe read_only dall'esterno, le classi ereditate hanno accesso in scrittura ;-).

class Test {
    protected $foo;
    protected $bar;

    public function __construct($foo, $bar) {
        $this->foo = $foo;
        $this->bar = $bar;
    }

/**
 * All property accessible from outside but readonly
 * if property does not exist return null
 *
 * @param string $name
 *
 * @return mixed|null
 */
    public function __get ($name) {
        return $this->$name ?? null;
    }

/**
 * __set trap, property not writeable
 *
 * @param string $name
 * @param mixed $value
 *
 * @return mixed
 */
    function __set ($name, $value) {
        return $value;
    }
}

testato in php7

Per coloro che cercano un modo per esporre le proprietà private / protette per la serializzazione, se si sceglie di utilizzare un metodo getter per renderle di sola lettura, ecco un modo per farlo (@Matt: per json come esempio):

interface json_serialize {
    public function json_encode( $asJson = true );
    public function json_decode( $value );
}

class test implements json_serialize {
    public $obj = null;
    protected $num = 123;
    protected $string = 'string';
    protected $vars = array( 'array', 'array' );
    // getter
    public function __get( $name ) {
        return( $this->$name );
    }
    // json_decode
    public function json_encode( $asJson = true ) {
        $result = array();
        foreach( $this as $key => $value )
            if( is_object( $value ) ) {
                if( $value instanceof json_serialize )
                    $result[$key] = $value->json_encode( false );
                else
                    trigger_error( 'Object not encoded: ' . get_class( $this ).'::'.$key, E_USER_WARNING );
            } else
                $result[$key] = $value;
        return( $asJson ? json_encode( $result ) : $result );
    }
    // json_encode
    public function json_decode( $value ) {
        $json = json_decode( $value, true );
        foreach( $json as $key => $value ) {
            // recursively loop through each variable reset them
        }
    }
}
$test = new test();
$test->obj = new test();
echo $test->string;
echo $test->json_encode();
Class PropertyExample {

        private $m_value;

        public function Value() {
            $args = func_get_args();
            return $this->getSet($this->m_value, $args);
        }

        protected function _getSet(&$property, $args){
            switch (sizeOf($args)){
                case 0:
                    return $property;
                case 1:
                    $property = $args[0];
                    break;  
                default:
                    $backtrace = debug_backtrace();
                    throw new Exception($backtrace[2]['function'] . ' accepts either 0 or 1 parameters');
            }
        }


}

Questo è il modo in cui mi occupo di ottenere / impostare le mie proprietà, se vuoi rendere Value () in sola lettura ... allora devi semplicemente fare quanto segue:

    return $this->m_value;

Dove come la funzione Value () in questo momento potrebbe ottenere o impostare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top