Are PHP8.1 read-only properties compatible with bind_param?
Here is my constructor
public function __construct(
private readonly ?bool $alreadyLive, //If true, the article is already live and will be updated. If false, it is a new article
private readonly bool $pushLive, //If true, the article will be pushed live. If false, it will be saved in pending_articles
private string $articleTitle,
private string $articleExcerpt,
private string $articleContent,
private string $imageCard,
private readonly string $articleType,
private readonly string $articleStatus,
private readonly ?int $articleNumber,
private readonly int $authorID,
private readonly int $heroPosition,
databaseconnection $db
) {
$this->db = $db;
}
I'm attempting to insert some data into a database like so:
try {
$sql = "INSERT INTO " . $table . "
(title, author, content, excerpt, image_card,
views, hero_position, type, status)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
$stmt = $connection->prepare($sql);
$stmt->bind_param("sisssiiss",
$this->articleTitle, $this->authorID,
$this->articleContent, $this->articleExcerpt,
$this->imageCard, $views, $this->heroPosition,
$this->articleType, $this->articleStatus
);
$stmt->execute();
$article_id = $stmt->insert_id;
$stmt->close();
} catch (\Exception) {
//Rollback the transaction
$connection->rollback();
//Return error message
$response['status'] = 'error';
$response['message'] = 'There was an error submitting your article. Please try again.';
return $response;
}
But I keep getting this error:
Cannot modify readonly property article::$authorID
Which is caused by this line as per the line in the stack trace:
$stmt->bind_param("sisssiiss", $this->articleTitle, $this->authorID, $this->articleContent, $this->articleExcerpt, $this->imageCard, $views, $this->heroPosition, $this->articleType, $this->articleStatus);
The error is absolutely correct. You cannot modify readonly
properties, but you also cannot use them in a write context. In PHP, passing parameters by reference is considered a read-write operation. Thus you are not allowed to pass readonly properties to bind_param()
just as you are not allowed to pass constants or literals.
To overcome this problem, use execute()
and pass the values as an array.
$stmt = $mysqli->prepare();
$stmt->execute([
$this->articleTitle,
// ...
]);
Or since PHP 8.2, you can use execute_query()
:
$mysqli->execute_query($sqlQuery, [
$this->articleTitle,
// ...
]);