|
| 1 | +@title Phabricator Code Layout |
| 2 | +@group developer |
| 3 | + |
| 4 | +Guide to Phabricator code layout, including how URI mapping works through |
| 5 | +application class and subdirectory organization best practices. |
| 6 | + |
| 7 | += URI Mapping = |
| 8 | + |
| 9 | +When a user visits a Phabricator URI, the Phabricator infrastructure parses |
| 10 | +that URI with a regular expression to determine what controller class to load. |
| 11 | +For now, that regular expression is hard-coded inside the |
| 12 | +@{class:AphrontDefaultApplicationConfiguration} within the ##getURIMap## |
| 13 | +method. Use the existing entries as examples for adding your own entries. |
| 14 | + |
| 15 | +The Phabricator infrastructure knows where a given controller class lives on |
| 16 | +disk from a cache file the Arcanist phutil mapper generates. This mapping |
| 17 | +should be updated whenever new classes or files are added: |
| 18 | + |
| 19 | + /path/to/arcanist/scripts/phutil_mapper.php /path/to/phabricator/src |
| 20 | + |
| 21 | +Finally, a given controller class will map to an application which will have |
| 22 | +most of its code in standardized subdirectories and classes. |
| 23 | + |
| 24 | += Best Practice Class and Subdirectory Organization = |
| 25 | + |
| 26 | +Suppose you were working on the application ##Derp##. |
| 27 | + |
| 28 | + phabricator/src/applications/derp/ |
| 29 | + |
| 30 | +If ##Derp## were as simple as possible, it would have one subdirectory: |
| 31 | + |
| 32 | + phabricator/src/applications/derp/controller/ |
| 33 | + |
| 34 | +containing the file ##DerpController.php## with the class |
| 35 | + |
| 36 | + - ##DerpController##: minimally implements a ##processRequest()## method |
| 37 | + which returns some @{class:AphrontResponse} object. The class would probably |
| 38 | + extend @{class:PhabricatorController}. |
| 39 | + |
| 40 | +plus an auto-generated ##__init__.php## file. |
| 41 | + |
| 42 | +NOTE: ##__init.php__## files are generated and maintained via `arc lint`. |
| 43 | + |
| 44 | +If ##Derp## were (relatively) complex, one could reasonably expect to see |
| 45 | +the following directory layout: |
| 46 | + |
| 47 | + phabricator/src/applications/derp/constants/ |
| 48 | + phabricator/src/applications/derp/controller/ |
| 49 | + phabricator/src/applications/derp/editor/ |
| 50 | + phabricator/src/applications/derp/exception/ |
| 51 | + phabricator/src/applications/derp/query/ |
| 52 | + phabricator/src/applications/derp/replyhandler/ |
| 53 | + phabricator/src/applications/derp/storage/ |
| 54 | + phabricator/src/applications/derp/view/ |
| 55 | + phabricator/src/applications/conduit/method/derp/ |
| 56 | + |
| 57 | +(The following two folders are also likely to be included for javascript and |
| 58 | +css respectively. However, static resources are largely outside the scope of |
| 59 | +this document. See @{article:Adding New CSS and JS}.) |
| 60 | + |
| 61 | + phabricator/webroot/rsc/js/application/derp/ |
| 62 | + phabricator/webroot/rsc/css/application/derp/ |
| 63 | + |
| 64 | +These directories under ##phabricator/src/applications/derp/## represent |
| 65 | +the basic set of class types from which most Phabrictor applications are |
| 66 | +assembled. Each would contain a class file and an ##__init__.php## file. |
| 67 | +For ##Derp##, these classes could be something like: |
| 68 | + |
| 69 | + - **DerpConstants**: constants used in the ##Derp## application. |
| 70 | + - **DerpController**: business logic providing functionality for a given |
| 71 | + URI. Typically, controllers load data via Storage or Query classes, then |
| 72 | + present the data to the user via one or more View classes. |
| 73 | + - **DerpEditor**: business logic for workflows that change one or more |
| 74 | + Storage objects. Editor classes are only necessary for particularly |
| 75 | + complicated edits and should be used pragmatically verus Storage objects. |
| 76 | + - **DerpException**: exceptions used in the ##Derp## application. |
| 77 | + - **DerpQuery**: query one or more storage objects for pertinent ##Derp## |
| 78 | + application data. @{class:PhabricatorOffsetPagedQuery} is particularly |
| 79 | + handy for pagination and works well with @{class:AphrontPagerView}. |
| 80 | + - **DerpReplyHandler**: business logic from any configured email interactions |
| 81 | + users can have with the ##Derp## application. |
| 82 | + - **DerpStorage**: storage objects for the ##Derp## application. Typically |
| 83 | + there is a base class which extends @{class:PhabricatorLiskDAO} to configure |
| 84 | + application-wide storage settings like the application (thus database) name. |
| 85 | + Reading more about the @{class:LiskDAO} is highly recommended. |
| 86 | + - **DerpView**: view objects for the ##Derp## application. Typically these |
| 87 | + extend @{class:AphrontView}. |
| 88 | + - **ConduitAPI_derp_Method**: provides any and all ##Derp## application |
| 89 | + functionality that is accessible over Conduit. |
| 90 | + |
| 91 | +However, it is likely that ##Derp## is even more complex, and rather than |
| 92 | +containing a class and an ##__init__.php## file, each directory has |
| 93 | +subdirectories of its own. A typical example happens around the CRUD of an |
| 94 | +object: |
| 95 | + |
| 96 | + phbaricator/src/application/derp/controller/base/ |
| 97 | + phabricator/src/application/derp/controller/delete/ |
| 98 | + phabricator/src/application/derp/controller/edit/ |
| 99 | + phabricator/src/application/derp/controller/list/ |
| 100 | + phabricator/src/application/derp/controller/view/ |
| 101 | + |
| 102 | +Which would then each contain a class and an ##__init__.php## file mapping to |
| 103 | +corresponding classes |
| 104 | + |
| 105 | + - **DerpBaseController**: typically extends @{class:PhabricatorController}, |
| 106 | + implements ##buildStandardPageResponse## with the ##Derp## application name |
| 107 | + and other ##Derp##-specific meta-data, and contains any controller-specific |
| 108 | + functionality used throughout the ##Derp## application. |
| 109 | + - **DerpDeleteController**: typically extends ##DerpBaseController## and |
| 110 | + presents a confirmation dialogue to the user about deleting a ##Derp##. |
| 111 | + - **DerpEditController**: typically extends ##DerpBaseController## and |
| 112 | + presents a form to create and edit ##Derps##. Most likely uses |
| 113 | + @{class:AphrontFormView} and various ##AphrontFormXControl## classes such as |
| 114 | + @{class:AphrontFormTextControl} to create the form. |
| 115 | + - **DerpListController**: typically extends ##DerpBaseController## and displays |
| 116 | + a set of one or more ##Derps##. Might use @{class:AphrontTableView} to create |
| 117 | + a table of ##Derps##. |
| 118 | + - **DerpViewController**: typically extends ##DerpBaseController## and displays |
| 119 | + a single ##Derp##. |
| 120 | + |
| 121 | +NOTE: each directory will have a class file with an ##__init__.php## or |
| 122 | +subdirectories; never both. |
| 123 | + |
| 124 | += Next Steps = |
| 125 | + |
| 126 | + - Learn about @{article:Adding New CSS and JS}; or |
| 127 | + - learn about the @{class:LiskDAO}; or |
| 128 | + - learn how to contribute (see @{article:Contributor Introduction}). |
0 commit comments