|
| 1 | +@title Handles Technical Documentation |
| 2 | +@group handles |
| 3 | + |
| 4 | +Technical overview of Handles. |
| 5 | + |
| 6 | +Overview |
| 7 | +======== |
| 8 | + |
| 9 | +Most objects in Phabricator have PHIDs, which are globally unique identifiers |
| 10 | +that look like `PHID-USER-2zw4hwdt4i5b5ypikv6x`. If you know the PHID for an |
| 11 | +object, you can load a **handle** for that object to get more information |
| 12 | +about it. |
| 13 | + |
| 14 | +Handles are lightweight reference objects which provide some basic information |
| 15 | +common across all objects (like their type, icons, names, monograms, URIs, and |
| 16 | +whether they are open or closed). Applications don't need to know anything about |
| 17 | +other types of objects in order to load and use handles. There are uniform |
| 18 | +mechanisms available to load and work with handles which work across all types |
| 19 | +of objects in every application. |
| 20 | + |
| 21 | + |
| 22 | +Loading Handles |
| 23 | +=============== |
| 24 | + |
| 25 | +To load handles, you'll usually call `loadHandles(...)` on the viewer: |
| 26 | + |
| 27 | + $handles = $viewer->loadHandles($phids); |
| 28 | + |
| 29 | +This returns a @{class:PhabricatorHandleList}. This object behaves like an |
| 30 | +array, and you can access handle objects by using their PHIDs as indexes: |
| 31 | + |
| 32 | + $handle = $handles[$phid]; |
| 33 | + |
| 34 | +Handles will always load, even if the PHID is invalid or the object it |
| 35 | +identifies is restricted or broken. In these cases, the handle will accurately |
| 36 | +represent the state of the associated object. This means that you generally do |
| 37 | +not need to check if a handle loaded. |
| 38 | + |
| 39 | + |
| 40 | +Rendering Handles |
| 41 | +================= |
| 42 | + |
| 43 | +After loading handles, you'll usually call `renderHandle($phid)` to render a |
| 44 | +link to an object: |
| 45 | + |
| 46 | + $view = $handles->renderHandle($phid); |
| 47 | + |
| 48 | +This returns a @{class:PHUIHandleView}. The class exposes some methods which |
| 49 | +can adjust how the handle renders. |
| 50 | + |
| 51 | +If you want to render a list of handles, you can use `renderList()`: |
| 52 | + |
| 53 | + $list_view = $handles->renderList(); |
| 54 | + |
| 55 | +This returns a @{class:PHUIHandleListView}. This class also exposes some |
| 56 | +methods to adjust how the list renders. |
| 57 | + |
| 58 | +Convenience methods for these operations are also available on the viewer |
| 59 | +object itself: |
| 60 | + |
| 61 | + $view = $viewer->renderHandle($phid); |
| 62 | + $list_view = $viewer->renderHandleList($phids); |
| 63 | + |
| 64 | +When you only need to render a handle once, these methods make it easier. |
| 65 | + |
| 66 | + |
| 67 | +Fetch Semantics |
| 68 | +=============== |
| 69 | + |
| 70 | +When you load and render handles through the viewer, the actual data fetching |
| 71 | +occurs just-in-time. Specifically, all of the required PHIDs are queued up |
| 72 | +until a concrete representation //needs// to be produced. Handles are then bulk |
| 73 | +loaded. |
| 74 | + |
| 75 | +This means that, unlike most other types of data fetching, it's OK to |
| 76 | +single-fetch handles, because they won't //really// single-fetch. This code is |
| 77 | +correct and desirable: |
| 78 | + |
| 79 | + $list->addProperty(pht('Pilot'), $viewer->renderHandle($pilot_phid)); |
| 80 | + $list->addProperty(pht('Copilot'), $viewer->renderHandle($copilot_phid)); |
| 81 | + |
| 82 | +If you're rendering a very large number of handles (for example, 100+ handles |
| 83 | +in a result list view) it's //slightly// more efficient to render them through |
| 84 | +a @{class:PhabricatorHandleList}: |
| 85 | + |
| 86 | + $handles = $viewer->loadHandles($phids); |
| 87 | + foreach ($items as $item) { |
| 88 | + // ... |
| 89 | + $view = $handles->renderHandle($item->getPHID()); |
| 90 | + // ... |
| 91 | + } |
| 92 | + |
| 93 | +This shaves off a tiny bit of internal bookkeeping overhead. This does not |
| 94 | +change the underlying semantics of the data fetch. |
| 95 | + |
| 96 | +Handles are particularly well suited to use this just-in-time fetch pattern |
| 97 | +because they're ubiquitous and code essentially never makes decisions based on |
| 98 | +handles, so it's very rare that they need to be made concrete until final page |
| 99 | +rendering. Most other kinds of data do not have the same sort of |
| 100 | +application-level semantics. This generally makes other objects much less |
| 101 | +suitable to be fetched just-in-time. |
0 commit comments