Отфильтруйте экземпляры "подмодели" из выпадающего списка

Я создал новое расширение Typo3 с помощью кикстартера.
и мой Cities модель имеет несколько street моделей.
В шаблоне street модели из city перечислены в выпадающем меню, как это:



Код шаблона:

<f:section name="main">
    <h1>Single View for City</h1>

    <f:flashMessages renderMode="div" />
    <f:render partial="City/Properties" arguments="{city:city}" />
    Filter:<br>
    <a href='<f:uri.action controller="City" action="showFiltered"  arguments="{city:city, char : 'a'}" />'>A</a>
    <a href='<f:uri.action controller="City" action="showFiltered"  arguments="{city:city, char : 'b'}" />'>B</a>
    <a href='<f:uri.action controller="City" action="showFiltered"  arguments="{city:city, char : 'c'}" />'>C</a>
    <br>
    <f:debug>{city}</f:debug>
    <select onchange="location = this.options[this.selectedIndex].value;">
            <option>Select street</option>
        <f:for each="{city.streets}" as="street">
            <option value='<f:uri.action controller="Street"  action="show"  arguments="{street : street}" />' >{street.name}</option>
        </f:for>
    </select>
    <br>
    <f:link.action action="list">Back to list</f:link.action><br />
    <br>
    <f:link.action action="new">New City</f:link.action>
</f:section>

Теперь мне нужно отфильтровать записи по их первому символу, используя ссылки над раскрывающимся списком.
(А, В, С).
Например, после нажатия A только Aviation а также Automation будет показано...

Когда я выброшу city я получаю это:

Но в не знаю, как получить доступ к улицам в моем showFiltered действие:

public function showFilteredAction(\Vendor\CollectionPlan\Domain\Model\City $city) {
        $char = $this->request->getArgument('char');

        $this->view->assign('city', $city);
        $this->view->assign('char', $char);
    }

построить что-то вроде этого:

public function showFilteredAction(\ActiView\CollectionPlan\Domain\Model\City $city) {
        $char = $this->request->getArgument('char');

        /* This is pseudocode to demonstrate my idea */
        foreach($city => street as $street){  /* Loop through the streets of the city model */
            if(!$street => name.startsWith($char)){ /* Check if the streets name starts with the filter key */
                $street.remove(); /* If it doesn't  remove it from the city variable */
            }
        }
        $this->view->assign('city', $city);
        $this->view->assign('char', $char);
    }

TL; DR
Как я могу получить доступ к улицам городской модели в своем действии контроллера, чтобы проверить, начинаются ли они с заданного ключа?

1 ответ

Решение

Каждое поле, к которому вы обращаетесь через точечную нотацию в контроллере флюидов, имеет геттер и сеттер (по крайней мере, если вы создали его с помощью Extension Builder), более того, вы не должны удалять улицу из коллекции, так как диспетчер постоянства удалит их, вместо этого добавьте в модель города переходный процесс с типом т.е. массива, давайте назовем его $streetsFilteredTransient и создайте геттер, который будет фильтровать улицы:

Просто поместите это в модель вашего города и исправьте GeneralUtility::_GP метод

/**
 * The transient field in model is that which haven't a declaration
 * in TCA and field in SQL file
 * so it's ideal for *processing* other fields...
 *
 * @var array
 */
protected $streetsFilteredTransient = array();

/**
 * Returns array of street objects which names begins with char,
 * or all streets if no char is given
 *
 * @return array Array of objects
 */
public function getStreetsFilteredTransient() {

    // As model has no access to request you need to fetch the `char` argument *manually*
    $arguments = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('tx_flysites_show');
    $char = (!is_null($arguments) && isset($arguments['char'])) 
        ? htmlspecialchars($arguments['char']) 
        : false;

    foreach ($this->kinds as $street) {
        if (!$char || $this->startsWith($street->getName(), $char))
            $this->streetsFilteredTransient[] = $street;
    }
    return $this->streetsFilteredTransient;
}


private function startsWith($haystack, $needle) {
    $haystack = strtolower($haystack);
    $needle = strtolower($needle);
    $length = strlen($needle);
    return (substr($haystack, 0, $length) === $needle);
}

и использовать его в виде как:

<f:for each="{city.streetsFilteredTransient}" as="street">
    ...
</f:for>
Другие вопросы по тегам