0

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

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);
4

2 回答 2

2

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

看起来您的所有标签都在 $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;
}
于 2012-05-28T01:31:55.703 回答
1

在您的 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 并获得预期的结果。

As mentioned in the comments, this is only useful if you will call getTagsByName multiple times. You are trading a little additional memory usage in order to get quicker lookups by name.

于 2012-05-28T02:18:28.530 回答