Jump to content

$input and associative array issue


celfred
 Share

Recommended Posts

Hello all,

I'm back on my PW site and I'm facing an issue for a couple of hours now and it's driving me crazy... I'm sure it's not that much for a bunch of you, but it looks hopeless to me so here's my problem :

I'm sending a form to a page and I have many checkboxes sent, so I used an array. My code looks like this :

    <table class="adminTable">
      <tr>
        <td></td>
        <th ng-repeat="task in tasks" title="{{task.summary}}"><div class="vertical-text"><div class="vertical-text__inner">{{task.title}}</div></div></th>
      </tr>
      <tr>
        <td></td>
        <td ng-repeat="task in tasks" title="Tout cocher"><input type="checkbox" /></td>
      </tr>
      <tr ng-repeat="player in players">
        <th>{{player.title}}</th>
        <td ng-repeat="task in tasks" title="{{player.name}} - {{task.title}}">
          <!-- <input type="hidden" name="player[{{$parent.$index}}]" value="{{player.id}}" /> -->
          <input type="checkbox" name="player[{{player.id}}][]" value="{{task.id}}" />
        </td>
      </tr>
    </table>

The important line (to me) is the <input type="checkbox" name="player[{{player.id}}][]" value="{{task.id}}" /> in which I'm trying to pass both the id of the player and the task id to record for the player. All this is embedded into an ng-repeat loop since I'm using AngularJs... Anyway, the variables look ok when I'm looking at the generated source and in fact it look fine if I print_r($GLOBALS) when I recieve the POST variables.

Here's the print_r($GLOBALS) result :

   [_POST] => Array
        (
            [adminTableSubmit] => Enregistrer
            [player] => Array
                (
                    [5157] => Array
                        (
                            [0] => 1580
                            [1] => 1578
                        )

                    [5171] => Array
                        (
                            [0] => 1580
                            [1] => 1578
                        )

                )

        )

(2 players and 2 tasks for each)

BUT : if I write

$checked_players = $input->post->player;

I get an empty array! Indeed, trying to debug my thing (I guess I can call it a 'thing' at this time), I type :

      foreach($input->post as $key => $value)
        echo htmlentities("$key = $value") . "<br />"; 
      $checked_players = $input->post->player;
      print_r($checked_players);

and here's what I get :

adminTableSubmit = Enregistrer
player = Array
Array ( ) 

Whereas I keep thinking my print_r($checked_players) should return :

[5157] => Array
  (
   [0] => 1580
   [1] => 1578
  )

[5171] => Array
  (
   [0] => 1580
   [1] => 1578
  )

so that I could then work with that and save data as pages...

So please, what I am doing wrong? I'm sure I'm messing things up. I've tried so many possibilities and nothing has worked so far. Hence my message to the community. I really don't get it since it seems like such a basic problem... but the facts are there : I'm stuck :(

Hope to hear from one of you soon. Thanks in advance for your help :)

PS : Sorry for my long post, but I'm trying to be as clear s possible.

Link to comment
Share on other sites

Hello!

There is a very simple answer for this:

https://github.com/ryancramerdesign/ProcessWire/blob/dev/wire/core/WireInput.php#L60

This is ProcessWire's doing and it is meant to work like that.

For now, I'd just suggest that you fetch them directly from the $_POST-variable ($_POST['players']). Obviously you need to validate/sanitize it yourself, but that's the way to go if you don't want to change your form.

If you want to play by ProcessWire's "rules", then you will modify your checkboxes so that their name is "player_{{player.id}}[]" and parse them into a multi-dimensional array yourself. This could be done with a simple function like this:

/**
 * Parses a multi-dimensional array
 *
 * This function will use $prefix to match the keys in the source $values.
 * For matching keys the suffix is then extracted and used as a key for the resulting array.
 *
 * @param array|Traversable $values The source values
 * @param string $prefix The prefix used for extraction
 * @return array The parsed multi-dimensional array
 */ 
function getMultiDimensional($values, $prefix)
{
  // Validate the arguments
  if(!is_array($values) and !($values instanceof Traversable))
    throw new Exception("Invalid values");
  $len = strlen($prefix);
  if(!$len)
    throw new Exception("Invalid prefix");
 
  $output = Array();

  foreach($values as $key=>$value)
  {
    // The key needs to match our prefix
    if(strcmp(substr($key,0,$len), $prefix) != 0)
      continue;

    // We expect the other part of the key to hold numeric IDs
    $id = intval(substr($key,$len));
    if(!$id)
      continue;

    $output[$id] = $value;
  }
  return $output;
}

// Demonstration
$players = getMultiDimensional(wire('input')->post, "player_");

// print_r($players);
//
//  [5157] => Array
//    (
//      [0] => 1580
//      [1] => 1578
//    )
//  ...and so on

Edit: Added an example and some comments

Needless to say, I suggest the latter solution :)

Edited by sforsman
  • Like 10
Link to comment
Share on other sites

Wow....

I've just tested what you said and .... THANKS a lot. This works fine and I guess I could have struggled many more days without finding it myself... I've used the second solution ;). And now I can go on with my little project, cool!

Thanks again for your great explanations and answer.

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...