PHPのオブジェクトが持つプロパティは、インスタンスの生成後も値を変更することができます。-> 演算子を使ってプロパティにアクセスし、代入演算子で新しい値を設定します。
ただし、プロパティを直接変更できるのは public なプロパティだけです。データの整合性を保つため、実際の開発では setter メソッドを通じて変更するのが一般的です。ここではプロパティの変更方法と、安全な値の管理方法を解説します。
基本的な使い方
public プロパティは、オブジェクトの外部から直接読み書きできます。
PHP
<?php
class User {
public string $name;
public int $age;
public function __construct(string $name, int $age) {
$this->name = $name;
$this->age = $age;
}
}
$user = new User("田中", 25);
echo "変更前: {$user->name}({$user->age}歳)\n";
// プロパティを変更
$user->name = "佐藤";
$user->age = 30;
echo "変更後: {$user->name}({$user->age}歳)\n";
実行結果
変更前: 田中(25歳)
変更後: 佐藤(30歳)
setterメソッドによる安全な変更
プロパティを private にし、setterメソッドを通じて値を変更すると、バリデーションを挟むことができます。
PHP
<?php
class Product {
private string $name;
private int $price;
private int $stock;
public function __construct(string $name, int $price, int $stock) {
$this->name = $name;
$this->setPrice($price);
$this->setStock($stock);
}
// getter
public function getName(): string { return $this->name; }
public function getPrice(): int { return $this->price; }
public function getStock(): int { return $this->stock; }
// setter(バリデーション付き)
public function setPrice(int $price): void {
if ($price < 0) {
throw new InvalidArgumentException("価格は0以上にしてください");
}
$this->price = $price;
}
public function setStock(int $stock): void {
if ($stock < 0) {
throw new InvalidArgumentException("在庫は0以上にしてください");
}
$this->stock = $stock;
}
}
$product = new Product("りんご", 150, 100);
echo "{$product->getName()}: {$product->getPrice()}円(在庫{$product->getStock()})\n";
$product->setPrice(200);
$product->setStock(80);
echo "{$product->getName()}: {$product->getPrice()}円(在庫{$product->getStock()})\n";
// 不正な値はエラーになる
try {
$product->setPrice(-100);
} catch (InvalidArgumentException $e) {
echo "エラー: " . $e->getMessage() . "\n";
}
実行結果
りんご: 150円(在庫100)
りんご: 200円(在庫80)
エラー: 価格は0以上にしてください
メソッドチェーンによる変更
setterメソッドが $this を返すようにすると、メソッドチェーンで複数のプロパティを連続して変更できます。
PHP
<?php
class QueryBuilder {
private string $table = "";
private array $conditions = [];
private ?int $limit = null;
public function from(string $table): self {
$this->table = $table;
return $this;
}
public function where(string $condition): self {
$this->conditions[] = $condition;
return $this;
}
public function limit(int $limit): self {
$this->limit = $limit;
return $this;
}
public function toSQL(): string {
$sql = "SELECT * FROM {$this->table}";
if (!empty($this->conditions)) {
$sql .= " WHERE " . implode(" AND ", $this->conditions);
}
if ($this->limit !== null) {
$sql .= " LIMIT {$this->limit}";
}
return $sql;
}
}
$query = (new QueryBuilder())
->from("users")
->where("age >= 20")
->where("active = 1")
->limit(10)
->toSQL();
echo $query . "\n";
実行結果
SELECT * FROM users WHERE age >= 20 AND active = 1 LIMIT 10
readonlyプロパティ(PHP 8.1+)
PHP 8.1以降では readonly キーワードで、一度だけ代入可能なプロパティを定義できます。
PHP
<?php
class ImmutableUser {
public function __construct(
public readonly string $name,
public readonly int $age
) {}
}
$user = new ImmutableUser("田中", 25);
echo "{$user->name}({$user->age}歳)\n";
// $user->name = "佐藤"; // Error: Cannot modify readonly property
実行結果
田中(25歳)
ポイント
getter/setterパターン(カプセル化)は面倒に感じるかもしれませんが、後から「価格変更時にログを記録する」「在庫変更時に通知を送る」といった処理を追加しやすくなります。大規模な開発では必須のテクニックです。
注意
publicプロパティは外部から自由に変更できるため、意図しない値(負の価格やnullの名前など)がセットされるリスクがあります。データの整合性が重要な場合は、privateプロパティ + setterメソッドで保護しましょう。
まとめ
->演算子でpublicプロパティの値を直接変更できる- setterメソッドを使うとバリデーション付きの安全な変更が可能
- setterが
$thisを返すとメソッドチェーンが実現できる - PHP 8.1の
readonlyで変更不可のプロパティを定義できる - カプセル化(private + setter)はデータの整合性を保つ基本テクニック