Getter and Setter?

前端 未结 15 675
南方客
南方客 2020-11-22 16:47

I\'m not a PHP developer, so I\'m wondering if in PHP is more popular to use explicit getter/setters, in a pure OOP style, with private fields (the way I like):



        
相关标签:
15条回答
  • 2020-11-22 17:28

    Why use getters and setters?

    1. Scalability: It's easier refactor a getter than search all the var assignments in a project code.
    2. Debugging: You can put breakpoints at setters and getters.
    3. Cleaner: Magic functions are not good solution for writting less, your IDE will not suggest the code. Better use templates for fast-writting getters.

    direct assignment and getters/setters

    0 讨论(0)
  • 2020-11-22 17:28

    Update: Don't use this answer since this is very dumb code that I found while I learn. Just use plain getter and setter, it's much better.


    I usually using that variable name as function name, and add optional parameter to that function so when that optional parameter is filled by caller, then set it to the property and return $this object (chaining) and then when that optional parameter not specified by caller, i just return the property to the caller.

    My example:

    class Model
    {
         private $propOne;
         private $propTwo;
    
         public function propOne($propVal = '')
         {
              if ($propVal === '') {
                  return $this->propOne;
              } else {
                  $this->propOne = $propVal;
                  return $this;
              }
         }
    
         public function propTwo($propVal = '')
         {
              if ($propVal === '') {
                  return $this->propTwo;
              } else {
                  $this->propTwo = $propVal;
                  return $this;
              }
         }
    }
    
    0 讨论(0)
  • 2020-11-22 17:30
    class MyClass {
        private $firstField;
        private $secondField;
        private $thirdField;
    
        public function __get( $name ) {
            if( method_exists( $this , $method = ( 'get' . ucfirst( $name  ) ) ) )
                return $this->$method();
            else
                throw new Exception( 'Can\'t get property ' . $name );
        }
    
        public function __set( $name , $value ) {
            if( method_exists( $this , $method = ( 'set' . ucfirst( $name  ) ) ) )
                return $this->$method( $value );
            else
                throw new Exception( 'Can\'t set property ' . $name );
        }
    
        public function __isset( $name )
        {
            return method_exists( $this , 'get' . ucfirst( $name  ) ) 
                || method_exists( $this , 'set' . ucfirst( $name  ) );
        }
    
        public function getFirstField() {
            return $this->firstField;
        }
    
        protected function setFirstField($x) {
            $this->firstField = $x;
        }
    
        private function getSecondField() {
            return $this->secondField;
        }
    }
    
    $obj = new MyClass();
    
    echo $obj->firstField; // works
    $obj->firstField = 'value'; // works
    
    echo $obj->getFirstField(); // works
    $obj->setFirstField( 'value' ); // not works, method is protected
    
    echo $obj->secondField; // works
    echo $obj->getSecondField(); // not works, method is private
    
    $obj->secondField = 'value'; // not works, setter not exists
    
    echo $obj->thirdField; // not works, property not exists
    
    isset( $obj->firstField ); // returns true
    isset( $obj->secondField ); // returns true
    isset( $obj->thirdField ); // returns false
    

    Ready!

    0 讨论(0)
  • 2020-11-22 17:30

    If you preffer to use the __call function, you can use this method. It works with

    • GET => $this->property()
    • SET => $this->property($value)
    • GET => $this->getProperty()
    • SET => $this->setProperty($value)

    kalsdas

    public function __call($name, $arguments) {
    
        //Getting and setting with $this->property($optional);
    
        if (property_exists(get_class($this), $name)) {
    
    
            //Always set the value if a parameter is passed
            if (count($arguments) == 1) {
                /* set */
                $this->$name = $arguments[0];
            } else if (count($arguments) > 1) {
                throw new \Exception("Setter for $name only accepts one parameter.");
            }
    
            //Always return the value (Even on the set)
            return $this->$name;
        }
    
        //If it doesn't chech if its a normal old type setter ot getter
        //Getting and setting with $this->getProperty($optional);
        //Getting and setting with $this->setProperty($optional);
        $prefix = substr($name, 0, 3);
        $property = strtolower($name[3]) . substr($name, 4);
        switch ($prefix) {
            case 'get':
                return $this->$property;
                break;
            case 'set':
                //Always set the value if a parameter is passed
                if (count($arguments) != 1) {
                    throw new \Exception("Setter for $name requires exactly one parameter.");
                }
                $this->$property = $arguments[0];
                //Always return the value (Even on the set)
                return $this->$name;
            default:
                throw new \Exception("Property $name doesn't exist.");
                break;
        }
    }
    
    0 讨论(0)
  • 2020-11-22 17:34

    Validating + Formatting/Deriving Values

    Setters let you to validate data and getters let you format or derive data. Objects allow you to encapsulate data and its validation and formatting code into a neat package that encourages DRY.

    For example, consider the following simple class that contains a birth date.

    class BirthDate {
    
        private $birth_date;
    
        public function getBirthDate($format='Y-m-d') {
            //format $birth_date ...
            //$birth_date = ...
            return $birth_date;
        }
    
        public function setBirthDate($birth_date) {                   
            //if($birth_date is not valid) throw an exception ...          
            $this->birth_date = $birth_date;
        }
    
        public function getAge() {
            //calculate age ...
            return $age;
        }
    
        public function getDaysUntilBirthday() {
            //calculate days until birth days
            return $days;
        }
    }
    

    You'll want to validate that the value being set is

    • A valid date
    • Not in the future

    And you don't want to do this validation all over your application (or over multiple applications for that matter). Instead, it's easier to make the member variable protected or private (in order to make the setter the only access point) and to validate in the setter because then you'll know that the object contains a valid birth date no matter which part of the application the object came from and if you want to add more validation then you can add it in a single place.

    You might want to add multiple formatters that operate on the same member variable i.e. getAge() and getDaysUntilBirthday() and you might want to enforce a configurable format in getBirthDate() depending on locale. Therefore I prefer consistently accessing values via getters as opposed to mixing $date->getAge() with $date->birth_date.

    getters and setters are also useful when you extend objects. For example, suppose your application needed to allow 150+ year birth dates in some places but not in others. One way to solve the problem without repeating any code would be to extend the BirthDate object and put the additional validation in the setter.

    class LivingBirthDate extends BirthDate {
    
        public function setBirthDate($birth_date) {
            //if $birth_date is greater than 150 years throw an exception
            //else pass to parent's setter
            return parent::setBirthDate($birth_date);
        }
    }
    
    0 讨论(0)
  • 2020-11-22 17:36

    Google already published a guide on optimization of PHP and the conclusion was:

    No getter and setter Optimizing PHP

    And no, you must not use magic methods. For PHP, Magic Method are evil. Why?

    1. They are hard to debug.
    2. There is a negative performance impact.
    3. They require writing more code.

    PHP is not Java, C++, or C#. PHP is different and plays with different roles.

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