Difference in write
One big difference is that you can't set class constants dynamically at runtime, which you can do with readonly properties (from the constructor).
Difference in read
There's also a big difference in how you access the two. Unless the property is static, you will need to have an instance (and all instances can have different values), while constants can always be access without an instance.
Props to M. Eriksson
Answer from Phil on Stack OverflowAfter all, the overlap is so big that I struggle to see why they were introduced.
If you want a property to be immutable after assignment, a constant does that, too. That's also why constants being public is fine.
So, I would have found readonly more useful, if I was allowed to always re-assign them from inside the class that defined them. Then they would work like a private property that only has a getter but no setter - which I find convenient. It's the job of the class to manage its state, so I don't see why you shouldn't be allowed to re-assign them from inside when constants already exist.
Care to enlighten me?
I’m coming from a background in C++ where my team used the const keyword whenever possible to prevent the chance of variables unintentionally being modified. Transitioning to PHP, I’m having a hard time understanding when to use the const keyword. I want to use it all the time like I did with C++ but naming const variables all in uppercase seems to hurt the code readability.
Do PHP developers just not use the const keyword a lot or maybe not name them all in uppercase? As a side note, is there a good open source PHP repository that I could use as a reference for the best practices for developing in PHP?
class constant:
class MyClass
{
const CONSTANT = 'constant value';
function showConstant() {
echo self::CONSTANT . "\n";
}
}
generally:
define("const_name", "const_value");
echo const_name;
http://php.net/manual/en/language.oop5.constants.php
http://php.net/manual/en/function.constant.php
We can define an closure accessor for that property.
function f(ComplexObject $object)
{
$innerName = function() use($object) {
return $object->innerObject->attributes->name;
}
/**
* All places that use $object->innerObject->attributes->name
* can address is as $innerName()
*/
}
Note: function call has some cost, but readability and error protection usually outweighs.
Directly answering your question: No, you cannot mark regular properties as readonly. If you want to set primitive types (except array), that will never change, you should use constants
const QWE = '666';
That doesn't work for objects and arrays. I see two (lets say) "solutions"
Use Getter
private $qwe; public function getQwe() { return $this->qwe; } protected function setQwe($value) { $this->qwe = $value; }I don't like them very much ("Properties define the state, not the behavior, like methods do"). You always get twice as much additional methods as properties and if you have many properties, this will extremely blow up your class. However, it's as far as I can see the only way to implement what you want to achieve.
Trust your users ;) Comment your property and say something like "If you change this value, probably something will break and its your very own fault".
/** * QWE * * This property should be treatened as "readonly". If you change this value * something scary will happen to you. * * @readonly * @var string */ public $qwe = '666';Its not great, but at least you can say "I told you".
Readonly properties were introduced in PHP 8.1, but static readonly properties are not supported.
From the RFC:
Readonly static properties are not supported. This is a technical limitation, in that it is not possible to implement readonly static properties non-intrusively. In conjunction with the questionable usefulness of readonly static properties, this is not considered worthwhile at this time.
However you can declare a static function to more or less get the same end result.
public static function getType(): string
{
return 'Duck';
}
I discovered this feature a few weeks ago and end up using it a lot in my DTOs (most times they end up being read-only classes).
Right now, the only other use case I have for it is for class properties injected via dependency injection, which I believe should probably never be changed to anything else than what it was first instantiated as.
I'm not sure if the DI properties is a good excuse for using read-only, or if there are other use cases I might have missed, which is why I'm asking how you guys use it :)