Methods and References to Properties

Say I have:


class QWERTY {
    private $check_arr;

    private function set_check_array($bool) {
        $arr = $this->get_check_arr();
        array_push($arr, $bool);
        unset($arr);
    }

    private function &get_check_arr() {
        if(!is_array($this->check_arr)) {
        $this->check_arr = array();
        }

    return $this->check_arr;
    }
}

All I’m trying to do is modify the class property $check_arr. Is this a good way to accomplish this or is there a better way? The method variable $arr of set_check_arr() is a reference to my class property correct? Should I just interact with the property directly rather than creating a reference to it?
Would this work better?:


class QWERTY {
    private $check_arr;

    private function set_check_array($bool) {
        array_push($this->get_check_arr(), $bool);
        }

    private function get_check_arr() {
       $arr =& $this->check_arr;
        if(!is_array($arr)) {
            $arr = array();
        }
        return $arr;
    }
}

Are references the best way to accomplish getting and modifying class properties?

Hello Angrypoonani!

First of all, you need to initialize your private property check_arr:

class QWERTY {
	private $check_arr = array();
	// ...

Then, why do you need a reference to the private property? Private property is needed to isolate data from everywhere except class’ scope.

Also private methods surprised me. Do you plan to use these methods somewhere in your class, or not?

If you’re trying to modify class property $check_arr through private methods, isn’t it easier would be to do it directly in class, hm?

Reply back, because I’m little bit confused. :slight_smile:

Hello Volter9, thank you for your reply!

I wait until my get_arr() method to initialize the array:


if(!is_array($this->check_arr)) {
        $this->check_arr = array();
        }

:x I forgot that I could initialize arrays when I declare them in a class. Is my way a bad way to do it?

These two methods are part of a larger class with public methods and properties however set_check_array() is called by a separate method which is public, though it’s possible I don’t need any of them to be private.

Is there a different way to edit the $check_arr property other than a reference? I’m guessing:


```php

private function set_check_array($bool) {
    array_push($this->check_arr, $bool);
}



Maybe I'm just tired of typing $this->check_arr everywhere haha :shifty:
Would that be a better way of modifying my property? (Just doing it directly instead of using a reference)

My first piece of advice is to avoid setters and getters altogether; it’s just bad design.

From http://typicalprogrammer.com/doing-it-wrong-getters-and-setters/
Every getter and setter in your code represents a failure to encapsulate and creates unnecessary coupling. A profusion of getters and setters (also referred to as accessors, accessor methods, and properties) is a sign of a poorly-designed set of classes.

Not only that, but it creates more complexity than necessary.

Now, it’s really tough to answer any questions without knowing first what the purpose of the class is. Can you clarify a bit on what you are trying to accomplish?

I’m sorry, but I wholeheartedly disagree with that statement. Getters and setters are the way to expose private variables in a class to the outside world in a way you want. If you ever wanted to change the public API of your class, you can do that without any problem, as long as the getters and setters produce the same output given the same input. What happens within those function is of no concern to the callser. Also, you can do extra checking of input/output you just can’t do if you access variables directly, like


private function set_check_array($bool) {
    if (!is_bool($bool)) {
        throw new \\InvalidArgumentException('Parameter 1 of SomeClass::set_check_array must be a boolean, '.gettype($bool).' given.');
    }
    array_push($this->check_arr, $bool);
}

That being said, the use of private getters and setters within a class is a little more doubtful, but still it may have its place.

Also see http://pragprog.com/articles/tell-dont-ask

I don’t think arout77 is advocating directly accessing object properties, but rather having methods that perform more domain specific actions instead of getters and setters for individual properties which expose too much information about the object’s internal structure.

Now that I fully agree with :slight_smile:

I think it depends on how you approach things…given that there is so little that is canonical about PHP, subjects like this often appear to boil down to personal preference.

I see that fretburner already responded, and he is pretty well spot on with what I was getting at.

When I think of getters / setters, I always think of this post I saw a long time ago on killerphp.
From his tutorial, he taught people to do this –


<?php
                 $stefan = new person();
                 $jimmy = new person;
                 
                 $stefan->set_name("Stefan Mischook");
                 $jimmy->set_name("Nick Waddles");
               
                echo "Stefan's full name: " . $stefan->get_name();
                echo "Nick's full name: " . $jimmy->get_name();
?>

Granted, this is a crude example, but it is just terrible! Why even bother wrapping something like that in a class, especially since you are completely ignoring one of the main pillars of OOP (polymorphism)?

For the OP, here is a real quick example of why I say setters / getters should be avoided. This is a fictional class that sets a user’s name ( it’s a bit crude, but anyway… )



class Users {

    private $usernames = array();
    
    function set_my_name( $data ) {

        return $this->usernames[$data] = $data;
    }

    function get_my_name() {

        return $this->usernames;
    }

}

$user = new Users;
$user->set_my_name(  'Bob'  );
echo 'Hello, ' . $user->get_my_name( );


First problem is, it’s simply a PITA to have to call set_my_name() every time we need to use this. What if we forget to, and just try to use get_name_name()? How do we ensure that all the setters will always be called, and in the proper order?
Second problem is, we now just created a coupling, which can cause headaches when it’s time to test this class. In this particular example, no big deal…but then, real world scripts are going to be a lot more complex.
Third problem is, and this is sorta kinda what fretburner was alluding to (in addition to the first problem I mentioned), is that to perform error checking, you would need to know what exactly set_my_name() expects to recieve, and you do your error checking outside of the class…that’s another big no-no, as well as being another PITA.

A better way of writing the above would be something like this (again, keeping it real brief)



class Users {

    private $usernames = array();
    
    function my_name( $data ) {
        
        // Do error checking as needed, etc etc
        
        if( empty( $data ) ) {
            // Handle the error however you want
            throw new Exception( "We haven't met yet! What is your name?" );
        }
        
        if( strlen( $data ) >= 20 ) {
            // Handle the error however you want
            throw new Exception( "Did you fall asleep on the keyboard?" );
        }

        return $this->usernames[$data] = $data;
    }

}

$user = new Users;
echo 'Hello, ' . $user->my_name( 'Bob' );


Much simpler! Everything is still kept private, no need to set anything and check for errors every time you use it, no potential issues when you test the code.
But where it really shines in my opinion is when you extend the class, and it has a billion child classes…things start getting really tricky, because you’ll often use traits and interfaces when you are creating classes that are meant to be extensible. But using traits and interfaces is another reason why I feel setters and getters are not a good fit for PHP…that’s a long rant for another day. Sorry for the long post, but I haven’t even really given half my thoughts and this is already a wall of text…

I appreciate all the food for thought. I’m sure I have more questions but after reading through some of the linked resources I can see some alterations that can be made to simplify things. I can see that I don’t need to use references and some of my accessors can be modified or removed. Thanks again.

Getters and setters is just a tool, as a bad workman blames his tools.
In my opinion, manual getters and setters is a bad idea, it’s routine job. What do you think about magic getters and setters?

Personally, I don’t like them at all, for a lot of reasons. I would sooner use regular getter / setters.

Want to edit this post, just to make an observation. I think that a lot of people bring ideas / philosophies from other languages and apply them to PHP. Sometimes that is a good thing, in a general sense. For example, while it may have been used here and there before, MVC didn’t really take off in the PHP world until Rails and Django became popular. Another good example is how those two languages have Bundler and PIP…and now finally, PHP is taking it’s package management seriously with Composer.

But I think it is also very often counter-productive when we apply certain ideas to PHP. My opinion is that getters / setters is generally speaking one of them…they may have some fringe use cases, but usually, in my experience, it is typically a sign that you need to rethink the design. I’m from the school of thought that complex code is a burden, not an achievement…that’s not to say there is anything complex about getters / setters, but they definitely present the opportunity for undue complexity to appear (near and far) down the road. And same can be said of magic methods, 10x. My line of thinking is that when you write code, you should write it for others, not yourself. You are going to understand your own code no matter what you write…but it’s when others can read your code and follow along with minimal fuss that you know you wrote something good. I feel that magic gets in the way of accomplishing that…as well as having other undesirable traits.

Think about controller and loading models. Would you load each of them and set setters and getters? It would be easier to use loader class that will load automatically via __get and __isset needed models.

Another way, that I could think of, is to use PHP Reflection API and custom class importer that would load models into defined public properties. The advantage of this solution is that you could document it, and there wouldn’t be “magic” (except loading process, which isn’t really “magic”).