As a follow-up to #1216758: Add $module and $hook as formal parameters in module_invoke(), I noticed that when removing arguments after a call to $args = func_get_args(), sometimes it used unset($args[0]);, other times array_shift($args);. Also, a couple places didn't have a comment.

Comments

tim.plunkett’s picture

Status: Active » Needs review
StatusFileSize
new1.81 KB
tim.plunkett’s picture

StatusFileSize
new1.83 KB

Since the indices are not important, these should be removed with unset(), not array_shift(). Thanks to chx for pointing out how much faster unset is.

droplet’s picture

array_shift is bad in performance

sun’s picture

Title: Unify removal of arguments after func_get_args() » Use unset() instead of array_shift() to remove arguments from func_get_args()
Issue tags: +Needs backport to D7

Excellent, thanks!

sun’s picture

Status: Needs review » Reviewed & tested by the community

d'oh, sorry.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, drupal-1217840-2.patch, failed testing.

tim.plunkett’s picture

Status: Needs work » Needs review
StatusFileSize
new1.5 KB

This gets smaller and less exciting each time. But I learned plenty about when Drupal cares about indices, and cool things about call_user_func_array...

sun’s picture

Can you enlighten us, too, please? :) Why did #2 fail?

droplet’s picture

@sun,

the failed tests are hardcode the args key. eg.

    ->condition('uid', $form_state['build_info']['args'][0]->uid)
    ->condition('aid', $form_state['build_info']['args'][1])

array_shift reorder the index key from ZERO and unset just remove an element from array only.

sun’s picture

Status: Needs review » Reviewed & tested by the community
sun’s picture

Issue tags: -Needs backport to D7

#7: drupal-1217840-7.patch queued for re-testing.

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs backport to D7

The last submitted patch, drupal-1217840-7.patch, failed testing.

tim.plunkett’s picture

Status: Needs work » Needs review
StatusFileSize
new3.33 KB

I see no reason to babysit that code.

tim.plunkett’s picture

StatusFileSize
new2.43 KB
new5.61 KB

This is the last of it.

sun’s picture

Status: Needs review » Needs work

I'm OK with the changes in this patch that only effect subsequent code, which is doing stuff like implode().

In other words, I'd like to see the changes to form.inc reverted. (but fine with adding a comment as in #7)

tim.plunkett’s picture

Status: Needs work » Needs review

I'd agree for the D7 backport. But this is D8, there is no reason for an implementation of hook_form_alter() to blindly trust the array keys in $form_state['build_info']['args'], and we can document that and fix it.

sun’s picture

There's lots of code that's doing that outside of core, and that's why I disagree with it. It's a perfectly fine way for accessing the arguments, and I do not see why we want to break such code. Contrary to that, the change to unset() is a pure micro-optimization only.

tim.plunkett’s picture

StatusFileSize
new1.75 KB
new4.84 KB

Here's another approach then.

sun, if you really disagree with this one too, can we chat about it in IRC sometime?

Status: Needs review » Needs work
Issue tags: -Needs backport to D7

The last submitted patch, drupal-1217840-18.patch, failed testing.

tim.plunkett’s picture

Status: Needs work » Needs review
Issue tags: +Needs backport to D7

#18: drupal-1217840-18.patch queued for re-testing.

tim.plunkett’s picture

The difference between #14 and #18 is that first index of $form_state['build_info']['args'] will be 2 or 0, respectively.

I'd just as soon go with #18 since its not an API change.

sun’s picture

I've to admit that there's no difference between unset() + array_values(), but at the same time, array_shift() is just one amount of confusion.

Also, did we check the behavior of PHP references with array_values()?

tim.plunkett’s picture

StatusFileSize
new5.75 KB

Rerolled. And yes, I tested array_values(), it doesn't affect PHP references

tim.plunkett’s picture

StatusFileSize
new6.03 KB

Rerolled.

tim.plunkett’s picture

Issue summary: View changes
StatusFileSize
new2.51 KB
andypost’s picture

Status: Needs review » Reviewed & tested by the community

Interesting how this impacts on performance ;)

catch’s picture

Version: 8.x-dev » 7.x-dev
Status: Reviewed & tested by the community » Patch (to be ported)

Committed/pushed to 8.x, thanks!

Moving 7.x for backport.

dcam’s picture

Status: Patch (to be ported) » Needs review
StatusFileSize
new1007 bytes

Backported #25 to D7.

There were only a couple of things to backport. module_invoke_all() in D7 already uses unset() and the changes to Views aren't relevant.

yesct’s picture

+++ b/includes/bootstrap.inc
@@ -3425,7 +3425,8 @@ function &drupal_register_shutdown_function($callback = NULL) {
-    array_shift($args);
+    // Remove $callback from the arguments.
+    unset($args[0]);

+++ b/includes/form.inc
@@ -124,8 +124,8 @@ function drupal_get_form($form_id) {
-  array_shift($args);
-  $form_state['build_info']['args'] = $args;
+  unset($args[0]);
+  $form_state['build_info']['args'] = array_values($args);

why do we have to do array_values in the second case, and not in the first?

I went back and re-read some comments... maybe because

array_shift reorder the index key from ZERO and unset just remove an element from array only.

Does array_values reorder from zero then?

http://us2.php.net/manual/en/function.array-values.php
"array_values() returns all the values from the array and indexes the array numerically."

tim said in #16

there is no reason for an implementation of hook_form_alter() to blindly trust the array keys in $form_state['build_info']['args'], and we can document that and fix it.

and then added some array_values() in #18.

I would have thought we would have had to do unset and then array values all the time? ...
and why not do it right after the unset? like:
+ unset($args[0]);
+ // Put reason here...
+ $args=array_values($args);
$form_state['build_info']['args'] = $args;

OTOH, this is a backport... so maybe we should just do it the same as was done for drupal 8. (but I am curious)

mgifford’s picture

EDIT: Sorry, pasted in the wrong text.

Just looks like most of @YesCT's comments have to do with D8. Do we want to re-open this or just accept the decisions made in D8. If we want to accept them, we should be able to just back-port them to D7, right?

  • catch committed e3dfcf9 on 8.3.x
    Issue #1217840 by tim.plunkett: Use unset() instead of array_shift() to...

  • catch committed e3dfcf9 on 8.3.x
    Issue #1217840 by tim.plunkett: Use unset() instead of array_shift() to...

  • catch committed e3dfcf9 on 8.4.x
    Issue #1217840 by tim.plunkett: Use unset() instead of array_shift() to...

  • catch committed e3dfcf9 on 8.4.x
    Issue #1217840 by tim.plunkett: Use unset() instead of array_shift() to...

Status: Needs review » Closed (outdated)

Automatically closed because Drupal 7 security and bugfix support has ended as of 5 January 2025. If the issue verifiably applies to later versions, please reopen with details and update the version.