web-dev-qa-db-ja.com

関数で変数を使用する方法の何が問題になっていますか?

私は次のような関数を持っています:

function mymodule_privatemsg_message_validate($message) {
  $uid = $vars['message']->author->uid;

  //if root or help user, message should always go through regardless of length
  if ($uid !== '1') {
    if ($uid !== '3') {

      if (empty($message->thread_id) && strlen($message->body) < 200 ) {
    form_set_error('[body][value]', t('My custom message.'));
      }
    }
  }
}

しかし、私は コメント を受け取りました。「補足として、$ varsを使用していますが、その変数は関数から初期化されておらず、関数のパラメーターでもありません。」これが何を意味するのか、私が間違っているのか理解できません。誰かが私にこれを説明できますか?

2
Patrick Kenny

hook_privatemsg_message_validate() に指定されたパラメーターは、_$message_、および_$form_で、デフォルト値はFALSEです。
_$vars_は、関数に渡されるパラメーターではなく、関数から定義されたローカル変数でもありません。この結果、_$vars_の値はNULLになります。 _$vars['message']->author->uid_にアクセスしようとすると、PHPは2つの警告を表示します。

  • 未定義の変数:vars
  • 非オブジェクトのプロパティを取得しようとしています

最初の警告は、変数が関数から定義されていないためです。コードで_$vars_に値が割り当てられている場合、警告は表示されません。 _$vars_がグローバル(_global $vars;_を使用)として定義されていて、別の関数からすでに初期化されている場合にも機能します。
2番目の警告は、定義されていないすべてのPHP変数が、NULLである自動値を取得するためです。_$vars_はNULL、および_$vars['message']_も同様であり、NULLはオブジェクトではありません。

その結果、_$uid_もNULLに設定されます。

次のコードも間違っています。

_  if ($uid !== '1') {
    if ($uid !== '3') {
      if (empty($message->thread_id) && strlen($message->body) < 200 ) {
        form_set_error('[body][value]', t('My custom message.'));
      }
    }
  }
_

_$uid !== '1'_を使用すると、PHP _$uid_が_'1'_とは異なる値の文字列であるかどうかを確認します。_$uid_の場合が1(整数)に設定されている場合、次のコードは_"different"_ではなく_"equal"_を出力します。

_$uid = 1;

if ($uid !== '1') {
  print "different";
else {
  print "equal";
}
_

これとは異なり、次のコードは_"equal"_を出力します。

_$uid = 1;

if ($uid != '1') {
  print "different";
else {
  print "equal";
}
_

また、次のコードは_"equal"_を出力します。 (読者にとって、その理由を理解するためのタスク。_;)_)

_$uid = '1a';

if ($uid != 1) {
  print "different";
else {
  print "equal";
}
_

ユーザーオブジェクトのユーザーIDは文字列ではなく整数であるため、作成するつもりだったのは次のコードです。

_function mymodule_privatemsg_message_validate($message) {
  $uid = $message->author->uid;

  //if root or help user, message should always go through regardless of length
  if ($uid != 1 && $uid != 3) {
    if (empty($message->thread_id) && strlen($message->body) < 200 ) {
      form_set_error('[body][value]', t('My custom message.'));
    }
  }
}
_

_$message->author_が_$message_に対して定義されたプロパティであるかどうかはわかりませんが、それが本当に必要なものだと思います。

ちなみに、ユーザーオブジェクトのユーザーIDを確認することは避け、その値に基づいてアクションを実行したいと思います。 Drupalでは、次のようなコードを使用して、ユーザーに権限があるかどうかを確認することをお勧めします。

_if (user_access('permission to check', $account)) {
  // The user has the permission.
}
_

_$account_はユーザーオブジェクトです。

ユーザーIDしかない場合は、次のコードを使用できます。

_$account = user_load($uid);
if ($account && user_access('permission to check', $account)) {
  // The user has the permission.
}
_

ユーザーIDの代わりに権限をチェックする理由は、コードの保守性です。 100人のユーザーがいて、そのうち50人だけにエラーメッセージが表示される場合を想像してみてください。_$uid_の値が、エラーメッセージが表示されないユーザーのユーザーIDではないことを確認する必要があります。連続する値がない場合(ユーザーIDが1と3の場合のように)、各値を個別に確認する必要があります。

補足として、user_access()は常にユーザー#1に対してTRUEを返します。実際、この関数には次のコードが含まれています。

_function user_access($string, $account = NULL) {
  global $user;

  if (!isset($account)) {
    $account = $user;
  }

  // User #1 has all privileges:
  if ($account->uid == 1) {
    return TRUE;
  } 

  // ...
}
_

制御ステートメントが_$account->uid == 1_ではなく_$account->uid === '1'_を使用していることに注意してください。

3
kiamlaluno

関数のスコープで変数を使用できるようにするには、変数を初期化する必要があります(または、グローバルスコープで初期化し、globalを使用してローカル関数にインポートする必要があります)。

現時点では、$vars変数を宣言したり渡したりするものは何もありません...初期化されていないため、警告が表示されます。

$messageという関数に変数を渡しています。これは、コードが次のようになっていることを示しています。

$uid = $message->author->uid;

$vars/$variablesとの混同は、テーマ関数に渡される唯一の引数の標準名のようなものであるという事実が原因である可能性があります。

function MYTHEME_preprocess_node(&$vars) {
  // Use $vars
4
Clive

そのフックの型シグネチャを見ると、

function hook_privatemsg_message_validate($message, $form = FALSE) {
}

$varsは関数パラメーターではなく、gloablであると宣言していません。そのまま使用すると、PHP文句を言う(さまざまな未定義の変数通知の1つ)。現状では、$uidから何かを抽出しようとすると、$varsは未定義になります。

2
mpdonadio