【PHP】配列の変数を増やさずに連想配列のキーを変更したいときは unset を使う

PHP

連想配列のキーを変更したい。基本はそんなことはないのだけども、どうしても変えたいとなった時に作った関数です。

foreach で回す

ひとまず誰もが考えそうなことは以下のように新しい配列を作って値を入れていく。

$ary = [
 "key_1" => "value_1",
 "key_2" => "value_2",
];

$new_aray = [];

foreach ($ary as $key => $value){
  $new_aray["new_".$key] => $value;
}

こうしてもいいのですが、クラスを使うときにちょっとしか使わない変数が増えてしまうと気持ち悪いという方もいると思います。

配列の変数をそのまま利用したい場合

上記の例でも正しく動くとは思いますが、前述の通り自分は使用頻度の低い変数は気持ち悪いため、変数を増やさないためにはどうしたらいいかを考えました。まずは素直に。。

$ary = [
 "key_1" => "value_1",
 "key_2" => "value_2",
];

$new_aray = [];

foreach ($ary as $key => $value){
  $new_aray["new_".$key] => $value;
}

お気付きの通り、これだと元々のキーが残ってしまいます。このままだと foreach で利用する時に、キー名での条件分岐が必要になってしまいます。
というわけで、元々あった配列のキーは削除しましょう。

$ary = [
 "key_1" => "value_1",
 "key_2" => "value_2",
];

$new_aray = [];

foreach ($ary as $key => $value){
  $new_aray["new_".$key] => $value;
  unset($ary[$key]);
}

このようにすることで同じ変数で新しいキー名の連想配列を作ることができました。

こんなのどこで使ったのか

最近、PDOで流行りのフレームワークっぽくDBをいじれるクラスを作ったりしています。以下のような感じでもまだまだ面倒な記述は多いですが、だいぶスッキリしたかなと思ってます。

  $category = new \App\Db\Category();
  $category->setUpdateData([":title" => $post_datas["title"]]);
  $category->setUpdateCondition([":id" => $edit_id]);
  $category->update();

updateの前に連想配列を渡してあげて、PDOのプリペアドステートメントを作っています。最後のupdateFromAssociativeArray のメソッドはそのまま updateData と where の条件である updateCondition の配列をマージして渡してあげれば、データが更新されます。
ちなみに複数の値や複数の条件で更新できるように見えますができません。AND も OR も備えてません。

public function update(){
  $query = "update ". $this->tableName ." set ";
  foreach ($this->updateData as $key => $value){
    $query .= str_replace(":", "", $key) . "=" . $key . " ";
  }
  $query .= "where ";
  foreach ($this->updateCondition as $key => $value){
    $query .= str_replace(":", "", $key) . "=" . $key . "_cond ";
    $this->updateCondition[$key."_cond"] = $value;
    unset($this->updateCondition[$key]);
  }
  $this->updateFromAssociativeArray($query);
}

public function setUpdateData($data){
  $this->updateData = $data;
}

public function setUpdateCondition($data){
  $this->updateCondition = $data;
}

private function updateFromAssociativeArray($query){
  try{
      $stmt = $this->dbh->prepare($query);
      $data = array_merge($this->updateData, $this->updateCondition);
      $stmt->execute($data);
    } catch (PDOException $e) {
      var_dump( $e->getMessage() );
    }
}

それぞれの変数の中身は以下のようになっています。

$query
=> string 'update categories set title=:title where id=:id_cond ' (length=53)

$data
=> array (size=2)
     ':title' => string 'Bootsfdsa' (length=9)
     ':id_cond' => string '1' (length=1)

複数にも対応したい

特に必要ないけど、そのうち頑張って複数の値や条件にも対応させたいとは思ってます。ただこの方法だとなんか違うというのと、手順も多くなる気がしてるので、変える予定です。

コメント