0
votes

I'm managing the DataObject class 'trainer' with ModelAdmin. A trainer has a many_many relation to my other class 'language'.

On my 'trainer' class I'm manipulating the 'searchableFields' function to display a ListboxField in the filters area.

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

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

That works like expected and shows me the wanted ListboxField. The Problem is, after selecting 1 or 2 or whatever languages and submitting the form, I'm receiving

[Warning] trim() expects parameter 1 to be string, array given

Is it possible here to filter with an many_many relation? And if so, how? Would be great if someone could point me in the right direction.

Update:

Full Error Message: http://www.sspaste.com/paste/show/56589337eea35

Trainer Class: http://www.sspaste.com/paste/show/56589441428d0

2

2 Answers

0
votes

You need to define that logic within a $searchable_fields parameter instead of the searchableFields() which actually constructs the searchable fields and logic.

PHP would be likely to throw an error if you go doing fancy form stuff within the array itself, so farm that form field off to a separate method in the same DataObject and simply call upon it.

See my example, I hope it helps.

/* 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);
}
0
votes

Yes, it's possible. You just need to override two methods - one in Trainer data object and one in TrainerModelAdmin. First one will make a field, second one will do filtering.

Trainer Data Object:

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;
}

Trainer Model Admin

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;
}