1

So we have a variety of search pages each with different search criteria, so I decided to write a component which will get parameters passed to it from the controller, collect the neccesary data and return an array which I could then set to be used within my view file to populate drop down boxes to filter the criteria.

I have managed to get everything write up to where I must use the cakePHP helper to build a dynamical select box. I am convinced that I am doing something wrong and if there is an easier way to do this and still keep it somewhat dynamic please assist where you can:

// COMPONENT METHOD:
 public function filterQueries($parameters) {

    // Get defaults from the user:
    $criteria = $parameters["custom"];
    $defaults = $parameters["defaults"];

    // Validate the defaults the user may want and assign them to the return array:
    if($defaults != "false") {
        foreach($defaults as $key => $value) {
            if(array_key_exists($value, $this->defaults)) {
                $this->returnArray["defaults"][$value] = $this->defaults[$value];
            }
        }
    }

    // Get all data for the custom requested form fields:
    if($criteria != false) {
        foreach($criteria as $model => $arguments) {
            $fields = $arguments["fields"];
            $conditions = $arguments["conditions"];
            $recursive = $arguments["recursive"];
            if(!in_array($model,$this->uses)) {
                $useModel = ClassRegistry::init($model);
            } else {
                $useModel = $this->$$model;
            }
            $array = $useModel->find("all",array("conditions" => $conditions, "fields" => $fields, "recursive" => $recursive));
            $this->returnArray["custom"][$model] = $array;
        }
    }

    return $this->returnArray;
}

The above function will get an array which breaks down either custom searches or defaults (not included above but it all works, it returns the array exactly as I would have expected it.

 // The code within my action to get the content from above:
// Load the Filters component to search data:
        $search = $this->Components->load("Filter");

        // Tell search what you want:
        $searchBoxes = array(
            "defaults" => array("statuses", "survey_type"),
            "custom" => array(
              "User" => array(
                  "fields" => array("User.id","User.first_name", "User.last_name"),
                  "conditions" => array("User.user_group_id" => "4f847c63-1840-446e-88be-3e4d29566cf0"),
                  "recursive" => -1
              )  
            )
        );

       $filterResults = $search->filterQueries($searchBoxes);
       $this->set("filters",$filterResults);

So now I get this multi-associative array within my view file (all still fine), but I want to now build example a drop down list of the users based on the array created above, but the outcome is nothing like what I expected:

echo $this->Form->input('user_id',
                        array(
                            "type" => "select",
                            "options" => $filters["custom"]["User"]
                        )
                     );

The HTML output is broken and displays it like this:

<option value="last_name">Doe</option>
<option value="first_name">Jihn</option>
<optgroup label="User"> </optgroup>
<optgroup label="1"> </optgroup>
<option value="last_name">Marilyn</option>
<option value="first_name">Monroe</option>

I acknowledge that I do not have a lot of cake experience but cannot understand how to just get the results to :

 <option value='USERID'>NAME</option> // Yes I know the names and surnames must be concatinated still

Any advise help or guidance on how to do it, and do it the right way, would greatly be appreciated :)

VARDUMP ON $filters['custom']['users']

  array
   0 => 
     array
       'User' => 
         array
            'id' => string '4f84840e-cda8-4704-8fdf-210729566cf0' (length=36)
            'first_name' => string 'Name' (length=4)
            'last_name' => string 'Surname' (length=11)
    1 => 
      array
        'User' => 
          array
            'id' => string '4f8488cb-53e0-4f72-af73-3de229566cf0' (length=36)
            'first_name' => string 'Name' (length=6)
            'last_name' => string 'Surname' (length=6)
3
  • What does a var_dump($filters["custom"]["User"]) look like? Commented Apr 25, 2012 at 9:21
  • array 0 => array 'User' => array 'id' => string '4f84840e-cda8-4704-8fdf-210729566cf0' (length=36) 'first_name' => string 'NAME' (length=4) 'last_name' => string 'SURNAME' (length=11) 1 => array 'User' => array 'id' => string '4f8488cb-53e0-4f72-af73-3de229566cf0' (length=36) 'first_name' => string 'NAME' (length=6) 'last_name' => string 'SURNAME' (length=6) ..... It returns all the other users as well Commented Apr 25, 2012 at 9:24
  • Oh, can you edit your question it post it there. Hard to read in the comments with no formatting. Commented Apr 25, 2012 at 9:25

5 Answers 5

5

You can enhance your output by doing as follows:

1) for combining two fields of a table, you can use "virtualfields" in the model, as follows: For example if you have the user model, you can define as follows:

 public $virtualFields = array(
  'full_name' => 'CONCAT(first_name, " ",last_name)'
 );

So now the "full_name" field will be got whenever you call the find method of the User model.

2) For getting the data from the table for a select box, you can use the find('list') method. For example for the User model if you need the id,full_name (last and first name combined using the virtual fields) of the table,it can be done as follows :

$this->User->find('list',array('fields'=>array('id','full_name'),'conditions'=>$conditions))

I hope this helps..

Sign up to request clarification or add additional context in comments.

1 Comment

The crux of this is the list parameter for the find method. This helps the form helper figure out what the value should be and what should be displayed.
1

Well I guess what you want to do is actually create another array with formatted options.

foreach ($filters["custom"]["User"] as $arr)
{
    $options[$arr['id']] = $arr['first_name'] . ' ' . $arr['last_name'];
}

then

echo $this->Form->select('user_id', $options);

2 Comments

Hey Jack, I see where you're going with this, and I am happy to do it this way, but would you advise me to do it this way or is there a more efficient way of doing what I am trying to achieve above?
I don't believe there is any other way since you need the options to be formatted in a specific way. The CakePHP form->select uses the array key as the name="value" and the array value as the form text. book.cakephp.org/1.3/view/1430/select but your $results array from the find query returns a multidimensional array of arrays.
0

I think you need something like this:

$result = Set::combine($filters["custom"]["User"], 

                       '{n}.User.id', // this is the value of select box

                         array(
                               '{0} {1}', 
                               '{n}.User.first_name', 
                               '{n}.User.last_name'
                              ) // this is the text of select box
                      );

pr($result);

Comments

0

$this->form->input('inputname', array('label' => false, 'options' => array('Select optionstype','a','b'), 'class'=>array('form-a', 'b'), 'id' => 'bacid', 'style' => 'width:280px;','value'=>$abc['model']['array_attribute']));

Comments

0

On cakePHP 3, I can't use "virtualFields" yet, but I can use as follows:

//In PostsController
$users = $this->Posts->Users->find('list', 
['keyField'   => 'id', 
 'valueField' => 'full_name', //Don't forget to call concatened field here
 'conditions' => $conditions, 
 'order'      => $orderBy 
]);

//here the magic happens
$concat = $users->func()->concat(
['Users.first_name' => 'identifier', 
 ' ', 
 'Users.last_name' => 'identifier'
]);

//selecting fields
$users->select(['id', 'full_name' => $concat]);

//sending to view
$this->set('users', $users->toArray());

I hope this helps CakePHP 3 developers

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.