从下拉列表中过滤 "sub-model" 个实例

Filter "sub-model" instances from dropdown

我用 kickstarter 创建了一个新的 Typo3 扩展
我的 Cities 模型有多个 street 模型。
在模板中,citystreet 模型列在下拉菜单中,如下所示:



模板代码:

<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, B, C).
例如。单击 A 后,只会显示 AviationAutomation...

当我输出 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
如何在我的控制器操作中访问城市模型的街道以检查它们是否以给定的键开头?

您通过流体控制器中的点符号访问的每个字段都有 getter 和 setter(至少如果您使用 Extension Builder 创建它),而且您不应该从集合中删除街道因为持久性管理器将删除它们,而是将类型添加到您的城市模型 transient 中,我们将其命名为 $streetsFilteredTransient 并创建一个 getter 来过滤街道:

只需将其放入您的城市模型,然后修复 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>