0

当您只想在某些时候调用带有 byref 参数的函数时,您会做什么(在最近的 PHP 中)?

function blah_byval ($arg) { /* some code */ }
function blah_byref (&$arg) { /* same code */ }

对我来说似乎很迟钝。我肯定错过了什么。

我确实有一个用例,尽管这个问题基本上是假设性的。这是一个正在进行的验证码实施:

function captcha_image($string = "", $create = true, $session = "") {

  # outputs a transparent gif image 16 pixels high by 60 pixels wide containing
  # a string of six lowercase letters, either specified by $string or generated
  # randomly. returns this string, or false in the event of an error.

  # once a captcha image is created, the string it contains should be saved so
  # that it can be compared later with user input. to skip saving, set $create
  # to false.

  # if called from a web server, content-type is set.

  if (!preg_match("/^[a-z]{6}$/", $string)) $string = string_random(6);
  if (php_sapi_name() != "cli") header("Content-Type: image/gif");
  if ($ihandle = @imagecreatetruecolor(60, 16)) {
    $background = imagecolorallocate($ihandle, 255, 255, 255);
    $foreground = imagecolorallocate($ihandle, 128, 128, 128);
    imagecolortransparent($ihandle, $background);
    imagefilledrectangle($ihandle, 0, 0, 60, 16, $background);
    imagestring($ihandle, 5, 0, 0, $string, $foreground);
    imagegif($ihandle, NULL);
    imagedestroy($ihandle);
    if ($create) return captcha_create($string, $session);
    return $string;
  }
  return false;
}

function captcha_compare($string, $session = "", $destroy = true) {

  # returns true if $string is associated with a certain session, which is
  # specified by $session or, if no such session exists, by session_identity().
  # if $string is not associated with the session, returns false.

  # once a string is matched to a session, it should be destroyed to prevent
  # re-use. to allow re-use, $destroy may be set to false.

  global $cfgimage;
  if (!session_exists($session)) $session = session_identity();
  $get_return = false;
  if ($chandle = @fopen($cfgimage['captcha']['file'], "rb")) {
    flock($chandle, LOCK_SH);
    while (!feof($chandle)) {
      $line = explode(" ", trim(fgets($chandle)), 3);
      if (($line[2] === $string) && ($line[1] == $session) && ($line[0] > (time() - $cfgimage['captcha']['keepalive']))) {
        $get_return = true;
        break;
      }
    }
    fclose($chandle);
  }
  if (($destroy) && ($get_return)) captcha_destroy($session);
  return $get_return;
}

function captcha_create($string, $session = "") {

  # associates a string of six lowercase letters with a session, either
  # specified by $session or by session_identity(). fails if $string is not
  # well-formed. returns true if successful, or false.

  global $cfgimage;
  if (!preg_match("/^[a-z]{6}$/", $string)) return false;
  if (!session_exists($session)) $session = session_identity();
  if ($thandle = @tmpfile()) {
    if ($chandle = @fopen($cfgimage['captcha']['file'], "rb")) {
      flock($chandle, LOCK_SH);
      while (!feof($chandle)) {
        $line = explode(" ", trim(fgets($chandle)), 3);
        if (($line[1] != $session) && ($line[0] > (time() - $cfgimage['captcha']['keepalive']))) fputs($thandle, implode(" ", $line) . "\n");
      }
      fclose($chandle);
      fseek($thandle, 0);
      if ($chandle = @fopen($cfgimage['captcha']['file'], "cb")) {
        if (flock($chandle, LOCK_EX)) {
          fputs($chandle, time() . " " . $session . " " . $string . "\n");
          while (!feof($thandle)) fputs($chandle, fgets($thandle));
        }
        fclose($chandle);
      }
    }
    flock($thandle, LOCK_UN);
    fclose($thandle);
    return true;
  }
  return false;
}

function captcha_destroy($session = "") {

  # dis-associates any existing captcha string with a session, either specified
  # by $session or by session_identity(). does not return any value.

  global $cfgimage;
  if (!session_exists($session)) $session = session_identity();
  if ($thandle = @tmpfile()) {
    if ($chandle = @fopen($cfgimage['captcha']['file'], "rb")) {
      flock($chandle, LOCK_SH);
      while (!feof($chandle)) {
        $line = explode(" ", trim(fgets($chandle)), 3);
        if (($line[1] != $session) && ($line[0] > (time() - $cfgimage['captcha']['keepalive']))) fputs($thandle, implode(" ", $line) . "\n");
      }
      fclose($chandle);
      fseek($thandle, 0);
      if ($chandle = @fopen($cfgimage['captcha']['file'], "cb")) {
        if (flock($chandle, LOCK_EX)) {
          while (!feof($thandle)) fputs($chandle, fgets($thandle));
        }
        fclose($chandle);
      }
    }
    flock($thandle, LOCK_UN);
    fclose($thandle);
  }
}

在 captcha_image() 中,return captcha_create($string, $session)以前是captcha_create(&$string ...).

4

1 回答 1

3

这在用户态代码中是不可能的。对于手头的内部函数,您可以PREFER_REF在 arginfo 结构中指定标志。如果可能,这将传递值 by-ref,否则传递值。

在我看来,这个特性不暴露给用户态代码是件好事。在任何情况下,引用都是一件棘手的事情,并且根据您传递内容的准确程度,使它们具有不同的行为可选,只会使情况变得更糟。

我的建议:不要完全使用引用。你只会对他们有问题。

于 2012-07-11T21:46:50.073 回答