PHP: immutable public member fields

前端 未结 4 1894
孤城傲影
孤城傲影 2020-12-06 17:28

I need to create an immutable class which is simply a member field container. I want its fields to be instantiated once in its constructor (the values should be given as par

相关标签:
4条回答
  • 2020-12-06 17:50
    <?php 
    
    declare(strict_types=1);
    
    final class Immutable 
    {
        /** @var string */
        private $value;
    
        public static function withValue(string $value): self
        {
            return new self($value);
        }
    
        public function __construct(string $value) 
        {
            $this->value = $value;
        }
    
        public function value(): string 
        { 
            return $this->value;
        }
    }
    
    // Example of usage:
    
    $immutable = Immutable::withValue("my value");
    $immutable->value(); // You can get its value but there is no way to modify it.
    
    0 讨论(0)
  • 2020-12-06 17:56

    magic methods

    so you can do better - if you have a dinamyc count of fields

       class ClassName {
            private $fields = array(); 
            // use class : $cl = new ClassName(array('f'=>2,'field_4'=>5,''12));
            // echo $cl->field_4; echo $cl->f;
            public function __construct($data= array()) 
            {
               if (!is_array($data) || !count($data)) throw new Exception('Not enough args')
               foreach ($data as $key=>$val)
               {
                  if (is_numeric($key))
                    $this->fields['field_'.$key] = $val;
                  else
                    $this->fields[$key] = $val;
               }     
            }
              /* in this case you can use this class like $cl = new ClassName(12,14,13,15,12); echo $cl->field_1;
          public function __construct() 
        {
               $ata = funcs_get_args();
    
               if (!count($data)) throw new Exception('Not enough args')
               foreach ($data as $key=>$val)
               {
                  if (is_numeric($key))
                    $this->fields['field_'.$key] = $val;
                  else
                    $this->fields[$key] = $val;
               }     
        }
        */
            public function __get($var) {
                if (isset($this->fields[$var]))
                    return $this->fields[$var];
                return false; 
                //or throw new Exception ('Undeclared property');
            }
        }
    
    0 讨论(0)
  • 2020-12-06 18:01

    You should use __set and __get magic methods and declare that property as protected or private:

    /**
     * @property-read string $value
     */
    class Example
    {
        private $value;
    
        public function __construct()
        {
            $this->value = "test";
        }
    
        public function __get($key)
        {
            if (property_exists($this, $key)) {
                return $this->{$key};
            } else {
                return null; // or throw an exception
            }
        }
    
        public function __set($key, $value)
        {
            return; // or throw an exception
        }
    }
    

    Example:

    $example = new Example();
    var_dump($example->value);
    $example->value = "invalid";
    var_dump($example->value);
    

    Outputs:

    string(4) "test"
    string(4) "test"
    

    @property-read should help your IDE acknowledge existence of this magic property.

    0 讨论(0)
  • 2020-12-06 18:10

    You could use the __set() magic method and throw an exception when someone tries to set a property directly.

    class ClassName {
        public function __set($key, $value) {
            throw new Exception('Can&#39;t modify property directly.');
        }
    }
    

    However, this would prevent modification of properties regardless of whether they're public or not.

    0 讨论(0)
提交回复
热议问题