0

I'm currently cleaning up a bit of nasty code. This code defines to an existing array several new keys in quite the depth:

$form['long_key_name_right_here_you_see']['title'] = 'Hello';
$form['long_key_name_right_here_you_see']['body'] = 'This be a greeting';
$form['long_key_name_right_here_you_see']['etc'] = 'This does nothing';
$form['another_long_key_name_right']['title'] = 'Hello!';
$form['another_long_key_name_right']['body'] = 'This be a greeting!';
$form['another_long_key_name_right']['etc'] = 'This does nothing.';

I would prefer to define this as such:

$arr_form = array('long_key_name_right_here_you_see' => array('title' => 'Hello',
                                                              'body'  => 'This be a greeting',
                                                              'etc'   => 'This does nothing'
),
                  'another_long_key_name_right'      => array('title' => 'Hello!',
                                                              'body'  => 'This be a greeting!',
                                                              'etc'   => 'This does nothing.'));

$form = ($arr_form + $form);
  • Can I always count on my prefered approach to do the same result as existing case?
  • Would my prefered approach be considered unclear and pointless?

Essentially, I just feel that huge walls of identical keys defined in rows looks a bit ugly in the code, but maybe that's just my mind that's picky.

Relevant PHP Documentaion

The + operator returns the right-hand array appended to the left-hand array; for keys that exist in both arrays, the elements from the left-hand array will be used, and the matching elements from the right-hand array will be ignored.

Note:

The accepted answer helped me in my case. This question doesn't necessarily have one true answer but might inspire others and as it did me .

Robin Castlin
  • 10,808
  • 1
  • 23
  • 41
  • Apart from the fact that the syntax is off (you want `$form += $defaultValues`) this is the way to go. – Jon Jun 13 '13 at 10:17
  • Are you sure that's the correct approach? The array has existing values and keys needs to be overrided. Please check the documentation I linked in the question and share your thoughts. – Robin Castlin Jun 13 '13 at 10:20
  • 1
    Ah yes, I missed that. In that case your syntax is correct. I would prefer to use `$form = array_merge($form, $defaultValues)` instead to make it very clear to the reader that you are *supposed* to override values (that's the difference between `+` and `array_merge`), but the end result is the same. – Jon Jun 13 '13 at 10:25
  • Enforcing what Jon says. Try `$form = array_merge($form, $arr_form);`, it is ok, and more stable than union operator. – Peter Krauss Jun 13 '13 at 11:51

3 Answers3

2

Since we're working with a single array cell, I'd probably use a short pointer to the long key to improve readability. Personally, I dislike overusing the array() function call as it's a bit harder to read.

A pointer will not take extra memory space as a temporary variable would.

So this:

$form['long_key_name_right_here_you_see']['title'] = 'Hello';
$form['long_key_name_right_here_you_see']['body'] = 'This be a greeting';
$form['long_key_name_right_here_you_see']['etc'] = 'This does nothing';

Would become this:

$target_form =& $form['long_key_name_right_here_you_see'];

$target_form = array(); // In case it's undefined. Drop this if it's not empty.
$target_form['title'] = 'Hello';
$target_form['body'] = 'This be a greeting';
$target_form['etc'] = 'This does nothing';

unset($target_form); 

Note that the unset statement will unset the pointer reference, not the contents of the array. It's only necessary to avoid overwriting your data if you decide to reuse $target_form later on.

This probably deserves more attention than a mere comment: Be careful around pointers. It is easy to overwrite data and hard to debug unless used carefully.

Maxim Kumpan
  • 2,405
  • 2
  • 17
  • 23
  • Wow this approach looks quite beautiful! Always a pleasure to learn new ways to style the code. I will try it out and accept accordingly. – Robin Castlin Jun 13 '13 at 10:22
  • @RobinCastlin It might look good, but you should always be careful around pointers. Make sure you know what you are doing or debugging accidental overwrites will haunt your nightmares. :) – Maxim Kumpan Jun 13 '13 at 10:25
  • Pointers/references are great for making code simpler and more readable, just ensure that you give them meaningful names and avoid overwriting them (without a good reason). – Fabrício Matté Jun 13 '13 at 10:26
  • Thanks for the warnings :) May help my hair being dispatched by my hairdresser rather than by my own hands. – Robin Castlin Jun 13 '13 at 10:28
