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.
API page: https://api.drupal.org/api/drupal/core!modules!views!src!ViewsData.php/f...
Enter a descriptive title (above) relating to protected function ViewsData::getData, then describe the problem you have found:
Ummm... So I'm looking at the function bodies for ViewsData::get() and getData().
When they're storing data in the cache they do this:
$this->cacheSet($this->baseCid, $data);
return $data;
When they're getting data from the cache, they do this:
if ($data = $this->cacheGet($this->baseCid)) {
return $data->data;
}
This looks wrong to me. Shouldn't it just be return $data
? What is this ->data in the return?
Comment | File | Size | Author |
---|---|---|---|
#15 | drupal.cache-backend-get-2225087-15-do-not-test.patch | 8.73 KB | ehegedus |
#11 | drupal.cache-backend-get-2225087-11-do-not-test.patch | 4.94 KB | ehegedus |
#4 | drupal.cache-backend-get-2225087-0-do-not-test.patch | 1.75 KB | ehegedus |
Comments
Comment #1
larowlanYeah cache get returns a db row. There's an issue floating about to make it a real object.
Comment #2
jhodgdonWow. The cache docs are terrible... the ->get() method doesn't even tell me this, and the D8 section on drupal.org is really lame:
https://drupal.org/node/1884796
Also see
https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Cache!CacheBacken...
which really really really needs to say that to get the data you put into the cache back out, you need to get ->data().
I think this is a major oversight in the documentation that really needs to be fixed. Should be a good Novice issue.
What needs to be done:
In the @return section of CacheBackendInterface::get(), document that what is returned is a stdObject database row object, and that your data is in the ->data property of it.
Comment #3
ehegedus CreditAttribution: ehegedus commentedComment #4
ehegedus CreditAttribution: ehegedus commentedI think the "cache item" naming is more appropriate, as the implementing classes alter (prepare) the returned row, so it won't be a simple database row object most of the time.
\Drupal\Core\Cache\MemoryBackend::prepareItem()
\Drupal\Core\Cache\DatabaseBackend::prepareItem()
Comment #5
jhodgdonThis still doesn't tell me that to get back out the data that I placed in the cache, if I save the return value of ->get() in $cache_data, I have to do $cache_data->data. Hopefully that is true for all of the different cache backend classes, because I assume/hope that the user of the cache would not need to know the details of which back end is being used, in order to use the cache (which would completely nullify the idea of having a unified cache interface).
Also, shouldn't all of those other classes' ->get() methods just be using @inheritdoc instead of reproducing the entire ->get() docs?
Comment #6
jhodgdonSo I looked into this in more depth.
DatabaseBackEnd returns an object with the following properties:
- data - the cached data
- cid, created, expire, serialized, checksum_invalidations, checksum_deletions [database fields]
- tags [array of the tags]
MemoryBackend (and derived classes like MemoryCountBackend) returns an object with the following properties:
cid, data, created, expire, tags
NullBackend always returns FALSE (the others return FALSE if the cache is expired, nonexistent, etc.).
So, I think we should document the return value of the get() methods as either being:
- FALSE if there is no valid cached data
- An object with properties: cid, data, created, expire, tags [put these in a list and document what each one is].
And I also think all of the individual ->get() methods should use @inheritdoc to inherit the interface docs unless they have something specifically different to say. And I don't think they do. In fact, a few of them just say "Overrides ..." instead of even using @inheritdoc.
For details of how to do @inheritdoc, see:
https://drupal.org/node/1354#inheritdoc
Comment #7
ehegedus CreditAttribution: ehegedus commentedI searched, but couldn't find the a reference to the idea I read about the useage of dummy like class/interface for some particular return types. By dummy I mean we would not use (e.g. implement, extend) them in "real" cases and the only purpose they have is to store the documentation (instead of in the function/method directly). Do you have any existing procedure for this, or you think it may be an overhead?
Comment #8
jhodgdonI am not sure exactly what you mean in #7.... An interface should fully document the methods on the interface, including what their parameters and return values are. This is not a "dummy", but rather a "contract" that classes agree to follow when they implement the interface. A class that implements the interface can then use @inheritdoc instead of re-documenting the method. See https://drupal.org/node/1354#inheritdoc for details on how to use inheritdoc. Does that answer your question?
(As a side note, please do not change the status of an issue to "needs review" unless you have a new patch that needs reviewing. There's a link explaining what the priority/status values mean, under the priority/status fields. Thanks!)
Comment #9
ehegedus CreditAttribution: ehegedus commentedThe @inheritdoc part is clear.
Okay, so I meant something like defining a new dummy class, which we are not inteded to instantiate (abstract then?). In our case it would have only some properties (the database fields) with documentation, then the CacheBackendInterface::get() would return this data type instead of specifying any additional detail.
Then the ->get() method would contain only
My question is where should this class definition reside?
It worths the effort? Like it's a benefit to extend it in another dummy class and add there additional property documentation (e.g. additional properties added within a prepareItem() method) then return it instead of the parent data type?
I meant this whole thing as a generic question as this solution may apply in other parts also and I'm just wondering if it would clarify the return data type structure or not?
P.S.
Ideas and patches couldn't be mixed in the issue? :-\
Comment #10
jhodgdonNo. I don't think so.... not here, anyway. This "Major" issue is about the documentation missing crucial information about what the code is actually currently doing. If you would like to propose different ideas about how the Cache API should work, please open a new issue (not in the Documentation component) to discuss (and in that case, you can set the status to "needs review" to discuss ideas -- but on this issue, which already had a patch that was marked "needs work", please do not use "needs review" unless you are adding a new patch. People subscribed to the issue will notice already if you ask a question.)
So. On this issue, all we want to do is document the return value of the get() methods as either being:
- FALSE if there is no valid cached data
- An object with properties: cid, data, created, expire, tags [put these in a list and document what each one is].
This should be done on the interface, because all implementations of this interface need to have the same return value structure. And all methods that override ->get() on other classes should also be changed to use @inheritdoc.
Thanks!
Comment #11
ehegedus CreditAttribution: ehegedus commentedThank you for the guidance!
Comment #12
eojthebravePath applies cleanly for me. And the content looks correct and reads easily. Thanks!
Super nit-picky, but I think we shouldn't break the last 2 lines like you've done here. But instead, continue the 2nd to last line with ". For example ..." and break on "array ...". As is the formatting just seems off. Thoughts?
Comment #13
ehegedus CreditAttribution: ehegedus commentedOr maybe...?
Comment #14
jhodgdonYes to #13. Actually, given the context, I'd suggest this:
Other nitpicks:
a)
Otherwise should not be capitalized.
b)
The (sigh) correct punctuation for "i.e." would be: "... time; i.e., it will...". Or better yet, use the words "that is", because 90% of people don't understand the distinction between i.e. and e.g. and will be confused by this anyway. (The words "that is" need to be punctuated the same way.)
c)
Comma after "For example".
d) Shouldn't DatabaseBackend::get() and MemoryBackend::get() also just use @inheritdoc? Otherwise we need the full docs about the return value in those methods, or a link to the interface method for full docs.
Comment #15
ehegedus CreditAttribution: ehegedus commentedIn fact, I copied most of the docs from other methods, so the provided info stays consistent.
Corrected the set method's documentation too and added the @inheritdoc tags. I bet at d) you meant getMultiple(), but the same is true for other methods also (e.g., delete(), deleteMultiple()), which also need update, but in another issue?
Comment #16
jhodgdonOK, let's see if we can sort this out... And please in the future do not put the "do not test" suffix on patches. At a minimum, it sorts out whether the patch applies, and also makes sure there were no inadvertent PHP syntax problems.
So, back to basics.
a) We have CacheBackendInterface, and these extending classes:
BackendChain
DatabaseBackend
MemoryBackend
MemoryCounterBackend
NullBackend
b) The interface has two methods, get() and getMultiple(), which both refer to "cache item objects", and both of them need to either define what that means, or refer to the other method where it's defined, in their @return section. That's the main subject of this issue, although it originally only applied to get() -- I think we should fix getMultiple() too now that you point it out.
c) This patch adds documentation to get(). I suggest rather than repeating the docs in getMultiple(), we should instead make the @return for getMultiple say something like "An array of cache item objects indexed by cache ID; see CacheBackendInterface::get() for documentation of these objects."
d) I am also thinking that in the tags section of the get() return value documentation, instead of fully explaining tags, we should just say "The tags array that was passed into CacheBackendInterface::set()", since that method already documents what the tags are. And I think the change in this patch to the $tags param in set() is good too, plus the other cleanups to the interface docs.
e) So now on to the classes. I think that it is fine if this patch expands in scope slightly to replace existing docs in class methods with @inheritdoc, for these methods, on all of the classes:
get, getMultiple, set, delete, deleteMultiple, deleteTags, deleteAll, invalidate, invalidateMultiple, invalidateTags, invalidateAll, garbageCollection, isEmpty
Thanks!
Comment #17
ehegedus CreditAttribution: ehegedus commentedI was really busy in the past week. I try to do a re-roll today/tomorrow.
Comment #18
larowlanNote #1748022: Make cache()->get() return a classed CacheItem object
Comment #19
jhodgdonRE #18, do you think we should postpone this issue on that one? Is it likely to get done?
Comment #20
subhojit777Comment #21
cilefen CreditAttribution: cilefen commentedRemoving the "Novice" tag because the direction is unclear at the moment.
Comment #22
ehegedus CreditAttribution: ehegedus commentedSaying hi from DrupalCon Barcelona, also leaving this task unassigned as the doc issues are not for me.
Comment #31
catchPostponing on #1748022: Make cache()->get() return a classed CacheItem object, if we can make the return a value object, we have a better spot to document everything.
The patch as it currently stands documents all the properties of the cache object as returned from the database cache, but nothing enforces this. $cached->data has to be there since everything accesses that and you'll get fatal errors if it's not. But the rest aren't guaranteed to be there at all, so it could be more misleading than the current minimal docs.