Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Is the hook_taxonomy_term_load missing a return statement or is the $terms parameter supposed to be a reference? Without anyone of these the hook is not doing anything...
Comment | File | Size | Author |
---|---|---|---|
#22 | 471744.patch | 3.29 KB | jhodgdon |
#21 | 471744.patch | 3.1 KB | jhodgdon |
#12 | 471744b.patch | 2.81 KB | jhodgdon |
#2 | 471744.patch | 1.29 KB | jhodgdon |
Comments
Comment #2
jhodgdonIt looks like it should be a pass-by-reference. See http://api.drupal.org/api/function/taxonomy_term_load_multiple/7 for the calling function, and http://api.drupal.org/api/function/taxonomy_test_taxonomy_term_load/7 for a sample implementation (it looks to me as though that hook is not implemented anywhere in core).
The same problem exists in hook_taxonomy_vocabulary_load() in the same file. There are no implementations of this at all on api.drupal.org, but the way it is called suggests it should be passed by reference too -- see http://api.drupal.org/api/function/taxonomy_vocabulary_load_multiple/7
The attached patch fixes both of them (I think).
Comment #3
BerdirAs I already said in the other issue, this is not necessary, atleast not for this example.
The thing is that the objects inside the array are always passed by reference because they are objects. This means that the example works.
Another example of that is http://api.drupal.org/api/function/field_sql_storage_field_storage_load/7 ($objects is an array of objects). Actually, I had to remove the & there, because it generated a warning with PHP 5.3. This would not happen here though, because it is not invoked with call_user_func_array().
What you can't do is adding vocabularies to the array or remove some of them. Not sure if this is intended or not. And you can still add a & if you need to do that for whatever reason.
Comment #4
jhodgdonBerder: You said "As I already said in the other issue, this is not necessary, atleast not for this example." -- Which other issue?
Anyway, that aside... My PHP in a Nutshell book says (p. 58): "As of PHP 5, objects are passed and assigned by reference by default... This was different before PHP 5 -- obects were treated like other types of variables and copied entirely when assigned." So what you are saying about objects is correct for Drupal 7 (which requires PHP 5) but not for Drupal 6 and before. I guess this issue is Drupal 7 only, though, since there doesn't appear to be any equivalent to hook_taxonomy_term_load in Drupal 6 (there is hook_taxonomy, but it does not appear to have a 'load' operation).
In this case, however, it is an array and not an object that is being passed into the hook, I think? It is coming from
$queried_terms = $query->execute()->fetchAllAssoc('tid');
in http://api.drupal.org/api/function/taxonomy_term_load_multiple/7 and it looks like fetchAllAssoc() is making an associative array.
Assuming I've got that right, the question becomes whether your statement is true for arrays (that they are passed by reference by default). I don't think they are.... I couldn't find doc saying this was the case as I found for Objects (via web search or in my Nutshell book), so I wrote a quick and dirty little test script. I tried it with numeric and associative arrays -- same result: they are not passed by reference by default in PHP 5.
Here's the script, for reference:
Here is the output:
So it looks like arrays are not passed by reference. This was tested using PHP 5.
Comment #5
jhodgdonHmmm... I guess you are also saying that the objects within the array are passed by reference, so that they can be altered directly...
Comment #6
jhodgdonWell, I don't know what the right answer is. If we should omit the &, then it should also be omitted from the sample module http://api.drupal.org/api/function/taxonomy_test_taxonomy_term_load/7 -- and you are probably right that that particular function does not alter the array itself, and that the object references in the array would/should be successfully modified (in PHP 5) without the & in the function declaration.
Comment #7
jhodgdonI sit corrected: Passing an array of objects in PHP5, you are correct to point out that the objects will be modified directly:
Output:
So I think we should instead patch the sample implementation to remove the & and maybe make a note in the hook doc that you don't need to pass by reference unless you wanted to add/remove terms from the array. Thoughts?
Comment #8
BerdirSounds good. the "other issue" is #471746: hook_taxonomy_vocabulary_load missing return or reference?.
I'd also like to get catch's opinion on this...
Comment #9
catchThe hook documentation shouldn't have the & in it at all I think. I'm not sure about letting people alter the array here - would rather leave it undocumented and let people do evil things with the references if they really, really want to.
Comment #10
jhodgdonOK. We should therefore remove the & from http://api.drupal.org/api/function/taxonomy_test_taxonomy_term_load/7
I also think the example in the hook doc is written badly -- it looks like it could be adding things to the array. And we can document the passing by reference thing so that this question doesn't come up.
I'll make a patch.
Comment #11
catchI don't think we should document the passing by reference thing here - there are a lot of hook in D7 which pass an array of objects without an explicit by ref and we'd need to do that one by one. Maybe add it to coding standards or upgrade guide?
hook documention should just act on the object rather than worrying about the array key though yeah.
Comment #12
jhodgdonI think this patch improves the doc for both of those taxonomy load hooks (the doc for the vocabulary hook was incorrect, as it didn't even mention it was receiving an array). And I've removed the & from the test module implementation of the term load hook.
Thoughts?
Comment #14
jhodgdonSetting back to Needs Review in hopes that the patch will get retested. The test bot was apparently malfunctioning (I had about 7 patches fail in that time period, all were doc, none broke the HEAD install I am pretty sure).
Comment #15
Anonymous (not verified) CreditAttribution: Anonymous commentedThe changes are helpful and accurate.
Comment #16
webchickHm. I'm not sure about the documentation hunks. There are many, many, many more functions we'll need to add exactly the same string about objects in PHP5. Would it make more sense to document this somewhere more central?
Comment #17
Anonymous (not verified) CreditAttribution: Anonymous commentedCatch raised the same concern. I kinda agree, but I honestly didn't think about the ramifications for many other hook phpdoc. Jhodgdon said that if she doesn't get it, it needs to be documented in the phpdoc. (Forgive me if I'm misrepresenting you jhodgdon.)
To be consistent, we'd need to change all kinds of phpdoc throughout core.
On the other hand, documenting it centrally could be an opportunity to convey principles that help devs and users predict when they're going to have to think about this. Drupal doesn't pass around very many PHP objects, so where does this matter? Which objects does it matter for? (terms, users, nodes) Is there a potential "aha!" that we're dancing around by spreading the info throughout the API phpdocs? (Terms, users and nodes? Why those are among my favorite Drupal things! And they all get this special treatment!)
Comment #18
catchShould we put it in coding standards maybe? And/or should there be a PHP 5.2 (and probably PHP 5.3 support) section in the upgrade docs?
I didn't know about this behaviour until someone told me, while I was writing the patch which introduced this hook ;) but once you realise it then it's easy to remember.
Comment #19
jhodgdonThe confusing thing about this particular hook is that it passes an array of objects. The array itself is NOT passed by ref in PHP 5, but the objects in the array are, and neither is in PHP 4 (i.e. Drupal 6 and eariler). So if you wanted to add items to the array (does that apply here? not sure), you'd need to make the hook implementation use a by-ref parameter, while if all you needed to do was to modify objects in the array, you'd be OK without using a by-ref parameter. In PHP 5 anyway.
I also think that this is a bit of an unusual case. Much of the other stuff in Drupal is either just single objects (like $node) being passed around, or arrays of arrays. And most of the Drupal functions return their values instead of passing by reference.
Anyway... all of that said, if you want that note taken out, I can take it out. And we can put something in the coding standards about this... how's this:
---
Heading: Function arguments passed by reference
For PHP functions that needs to return more than one value, a common practice is to make the other return values be function arguments passed by reference. For example:
Because PHP 5 passes all objects by reference, you should omit the & from passed-by-reference arguments in functions (including hook implementations) in Drupal 7 and later versions, in the following cases:
* If the argument is a PHP object.
* If the argument is an array of objects, and your function will be modifying objects within the array (not adding or removing elements from the array itself).
Comment #21
jhodgdonHere is a patch that fixes up doc for the taxonomy term/vocabulary hooks, and removes the & in the one implementation, as discussed above. And it doesn't say anything about passing by reference.
I also added a new section to the module upgrade guide about PHP 5 and object passing. Review/comments requested...
http://drupal.org/update/modules/6/7#php_version
Comment #22
jhodgdonThis patch fixes one more spot that was wrong in the file.
Comment #24
catchThis is a straight bug report now, patch looks great.
Comment #25
Dries CreditAttribution: Dries commentedCommitted to CVS HEAD.
Comment #27
mathieso CreditAttribution: mathieso commentedAs noted above, if you want to remove specific terms, you can't just unset them in $terms in the hook, because it's not pass by ref.
But you can (1) change the term object in the hook, and (2) check for that change in a theme. E.g.,
Hook:
Theme:
I haven't bothered making odd/even work, since I don't use it. But it wouldn't be hard.