1

$arr_form += $form; would not be given you your desired output .. you should reverse the variables instead example:

$form = array();
$arr_form = array(
        'title' => 'Hello',
        'body' => 'This be a greeting',
        'etc' => 'This does nothing'
);
$form['long_key_name_right_here_you_see'] = $arr_form;
var_dump($form);
Baba
  • 89,415
  • 27
  • 158
  • 212
  • If I read the documentation right, `$form += $arr_form` won't override identical keys. – Robin Castlin Jun 13 '13 at 10:06
  • Why would you even bother setting the `$arr_form` variable in the first place? It'll stay in memory even though we don't need it at all. – h2ooooooo Jun 13 '13 at 10:08
  • If you always want to make you `override` with minimal overhead then just assign the key – Baba Jun 13 '13 at 10:08
  • @h2ooooooo they are cases where sub modules have their config which can work independently or grouped with the main configuration and even $form can be a session variable – Baba Jun 13 '13 at 10:09
  • In my case I simply find it more appealing to define the long key name once instead of three times as in the case. I doubt there would be a perfomance loss worth noticing by this practice. The answer has been updated a bit. Your answer works cleanly without doubt in first example though. – Robin Castlin Jun 13 '13 at 10:12
1

Each person has different tastes, and languages ​​(PHP, Python, etc.) generally allow you to do the same thing in various ways, serving all tastes and style codes ...


The with statment idea

The @MaximKumpan's answer is like to use a with..as statement of Python and other languages. Imagine something like this,

   //if not exist, $form['long_key_name_right_here_you_see']=array();    
   with $form['long_key_name_right_here_you_see'] as $f {
     $f['title'] = 'Hello';
     $f['body'] = 'This be a greeting';
     $f['etc'] = 'This does nothing';
   }

NOTE: only imagine (!), the real PHP code is $f =& $form['...'], ending with unset($f), as Max's code.

A general config problem/solution

Your problem reminds me of something we already saw before in various configuration scripts. Here we have a typical example of Mediawiki, offering two styling flavors, for two tastes:

$w = array( 'png', 'jpg', 'jp2', 'webp', '...'); // original

$w[] = 'pdf';  // "add one by one item" taste
$w[] = '...';

$new = array( 'pdf', 'ppt', 'jp2' );
$w   = array_merge( $w, $new );  // "add all itens" taste

And you remember another way

$w = $w + $new;
// CAUTION: array_merge, "+" and "+=" are not exactly the same thing!

But, your problem is not merge commom arrays, it is about "merging associative arrays"... You can do it as well (!), see this other similar question/answer (see also array_merge_recursive function).

For your example, array_merge is also a valid and readable solution (replace $arr_form + $form in yor code):

 $form = array_merge($form, $arr_form); // not the same as (arr_form,$form)!

Mediawiki (above link) is an example of "best practices", and (I also) prefer array_merge function than array union operator ("+").

Community
  • 1
  • 1
Peter Krauss
  • 11,340
  • 17
  • 129
  • 247
  • Thanks for input. Though I think you mean `$w = ($new + $w) // not necessarily equal to $w += $new;` is the way I shown. – Robin Castlin Jun 13 '13 at 11:19
  • It is only a "peripheral comment", thanks, I edited adding "CAUTION"... PHP have different behaviours with each "array merge taste" :-) But your problem is about **associative arrays**, so I also complete with the "associative solution" with `array_merge`. – Peter Krauss Jun 13 '13 at 11:46