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