我需要一些帮助来访问 PHP 中受保护数组中的成员函数


I need some help accessing a member function in a protected array in PHP

现在我正在尝试编写一个允许我访问成员函数的函数。有问题的代码看起来有点像这样:

protected $formName;
protected $formClass;
protected $formAction;
protected $formMethod;
protected $formObjArray = array(); //outputs in order. So far it should only take newLine, selectTag, inputTag, textTag.
protected $submitBtnVal;
protected $encType;
function __construct($args) {
  $this->formName = $args['formName'];
  $this->formAction = $args['formAction'];
  if (isset($args['formClass'])) $this->formClass = $args['formClass'];
  if (isset($args['encType'])) $this->encType = $args['encType'];
  //default should be POST. Hell, you should never really be using GET for this..
  //also, the default submit value is Submit
  $this->formMethod = isset($args['formMethod']) ? $args['formMethod'] : "POST"; 
  $this->submitBtnVal = isset($args['submitBtnVal']) ? $args['submitBtnVal'] : "Submit";
}
//get functions
function getFormName () { return $this->formName; }
function getFormAction () { return $this->formAction; }
function getFormMethod () { return $this->formMethod; }
function getSubmitBtnVal () { return $this->submitBtnVal; }
function getEncType () { return $this->encType; }
//set functions
function setFormName ($newName) { $this->fromName = $newName; }
function setFormAction ($newAction) { $this->formAction = $newAction; }
function setFormMethod ($newMethod) { $this->formMethod = $newMethod; }
function setEncType ($newEType) { $this->encType = $newEType; }
function addTag($newTag) {
  if ($newTag instanceof formTag || $newTag instanceof fieldSetCont || $newTag instanceof newLine
      || $newTag instanceof noteTag)
    $this->formObjArray[] = $newTag;
  else throw new Exception ("You did not add a compatible tag.");
}

我希望能够打电话给$myForm->getTagByName("nameA")->setRequired(true);

我该怎么做?还是我需要做一些更像的事情..

$tagID = $myForm->getTagByName("nameA");
$myForm->tagArray(tagID)->setRequired(true);

您的代码中似乎没有任何内容受到保护,因此您应该可以轻松访问其中任何一个。

看起来您的所有标签都在$formObjArray,因此过滤应该比数组和返回与您传入的名称匹配的标签变得微不足道。您将遇到的麻烦是,getTagByName确实应该getTagsByName并且应该返回一个数组,因为您可以有多个具有相同名称的标签。由于它会返回一个数组,所以你不能在返回值上调用setRequired,数组没有这样的方法。您需要更像地执行以下操作:

$tags = $myForm->getTagsByName("nameA");
foreach ($tags as $tag) {
    $tag->setRequired(true);
}

你到底坚持了什么?也许我不太明白这个问题。

所以也许过滤让你卡住了?试试这个(如果你至少使用php 5.3)

function getTagsByName($tagname) 
{
    return array_filter($this->formObjArray, function($tag) use($tagname) { 
        return $tag->getName() == $tagname; 
    });
}

没有如果或开关。

在 5.3 之前,您没有 lambda 函数,因此您需要以不同的方式执行。有几种选择,但这可能是最容易理解的:

function getTagsByName($tagname) 
{
    $out = array();
    foreach ($this->formObjArray as &$tag) {
        if ($tag->getName() == $tagname) {
            $out[] = $tag;
        }
    }
    return $out;
}

在 addTag 方法中,使用 [] 表示法将新标记存储在 $this->formObjArray 中,该表示法只会将新标记附加到数组的末尾。如果你的标签对象都有一个 getName() 方法,那么你可以做这样的事情:

$this->formObjArray[$newTag->getName()] = $newTag;

然后,您可以轻松添加 getTagByName() 方法:

public function getTagByName($name) {
  if (array_key_exists($name, $this->formObjArray) {
    return $this->formObjArray($name);
  }
  else {
    return null;
  }
}

请注意建议你遍历数组中所有标签的解决方案!随着表单变大,这可能会变得非常昂贵。

如果由于添加元素的顺序很重要而需要使用 [] 构造,那么您仍然可以按名称维护一个单独的索引 $this->tagIndex,该索引将是 name => 标记的关联数组。由于您存储的是对象引用,因此它们不会占用太多空间。假设 getTagByName 将被多次使用,这将为您节省大量资源,而不是在每次调用 getTagByName 时迭代标签数组。

在这种情况下,您的 addTag 方法将如下所示:

$this->formObjArray[] = $newTag;
$this->tagIndex[$newTag->getName()] = $newTag; // it seems that you're doubling the memory needed, but you're only storing object references so this is safe

编辑:这是一些修改后的代码,以解释多个标签可以具有相同名称的事实:

在你的addTag()方法中,执行:

$this->formObjArray[] = $newTag;
$tag_name = $newTag->getName();
if (!array_key_exists($tag_name, $this->tagIndex)) {
  $this->tagIndex[$tag_name] = array();
}
$this->tagIndex[$tag_name][] = $newTag

然后,您可以将 getTagByName 重命名为 getTagsByName 并获得预期的结果。

如注释中所述,这仅在多次调用getTagsByName时才有用。您正在交换一点额外的内存使用量,以便按名称更快地查找。