Home > front end >  In php, what is a good way to determine whether private property is set?
In php, what is a good way to determine whether private property is set?

Time:12-25

Consider the following user class:

<?php

class User
{
    private string $name;

    public function getName(): string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;
        return $this;
    }
}

$user = new User();

We would like to get the $name property of object $user. However, the $name property has not always been set. If we run $user->getName() and the $name property has not been set, then we get the following warning:

PHP Warning:  Uncaught Error: Typed property User::$name must not be accessed before initialization

How can we call $user->getName() without running into errors?

Use __isset?

Should we use the __isset magic method? For example, we could add the following __isset method to the class:

public function __isset($name): bool {
    return isset($this->$name);
}

And then, from outside the class, we could run:

if (isset($user->name)) {
    // $user->getName() can now be called
}

However, it seems odd that our code would contain $user->name knowing in advance that the $name property is private. Also, since we call the $name property often, we would be adding this if statement in numerous (perhaps hundreds of) places in our code.

Default $name to be null?

For example, we could update our class:

class User
{
    private ?string $name = null;

    public function getName(): ?string
    {
        return $this->name;
    }

    // ...
}

And then, from outside the class, we could run:

if (isset($user->getName())) {
    // Do stuff ...
}

However, it seems odd that $name would default to null since null is not a valid value for someone's name. An "uninitialized" value seems more appropriate. And, we would again need to add numerous if statements around out code.

Any suggestions or feedback would be very much appreciated. Thank you.

CodePudding user response:

Use a non-typed property, or initialize it in the constructor, or with the declaration of the property.

The whole point or a typed property is to avoid comparison with null (well, one of the points). Also null is not a string. So using a null/or-string type defeates the whole point more or less - you may just as well use a non-typed property instead.

In php, what is a good way to determine whether private property is set?

You have the wrong frame of mind imho. In the OOP paradigm, it's your responsibility to initialize your objects properly, as opposed to asking "are my objects initialized propery?" after instantiation.

So the answer is: initialize it properly, or declare a default value.

GLHF

CodePudding user response:

Four ways come to my mind:

  • Initialize $name upon definition
  • Force the constructor to initialize $name
  • Check within getName()
  • Add a helper method
class User
{
    // either pre-initialize
    private string $name = '';

    // or enforce setting by constructor
    public function __construct(string $name = '')
    {
        $this->name = $name;
    }

    public function getName(): string
    {
        // or check within getName(), null-coalescing operator added as suggested by Robert in a comment
            return $this->name ?? '';
        }
    }

    public function setName(string $name): self
    {
        $this->name = $name;
        return $this;
    }

    // or add a public helper function
    public function isNameSet(): bool
    {
        return (isset($this->name));
    }


}

$user = new User();

if ($user->isNameSet()) {
    // Do things
}

CodePudding user response:

Avoiding the use of conditional checks throughout your system could be difficult as it appears your system expects valid values but these are not always available and, depending on how the places your getters are called use the return value.

If your User is open to some modification, then you could as you've suggested make certain properties nullable or initialize them with suitable values (null, empty, whatever works for your business/use case). As Nigel Ren has mentioned in his comment a null value can be perfectly valid depending on the scenario (although it might not be ideal).

The following might be helpful to you, although it doesn't entirely mitigate the requirement to perform conditional checks. It does provide some (arguably) easier helper methods for performing such checks and returning some default values.

class User
{
    private ?string $name = null;
    
    private ?string $nickname = '';
    
    private ?string $city = 'New York';
    
    public function getName()
    {
        return $this->name !== null && !empty($this->name) 
            ? $this->name 
            : "Not Provided";
    }
    
    public function getNickName()
    {
        return $this->nickname !== null && !empty($this->nickname) 
            ? $this->nickname
            : "Not Provided";
    }
    
    public function getCity()
    {
        return $this->city !== null && !empty($this->city) 
            ? $this->city
            : "Not Provided";
    }
    
    public function uninitialised()
    {
        $uninitialized = [];
        foreach (get_object_vars($this) as $property => $value) {
            if (!isset($value) || empty($value)) {
                $uninitialized[] = $property;
            }
        }
        
        return $uninitialized;
    }
    
    public function checkForUninitialised(array $properties)
    {
        return array_intersect($properties, $this->uninitialised());
    }
}

$user = new User();

var_dump($user->uninitialised());

echo PHP_EOL;

var_dump(
    $user->checkForUninitialised(
        ['name', 'nickname', 'city'], 
        $user->uninitialised()
    )
);

The output of the above would be:

array(2) {
  [0]=>
  string(4) "name"
  [1]=>
  string(8) "nickname"
}

array(2) {
  [0]=>
  string(4) "name"
  [1]=>
  string(8) "nickname"
}

CodePudding user response:

In PHP, one way to determine whether a private property of an object is set is to use the isset() function. This function checks if a variable is set and is not NULL.

For example, consider the following class with a private property $name:

class Person {
  private $name;

  public function __construct($name) {
    $this->name = $name;
  }
}

$person = new Person('John');

To check if the $name property is set, you could use the following code:

if (isset($person->name)) {
  // The $name property is set
} else {
  // The $name property is not set
}

Keep in mind that, because the $name property is private, you will not be able to access it directly from outside the class. Instead, you will need to use a public method to get or set the value of the property.

For example, you could add a getName() method to the Person class to allow you to retrieve the value of the $name property:

class Person {
  private $name;

  public function __construct($name) {
    $this->name = $name;
  }

  public function getName() {
    return $this->name;
  }
}

$person = new Person('John');

if (isset($person->getName())) {
  // The $name property is set
} else {
  // The $name property is not set
}
  • Related