【今すぐ使える】PHPで「str_decrement」関数を使ってパスワードのリセットトークンの有効期限を減らす方法


str_decrement 関数は、PHP 8.3 以降で導入された、英数字の ASCII 文字列をデクリメント (1 つ減らす) するための関数です。これは、str_increment 関数の逆の動作となります。

機能

  • 文字列が空の場合、または英数字の ASCII 文字列でない場合、またはデクリメントできない場合 (例: "A" や "0") は、ValueError 例外をスローします。
  • 引数の文字列を 1 つデクリメントした新しい文字列を返します。
  • 英数字の ASCII 文字列を引数として受け取ります。

動作例

$str = 'ABC';
var_dump(str_decrement($str)); // string(3) "ABB"

$str = 'ZA';
var_dump(str_decrement($str)); // string(2) "YZ"

$str = 'AA';
var_dump(str_decrement($str)); // string(1) "Z"

詳細

  • デクリメントによって桁あふれが発生した場合、次の桁が 1 つずつ繰り下げられます (例: "ZY" から "XY" へのデクリメント)。
  • 英数字以外の文字は、そのまま保持されます。
  • 各文字は、ASCII コード値に基づいてデクリメントされます。
  • str_decrement 関数は、文字列の先頭から末尾に向かって処理されます。

使用例

  • データベース内のレコードのシーケンス番号を調整する。
  • パスワードのリセットトークンの有効期限を減らす。
  • 商品コードやバージョン番号などの英数字シーケンスを自動的に更新する。
  • デクリメントによって桁あふれが発生する可能性があることを考慮する必要があります。
  • 文字列が空の場合、またはデクリメントできない場合、ValueError 例外が発生します。
  • str_decrement 関数は、英数字の ASCII 文字列にのみ使用できます。


<?php

function updateProductCode($code) {
  // 英数字部分のみを抽出
  $alphaNumeric = preg_replace('/[^a-zA-Z0-9]/', '', $code);

  // デクリメント
  $newCode = str_decrement($alphaNumeric);

  // 英数字部分と非英数字部分を結合
  return $newCode . preg_replace('/[a-zA-Z0-9]/', '', $code);
}

$originalCode = 'AB123';
$newCode = updateProductCode($originalCode);
echo "オリジナルコード: $originalCode\n";
echo "更新されたコード: $newCode\n";

例 2: パスワードのリセットトークンの有効期限を減らす

この例では、str_decrement 関数を使用して、パスワードのリセットトークンの有効期限を 1 日減らします。

<?php

function decrementTokenExpiration($token) {
  // 有効期限部分のみを抽出
  $expiration = preg_match('/\d+/', $token, $matches);
  if (!$expiration) {
    throw new Exception('Invalid token format');
  }

  // デクリメント
  $newExpiration = str_decrement($matches[0]);

  // 有効期限部分を更新
  return preg_replace('/\d+/', $newExpiration, $token);
}

$token = 'token1234567890';
$newToken = decrementTokenExpiration($token);
echo "オリジナルトークン: $token\n";
echo "更新されたトークン: $newToken\n";

例 3: データベース内のレコードのシーケンス番号を調整する

この例では、str_decrement 関数を使用して、データベース内のレコードのシーケンス番号を 1 つ減らします。

<?php

function adjustSequenceNumber($sequenceNumber) {
  // シーケンス番号部分のみを抽出
  $sequence = preg_replace('/[^0-9]/', '', $sequenceNumber);

  // デクリメント
  $newSequence = str_decrement($sequence);

  // シーケンス番号部分を更新
  return preg_replace('/[^0-9]/', $newSequence, $sequenceNumber);
}

$sequenceNumber = 'REC0001';
$newSequenceNumber = adjustSequenceNumber($sequenceNumber);
echo "オリジナルのシーケンス番号: $sequenceNumber\n";
echo "更新されたシーケンス番号: $newSequenceNumber\n";
  • エラー処理や境界条件のチェックを追加することを忘れないでください。


手動でデクリメントする

最も単純な方法は、文字列をループで処理し、各文字を個別にデクリメントすることです。

function decrementString($str) {
  $newStr = '';
  for ($i = 0; $i < strlen($str); $i++) {
    $char = $str[$i];
    if (ctype_alpha($char)) {
      $newChar = chr(ord($char) - 1);
      if ($newChar < 'A') {
        $newChar = 'Z';
      }
    } elseif (ctype_digit($char)) {
      $newChar = chr(ord($char) - 1);
      if ($newChar < '0') {
        $newChar = '9';
      }
    } else {
      $newChar = $char;
    }
    $newStr .= $newChar;
  }
  return $newStr;
}

$str = 'ABC123';
$newStr = decrementString($str);
echo "オリジナルの文字列: $str\n";
echo "デクリメントされた文字列: $newStr\n";

正規表現を使用する

正規表現を使用して、英数字の文字を 1 つずつ置換する方法もあります。

function decrementStringRegex($str) {
  return preg_replace('/([a-zA-Z])/', function ($match) {
    $char = $match[1];
    if ($char === 'Z') {
      return 'Y';
    } else {
      return chr(ord($char) + 1);
    }
  }, $str);
}

$str = 'ABC123';
$newStr = decrementStringRegex($str);
echo "オリジナルの文字列: $str\n";
echo "デクリメントされた文字列: $newStr\n";

サードパーティライブラリを使用する

str_decrement 関数と同等の機能を提供するサードパーティライブラリもいくつか存在します。

これらのライブラリは、str_decrement 関数よりも多くの機能を提供している場合があります。

  • サードパーティライブラリを使用する場合は、ライブラリのドキュメントをよく読んでから使用してください。
  • 正規表現を使用する場合は、正規表現の構文に十分注意する必要があります。
  • 上記の代替方法は、str_decrement 関数よりも処理速度が遅くなる可能性があります。