This has been coming up endlessly on tons of plugins, systems, modules, ect...
The solution is quite simple: just declare the PARAMS you need in the class first. Then you can assign them later. For example:
class foo {
public $bar = ""; // my param BAR is declared here
public function __construct(){
$this->bar = "no_error"; // this assignment of value to BAR will not trigger deprecation warning
}
}
^ No errors occur because the param is not "dynamically assigned" (aka: made up on the fly)
Lets now consider the deprecation warning itself using your sample:
class database {
public $username = "root";
public $password = "password";
public $port = 3306;
public function __construct($params = array()){
foreach ($params as $key => $value) { $this->{$key} = $value;}
// you want this ^ to magically make properties... clever, but lazy & dangerous
// these [below] would also fail here, they are declared on the fly...
$this->databaseName= "myDB";
$this->hostName= "some.mysql.server";
$this->sqlQuery= "SELECT * FROM something";
}
}
Thats going to land you these
# Deprecated: Creation of dynamic property database::databaseName is deprecated
# Deprecated: Creation of dynamic property database::hostName is deprecated
# Deprecated: Creation of dynamic property database::sqlQuery is deprecated
In PHP 7 the class ya got there was supposed to make life easy by letting you instance then just shove-in some params that you can define on the fly, however, this is poor planning in php 8.2 (and in theory not very secure).
For details on that here is a TLDR; that is worth reading - https://php.watch/versions/8.2/dynamic-properties-deprecated
to make it simple? Just declare your params, like this:
class database {
public $username = "root";
public $password = "password";
public $port = 3306;
// just add params here, all planned out
public $databaseName = "";
public $hostName = "";
public $sqlQuery = "";
public function __construct($params = array()){
// now you do not need the offending dynamic foreach assignment here
// and now you CAN do this with no error
$this->databaseName = "myDB";
$this->hostName = "some.mysql.server";
$this->sqlQuery = "SELECT * FROM something";
// or, you could grab them from the construct array you passed in
$this->databaseName = $params['databaseName'];
$this->hostName = $params['hostName '];
$this->sqlQuery = $params['sqlQuery '];
}
}
If you really need the 'dynamic creation foreach loop' then other answers here will suffice.
IMHO: remove that foreach and just drop in your params, declare them in the class as expected in PHP 8.2 => done.
PS: I think its a bad idea to use #[AllowDynamicProperties]
because you are going to have to correct the issue eventually... you could just shove that into every class that has the deprecation warning but is that really good dev?
$this->{$key}
is a risky solution (IMHO) as it's easy (like you've found) to get the parameters wrong. – Xyloidif (!property_exists($this, $key)) { throw new Exception('Unknown property'); }
It won't fix your code, but it will at least give you a hook into the process of nailing down your other violations. – Grider