Что ж, после копания в процессе click () я не могу получить ожидаемый результат.
Решения следуют за проблемой:
в теге <select multiple>
, я ожидаю, что если я не буду публиковать какие-либо значения, он будет публиковать его как есть, а если я укажу значения, он будет публиковать только те и не будет пытаться контролировать вкл / выкл по значениям.
То, как он реагирует сейчас, заключается в том, что начальные значения и выбранные значения объединяются вместе, и ключи начальных значений, соответствующие ключам выбранных значений, заменяются, что не имеет смысла для меня, потому что эти ключи или их порядок не имеют значения. Меня интересуют только выбранные значения параметров.
Ответ на мой вопрос таков: Вы не можете делать то, что ожидаете с текущей реализацией.
Решение:
Переопределите (или отправьте патч, если у вас есть время) функцию doClickElement в классе sfBrowserBase, которая может выглядеть следующим образом: (ищите 3 комментария // исправление для выбора нескольких и последних 2 методов для добавления)
public function doClickElement(DOMElement $item, $arguments = array(), $options = array())
{
$method = strtolower(isset($options['method']) ? $options['method'] : 'get');
if ('a' == $item->nodeName)
{
if (in_array($method, array('post', 'put', 'delete')))
{
if (isset($options['_with_csrf']) && $options['_with_csrf'])
{
$arguments['_with_csrf'] = true;
}
return array($item->getAttribute('href'), $method, $arguments);
}
else
{
return array($item->getAttribute('href'), 'get', $arguments);
}
}
else if ('button' == $item->nodeName || ('input' == $item->nodeName && in_array($item->getAttribute('type'), array('submit', 'button', 'image'))))
{
// add the item's value to the arguments
$this->parseArgumentAsArray($item->getAttribute('name'), $item->getAttribute('value'), $arguments);
// use the ancestor form element
do
{
if (null === $item = $item->parentNode)
{
throw new Exception('The clicked form element does not have a form ancestor.');
}
}
while ('form' != $item->nodeName);
}
// form attributes
$url = $item->getAttribute('action');
if (!$url || '#' == $url)
{
$url = $this->stack[$this->stackPosition]['uri'];
}
$method = strtolower(isset($options['method']) ? $options['method'] : ($item->getAttribute('method') ? $item->getAttribute('method') : 'get'));
// merge form default values and arguments
$defaults = array();
$arguments = sfToolkit::arrayDeepMerge($this->fields, $arguments);
// fix for select multiple
$select_multiple_to_check = array();
$xpath = $this->getResponseDomXpath();
foreach ($xpath->query('descendant::input | descendant::textarea | descendant::select', $item) as $element)
{
if ($element->hasAttribute('disabled'))
{
continue;
}
$elementName = $element->getAttribute('name');
$nodeName = $element->nodeName;
$value = null;
if ($nodeName == 'input' && ($element->getAttribute('type') == 'checkbox' || $element->getAttribute('type') == 'radio'))
{
// fix for select multiple
if (substr($elementName, -2) == '[]')
{
$select_multiple_to_check[$elementName] = true;
}
if ($element->getAttribute('checked'))
{
$value = $element->hasAttribute('value') ? $element->getAttribute('value') : '1';
}
}
else if ($nodeName == 'input' && $element->getAttribute('type') == 'file')
{
$filename = array_key_exists($elementName, $arguments) ? $arguments[$elementName] : sfToolkit::getArrayValueForPath($arguments, $elementName, '');
if (is_readable($filename))
{
$fileError = UPLOAD_ERR_OK;
$fileSize = filesize($filename);
}
else
{
$fileError = UPLOAD_ERR_NO_FILE;
$fileSize = 0;
}
unset($arguments[$elementName]);
$this->parseArgumentAsArray($elementName, array('name' => basename($filename), 'type' => '', 'tmp_name' => $filename, 'error' => $fileError, 'size' => $fileSize), $this->files);
}
else if ('input' == $nodeName && !in_array($element->getAttribute('type'), array('submit', 'button', 'image')))
{
$value = $element->getAttribute('value');
}
else if ($nodeName == 'textarea')
{
$value = '';
foreach ($element->childNodes as $el)
{
$value .= $this->getResponseDom()->saveXML($el);
}
}
else if ($nodeName == 'select')
{
if ($multiple = $element->hasAttribute('multiple'))
{
// fix for select multiple
$select_multiple_to_check[$elementName] = true;
$elementName = str_replace('[]', '', $elementName);
$value = array();
}
else
{
$value = null;
}
$found = false;
foreach ($xpath->query('descendant::option', $element) as $option)
{
if ($option->getAttribute('selected'))
{
$found = true;
if ($multiple)
{
$value[] = $option->getAttribute('value');
}
else
{
$value = $option->getAttribute('value');
}
}
}
$option = $xpath->query('descendant::option', $element)->item(0);
if (!$found && !$multiple && $option instanceof DOMElement)
{
$value = $option->getAttribute('value');
}
}
if (null !== $value)
{
$this->parseArgumentAsArray($elementName, $value, $defaults);
}
}
// fix for select multiple
foreach($select_multiple_to_check as $elementName => $uselessbool)
{
$path = array_filter(preg_split('/(\[ | \[\] | \])/x', $elementName), create_function('$s', 'return $s !== "";'));
if ($this->findInArrayByArrayPath($arguments, $path) !== false)
{
$this->unsetInArrayByArrayPath($defaults, $path);
}
}
$arguments = sfToolkit::arrayDeepMerge($defaults, $arguments);
if (in_array($method, array('post', 'put', 'delete')))
{
return array($url, $method, $arguments);
}
else
{
$queryString = http_build_query($arguments, null, '&');
$sep = false === strpos($url, '?') ? '?' : '&';
return array($url.($queryString ? $sep.$queryString : ''), 'get', array());
}
}
// fix for select multiple
// taken from /3095100/ustanovit-mnogomernyi-massiv-po-klychevomu-puti-iz-znachenii-massiva#3095135
public function findInArrayByArrayPath(&$array, &$path, $_i=0) {
// sanity check
if ( !(is_array($array) && is_array($path)) ) return false;
$c = count($path); if ($_i >= $c) return false;
if ($_i==0) {$path = array_values($path);} // to make sure we don't get skipped numeric keys which does happens in the preg_split above
$k = $path[$_i];
if (array_key_exists($k, $array))
return ($_i == $c-1) ? $array[$k] : $this->findInArrayByArrayPath($array[$k], $path, $_i+1);
else
return false;
}
// fix for select multiple
public function unsetInArrayByArrayPath(&$array, &$path, $_i=0) {
// sanity check
if ( !(is_array($array) && is_array($path)) ) return false;
$c = count($path); if ($_i >= $c) return false;
if ($_i==0) {$path = array_values($path);} // to make sure we don't get skipped numeric keys which does happens in the preg_split above
$k = $path[$_i];
if (array_key_exists($k, $array))
if ($_i == $c-1) {
unset($array[$k]);
return true;
} else {
return $this->unsetInArrayByArrayPath($array[$k], $path, $_i+1);
}
else
return false;
}
И сейчас:
'profile' => array ('region_list' => array (8,9)) у меня работает.