【问题标题】:Filter ModelAdmin by many_many relation按 many_many 关系过滤 ModelAdmin
【发布时间】:2015-11-26 23:58:12
【问题描述】:

我正在使用 ModelAdmin 管理 DataObject 类“培训师”。培训师与我的其他课程“语言”有很多关系。

在我的“培训师”课程中,我正在操作“searchableFields”函数以在过滤器区域中显示一个 ListboxField。

public function searchableFields() {
  $languagesField = ListboxField::create(
    'Languages',
    'Sprachen',
    Language::get()->map()->toArray()
  )->setMultiple(true);

  return array (
    'Languages' => array (
      'filter' => 'ExactMatchFilter',
      'title' => 'Sprachen',
      'field' => $languagesField               
    )
  );
}

这就像预期的那样工作,并向我展示了想要的 ListboxField。问题是,在选择 1 或 2 或任何语言并提交表单后,我收到了

[警告] trim() 期望参数 1 是字符串,给定数组

这里是否可以使用 many_many 关系进行过滤?如果是这样,怎么办?如果有人能指出我正确的方向,那就太好了。

更新:

完整的错误信息:http://www.sspaste.com/paste/show/56589337eea35

培训师班:http://www.sspaste.com/paste/show/56589441428d0

【问题讨论】:

    标签: silverstripe


    【解决方案1】:

    您需要在 $searchable_fields 参数中定义该逻辑,而不是实际构造可搜索字段和逻辑的 searchableFields()。

    如果您在数组本身中执行花哨的表单内容,PHP 可能会抛出错误,因此将该表单字段农场到同一个 DataObject 中的单独方法并简单地调用它。

    看我的例子,希望对你有帮助。

    /* Define this DataObjects searchable Fields */
    private static $searchable_fields = array(
        'Languages' => array (
          'filter' => 'ExactMatchFilter',
          'title' => 'Sprachen',
          'field' => self::languagesField()               
        )
    );
    
    /* Return the searchable field for Languages */
    public function languagesField() {
      return ListboxField::create(
        'Languages',
        'Sprachen',
        Language::get()->map()->toArray()
      )->setMultiple(true);
    }
    

    【讨论】:

    • 谢谢你的回答,你有没有这样用过?不幸的是,它在'field' => self::languagesField() 上向我抛出了一个语法错误。我认为你不能在这里调用函数?
    • 你能不能复制错误信息本身。是的,我之前以类似的方式完成了它。 SilverStripe 有时很难在不查看所有代码的情况下进行调试。
    • 如果做不到这一点,请完全忽略语言字段()方法,只需将字段声明直接放在数组的“字段”键上。但是,通常 SilverStripe 只需要相关字段的类名称。因此,请尝试仅使用 ListboxField 或 Dropdown 字段,因为我不确定它是否足够聪明以接受来自 Listbox 的多个值。
    • 另外,也许在字段标题上使用点表示法。所以使用 Languages.Title 代替 Languages,其中 Languages 是 many_many 中引用的类,Title 是数据库列。
    • 好的,虽然不是修复,但我刚刚查看了 SilverStripe IRC 聊天记录中有关该主题的信息,另一位开发人员最近提出了它。看起来 SilverStripe 的核心目前无法在 ModelAdmin 的 $searchable_fields 功能中执行您所要求的操作,而无需对核心本身进行修改。您应该能够通过使用表单构建 LeftAndMain 的自定义扩展来实现此目的,该表单在提交时会更改 GridField 的视图,或者使用自定义 GridField 扩展。请参阅 SilverStripe 的文档。
    【解决方案2】:

    是的,这是可能的。您只需要覆盖两种方法 - 一种在 Trainer 数据对象中,另一种在 TrainerModelAdmin 中。第一个将创建一个字段,第二个将进行过滤。

    培训师数据对象:

    public function scaffoldSearchFields($_params = null)
    {
        $fields = parent::scaffoldSearchFields($_params);
    
        // get values from query, if set
        $query = Controller::curr()->request->getVar('q');
        $value = !empty($query['Languages']) && !empty($query['Languages']) ? $query['Languages'] : array();
    
        // create a field with options and values
        $lang = ListboxField::create("Languages", "Sprachen", Language::get()->map()->toArray(), $value, null, true);
    
        // push it to field list
        $fields->push($lang);
    
        return $fields;
    }
    

    培训师模型管理员

    public function getList()
    {
        $list = parent::getList();
    
        // check if managed model is right and is query set
        $query = $this->request->getVar('q');
        if ($this->modelClass === "Trainer" && !empty($query['Languages']) && !empty($query['Languages']))
        {
    
            // cast all values to integer, just to be sure
            $ids = array();
            foreach ($query['Languages'] as $lang)
            {
                $ids[] = (int)$lang;
            }
    
            // make a condition for query
            $langs = join(",", $ids);
    
            // run the query and take only trainer IDs
            $trainers = DB::query("SELECT * FROM Trainer_Languages WHERE LanguageID IN ({$langs})")->column("TrainerID");
    
            // filter query on those IDs and return it
            return $list->filter("ID", $trainers);
        }
        return $list;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-15
      • 2019-06-19
      • 2014-10-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多