First domain-driven User entity class I'm still learning about domain driven design, and I have created my first entity class User.

Is this fully compliant with the DDD principles?  Particularly my setters because I have business rules in them.  Any other suggestions would be highly appreciated as well.

namespace Models\Entities;

class User
{
    private $id;
    private $firstName;
    private $lastName;
    private $email;
    private $password;
    private $registerDate;

    public function setId($id)
    {
        if (!$this-&gt;id) {
            if (is_int($id) &amp;&amp; $id &gt;= 1) {
                $this-&gt;id = $id;

                return $this;
            }

            throw new \InvalidArgumentException('ID must be a positive integer.');
        }

        throw new \InvalidArgumentException('ID has already been set.');
    }

    public function getId()
    {
        return $this-&gt;id;
    }

    public function setFirstName($firstName)
    {
        if (is_string($firstName) &amp;&amp; !empty($firstName) &amp;&amp; ctype_alpha($firstName)) {
            $length = $this-&gt;stringLength($firstName);

            if ($length &gt;= 1 &amp;&amp; $length &lt;= 35) {
                $this-&gt;firstName = $firstName;

                return $this;
            }
        }

        throw new \InvalidArgumentException('First name must be an alpha string inclusively between 1 and 35 characters.');
    }

    public function getFirstName()
    {
        return $this-&gt;firstName;
    }

    public function setLastName($lastName)
    {
        if (is_string($lastName) &amp;&amp; !empty($lastName) &amp;&amp; ctype_alpha($lastName)) {
            $length = $this-&gt;stringLength($lastName);

            if ($length &gt;= 1 &amp;&amp; $length &lt;= 35) {
                $this-&gt;lastName = $lastName;

                return $this;
            }
        }

        throw new \InvalidArgumentException('Last name must be an alpha string inclusively between 1 and 35 characters.');
    }

    public function getLastName()
    {
        return $this-&gt;lastName;
    }

    public function getFullName()
    {
        return $this-&gt;firstName . ' ' . $this-&gt;lastName;
    }

    public function setEmail($email)
    {
        if (is_string($email) &amp;&amp; !empty($email)) {
            $sanitized = filter_var($email, FILTER_SANITIZE_EMAIL);
            $isValid   = filter_var($sanitized, FILTER_VALIDATE_EMAIL);
            $isValid   = $isValid ? $this-&gt;stringLength($email) &lt;= 254 : false;

            if ($email === $sanitized &amp;&amp; $isValid) {
                $this-&gt;email = $email;

                return $this;
            }
        }

        throw new \InvalidArgumentException('Email must be a string in this format: "[local]@[domain].[ext]".');
    }

    public function getEmail()
    {
        return $this-&gt;email;
    }

    public function setPassword($password)
    {
        if (is_string($password) &amp;&amp; !empty($password)) {
            $length = $this-&gt;stringLength($password);

            if ($length &gt;= 6 &amp;&amp; $length &lt;= 60) {
                $this-&gt;password = $password;

                return $this;
            }
        }

        throw new \InvalidArgumentException('Password must be a string inclusively between 6 and 60 characters.');
    }

    public function getPassword()
    {
        return $this-&gt;password;
    }

    public function setRegisterDate($date)
    {
        if (is_int($date) &amp;&amp; !empty($date)) {
            // TO DO: date validation unix timestamp is_int

            $this-&gt;registerDate = $date;

            return $this;
        }

        throw new \InvalidArgumentException('Register date must be an integer and valid unix timestamp.');
    }

    public function getRegisterDate()
    {
        return $this-&gt;registerDate;
    }

    private function stringLength($input)
    {
        $encoding = mb_detect_encoding($input);
        $length   = mb_strlen($input, $encoding);

        return $length;
    }
}
Your class can absolutely be considered like a DDD domain entity.
However, I would suggest some improvements:


DDD likes to use an ObjectValue for the unique identifiers, you could use one instead of a simple integer.
You could separate the validation logic from the entity (not specific to DDD).
You should not have a getPassword() method but a verifyPassword($password) instead. Don't expose the password in plain text.
You could also separate the stringLength() into its own string utility class.
Regarding the use of a Uniw timestamp, keep in mind that DateTime is a better option since it embeds the time zone. Timestamps don't, which is always confusing when handling dates from all over the world...