[{"data":1,"prerenderedAt":792},["ShallowReactive",2],{"navigation":3,"\u002Fguides\u002Fshare-code-between-layers":193,"\u002Fguides\u002Fshare-code-between-layers-surround":787},[4,27,49,99,149,169,183],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":26},"Getting Started","i-lucide-rocket","\u002Fgetting-started","1.getting-started",[10,14,18,22],{"title":11,"path":12,"stem":13},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction",{"title":15,"path":16,"stem":17},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation",{"title":19,"path":20,"stem":21},"Quick Start","\u002Fgetting-started\u002Fquick-start","1.getting-started\u002F3.quick-start",{"title":23,"path":24,"stem":25},"Existing Application","\u002Fgetting-started\u002Fexisting-application","1.getting-started\u002F4.existing-application",false,{"title":28,"icon":29,"path":30,"stem":31,"children":32,"page":26},"Concepts","i-lucide-layers","\u002Fconcepts","2.concepts",[33,37,41,45],{"title":34,"path":35,"stem":36},"Layers","\u002Fconcepts\u002Flayers","2.concepts\u002F1.layers",{"title":38,"path":39,"stem":40},"Buckets","\u002Fconcepts\u002Fbuckets","2.concepts\u002F2.buckets",{"title":42,"path":43,"stem":44},"Boundaries","\u002Fconcepts\u002Fboundaries","2.concepts\u002F3.boundaries",{"title":46,"path":47,"stem":48},"Service Providers","\u002Fconcepts\u002Fservice-providers","2.concepts\u002F4.service-providers",{"title":50,"icon":51,"path":52,"stem":53,"children":54,"page":26},"Guides","i-lucide-book-marked","\u002Fguides","3.guides",[55,59,63,67,71,75,79,83,87,91,95],{"title":56,"path":57,"stem":58},"Add a Domain","\u002Fguides\u002Fadd-a-domain","3.guides\u002F01.add-a-domain",{"title":60,"path":61,"stem":62},"Share Code Between Layers","\u002Fguides\u002Fshare-code-between-layers","3.guides\u002F02.share-code-between-layers",{"title":64,"path":65,"stem":66},"Routes","\u002Fguides\u002Froutes","3.guides\u002F03.routes",{"title":68,"path":69,"stem":70},"Views and Components","\u002Fguides\u002Fviews-and-components","3.guides\u002F04.views-and-components",{"title":72,"path":73,"stem":74},"Seeders","\u002Fguides\u002Fseeders","3.guides\u002F05.seeders",{"title":76,"path":77,"stem":78},"Configuration","\u002Fguides\u002Fconfiguration","3.guides\u002F06.configuration",{"title":80,"path":81,"stem":82},"Events","\u002Fguides\u002Fevents","3.guides\u002F07.events",{"title":84,"path":85,"stem":86},"Tests and CI","\u002Fguides\u002Ftesting-and-ci","3.guides\u002F08.testing-and-ci",{"title":88,"path":89,"stem":90},"Production","\u002Fguides\u002Fproduction","3.guides\u002F09.production",{"title":92,"path":93,"stem":94},"Remove a Layer","\u002Fguides\u002Fremoving-a-layer","3.guides\u002F10.removing-a-layer",{"title":96,"path":97,"stem":98},"Multi-tenancy","\u002Fguides\u002Fmulti-tenancy","3.guides\u002F11.multi-tenancy",{"title":100,"icon":101,"path":102,"stem":103,"children":104,"page":26},"Commands","i-lucide-terminal","\u002Fcommands","4.commands",[105,109,113,117,121,125,129,133,137,141,145],{"title":106,"path":107,"stem":108},"Overview","\u002Fcommands\u002Foverview","4.commands\u002F01.overview",{"title":110,"path":111,"stem":112},"osdd:start","\u002Fcommands\u002Fosdd-start","4.commands\u002F02.osdd-start",{"title":114,"path":115,"stem":116},"osdd:layer","\u002Fcommands\u002Fosdd-layer","4.commands\u002F03.osdd-layer",{"title":118,"path":119,"stem":120},"osdd:list","\u002Fcommands\u002Fosdd-list","4.commands\u002F04.osdd-list",{"title":122,"path":123,"stem":124},"osdd:check","\u002Fcommands\u002Fosdd-check","4.commands\u002F05.osdd-check",{"title":126,"path":127,"stem":128},"osdd:graph","\u002Fcommands\u002Fosdd-graph","4.commands\u002F06.osdd-graph",{"title":130,"path":131,"stem":132},"osdd:seed","\u002Fcommands\u002Fosdd-seed","4.commands\u002F07.osdd-seed",{"title":134,"path":135,"stem":136},"osdd:phpunit","\u002Fcommands\u002Fosdd-phpunit","4.commands\u002F08.osdd-phpunit",{"title":138,"path":139,"stem":140},"osdd:remove","\u002Fcommands\u002Fosdd-remove","4.commands\u002F09.osdd-remove",{"title":142,"path":143,"stem":144},"osdd:cache","\u002Fcommands\u002Fosdd-cache","4.commands\u002F10.osdd-cache",{"title":146,"path":147,"stem":148},"Generators","\u002Fcommands\u002Fmake-commands","4.commands\u002F11.make-commands",{"title":150,"icon":151,"path":152,"stem":153,"children":154,"page":26},"API Reference","i-lucide-book-open","\u002Fapi-reference","5.api-reference",[155,159,162,166],{"title":156,"path":157,"stem":158},"LayerServiceProvider","\u002Fapi-reference\u002Flayer-service-provider","5.api-reference\u002F1.layer-service-provider",{"title":34,"path":160,"stem":161},"\u002Fapi-reference\u002Flayers","5.api-reference\u002F2.layers",{"title":163,"path":164,"stem":165},"SeederRegistry","\u002Fapi-reference\u002Fseeder-registry","5.api-reference\u002F3.seeder-registry",{"title":76,"path":167,"stem":168},"\u002Fapi-reference\u002Fconfiguration","5.api-reference\u002F4.configuration",{"title":170,"icon":171,"path":172,"stem":173,"children":174,"page":26},"Integrations","i-lucide-puzzle","\u002Fintegrations","6.integrations",[175,179],{"title":176,"path":177,"stem":178},"Laravel Boost","\u002Fintegrations\u002Flaravel-boost","6.integrations\u002F1.laravel-boost",{"title":180,"path":181,"stem":182},"Tinker and IDE Helper","\u002Fintegrations\u002Ftinker-and-ide-helper","6.integrations\u002F2.tinker-and-ide-helper",{"title":184,"icon":185,"path":186,"stem":187,"children":188,"page":26},"Upgrade","i-lucide-arrow-up-circle","\u002Fupgrade","7.upgrade",[189],{"title":190,"path":191,"stem":192},"Upgrade from 2.x","\u002Fupgrade\u002Ffrom-2x","7.upgrade\u002F1.from-2x",{"id":194,"title":60,"body":195,"description":780,"extension":781,"links":782,"meta":783,"navigation":583,"path":61,"seo":784,"sitemap":785,"stem":62,"__hash__":786},"docs\u002F3.guides\u002F02.share-code-between-layers.md",{"type":196,"value":197,"toc":770},"minimark",[198,209,214,233,264,271,346,362,373,378,400,431,437,466,470,480,514,529,533,549,679,696,700,705,713,716,720,732,736,750,756,766],[199,200,201,202,208],"p",{},"A layer may use the classes of the layers it requires, and only those. This page shows the three ways to share code and how to keep ",[203,204,205],"a",{"href":123},[206,207,122],"code",{}," green with each.",[210,211,213],"h2",{"id":212},"require-the-layer","Require the layer",[199,215,216,217,220,221,224,225,228,229,232],{},"When ",[206,218,219],{},"functional\u002Finvoices"," uses ",[206,222,223],{},"Functional\\Orders\\Models\\Order",", it requires ",[206,226,227],{},"functional\u002Forders",". For a new layer, pass ",[206,230,231],{},"--requires",":",[234,235,240],"pre",{"className":236,"code":237,"language":238,"meta":239,"style":239},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","php artisan osdd:layer functional\u002Finvoices --requires=functional\u002Forders\n","bash","",[206,241,242],{"__ignoreMap":239},[243,244,247,251,255,258,261],"span",{"class":245,"line":246},"line",1,[243,248,250],{"class":249},"sBMFI","php",[243,252,254],{"class":253},"sfazB"," artisan",[243,256,257],{"class":253}," osdd:layer",[243,259,260],{"class":253}," functional\u002Finvoices",[243,262,263],{"class":253}," --requires=functional\u002Forders\n",[199,265,266,267,270],{},"For an existing layer, add the requirement to its ",[206,268,269],{},"composer.json",", then update it:",[234,272,277],{"className":273,"code":274,"filename":275,"language":276,"meta":239,"style":239},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\"require\": {\n    \"lomkit\u002Flaravel-osdd\": \"*\",\n    \"functional\u002Forders\": \"*\"\n}\n","functional\u002Finvoices\u002Fcomposer.json","json",[206,278,279,297,322,340],{"__ignoreMap":239},[243,280,281,285,288,290,294],{"class":245,"line":246},[243,282,284],{"class":283},"sMK4o","\"",[243,286,287],{"class":253},"require",[243,289,284],{"class":283},[243,291,293],{"class":292},"sTEyZ",": ",[243,295,296],{"class":283},"{\n",[243,298,300,303,307,309,311,314,317,319],{"class":245,"line":299},2,[243,301,302],{"class":283},"    \"",[243,304,306],{"class":305},"spNyl","lomkit\u002Flaravel-osdd",[243,308,284],{"class":283},[243,310,232],{"class":283},[243,312,313],{"class":283}," \"",[243,315,316],{"class":253},"*",[243,318,284],{"class":283},[243,320,321],{"class":283},",\n",[243,323,325,327,329,331,333,335,337],{"class":245,"line":324},3,[243,326,302],{"class":283},[243,328,227],{"class":305},[243,330,284],{"class":283},[243,332,232],{"class":283},[243,334,313],{"class":283},[243,336,316],{"class":253},[243,338,339],{"class":283},"\"\n",[243,341,343],{"class":245,"line":342},4,[243,344,345],{"class":283},"}\n",[234,347,349],{"className":236,"code":348,"language":238,"meta":239,"style":239},"composer update functional\u002Finvoices\n",[206,350,351],{"__ignoreMap":239},[243,352,353,356,359],{"class":245,"line":246},[243,354,355],{"class":249},"composer",[243,357,358],{"class":253}," update",[243,360,361],{"class":253}," functional\u002Finvoices\n",[199,363,364,365,368,369,372],{},"Only the tests use a layer? Put it in ",[206,366,367],{},"require-dev",": files under ",[206,370,371],{},"tests\u002F"," may use it, the rest of the layer may not.",[374,375,377],"h3",{"id":376},"generate-code-that-points-to-another-layer","Generate code that points to another layer",[199,379,380,381,384,385,388,389,388,392,395,396,399],{},"The ",[206,382,383],{},"--model"," option of ",[206,386,387],{},"osdd:policy",", ",[206,390,391],{},"osdd:controller",[206,393,394],{},"osdd:observer"," and ",[206,397,398],{},"osdd:factory"," keeps a fully qualified class of another layer:",[234,401,403],{"className":236,"code":402,"language":238,"meta":239,"style":239},"php artisan osdd:policy UserInvoicePolicy --model='Functional\\Users\\Models\\User' --layer=functional\u002Finvoices\n",[206,404,405],{"__ignoreMap":239},[243,406,407,409,411,414,417,420,423,426,428],{"class":245,"line":246},[243,408,250],{"class":249},[243,410,254],{"class":253},[243,412,413],{"class":253}," osdd:policy",[243,415,416],{"class":253}," UserInvoicePolicy",[243,418,419],{"class":253}," --model=",[243,421,422],{"class":283},"'",[243,424,425],{"class":253},"Functional\\Users\\Models\\User",[243,427,422],{"class":283},[243,429,430],{"class":253}," --layer=functional\u002Finvoices\n",[199,432,433,436],{},[206,434,435],{},"osdd:listener"," takes an event of another layer when its name starts with a backslash:",[234,438,440],{"className":236,"code":439,"language":238,"meta":239,"style":239},"php artisan osdd:listener SendInvoice --event='\\Functional\\Orders\\Events\\OrderPlaced' --layer=functional\u002Finvoices\n",[206,441,442],{"__ignoreMap":239},[243,443,444,446,448,451,454,457,459,462,464],{"class":245,"line":246},[243,445,250],{"class":249},[243,447,254],{"class":253},[243,449,450],{"class":253}," osdd:listener",[243,452,453],{"class":253}," SendInvoice",[243,455,456],{"class":253}," --event=",[243,458,422],{"class":283},[243,460,461],{"class":253},"\\Functional\\Orders\\Events\\OrderPlaced",[243,463,422],{"class":283},[243,465,430],{"class":253},[210,467,469],{"id":468},"move-shared-code-to-its-own-layer","Move shared code to its own layer",[199,471,472,473,476,477,232],{},"When several domains need the same code, such as a ",[206,474,475],{},"Money"," value object or a set of contracts, give it a layer of its own, usually in ",[206,478,479],{},"technical\u002F",[234,481,483],{"className":236,"code":482,"language":238,"meta":239,"style":239},"php artisan osdd:layer technical\u002Fmoney --generators=provider\nphp artisan osdd:class Money --layer=technical\u002Fmoney\n",[206,484,485,499],{"__ignoreMap":239},[243,486,487,489,491,493,496],{"class":245,"line":246},[243,488,250],{"class":249},[243,490,254],{"class":253},[243,492,257],{"class":253},[243,494,495],{"class":253}," technical\u002Fmoney",[243,497,498],{"class":253}," --generators=provider\n",[243,500,501,503,505,508,511],{"class":245,"line":299},[243,502,250],{"class":249},[243,504,254],{"class":253},[243,506,507],{"class":253}," osdd:class",[243,509,510],{"class":253}," Money",[243,512,513],{"class":253}," --layer=technical\u002Fmoney\n",[199,515,516,517,520,521,524,525,528],{},"Each layer that uses it requires ",[206,518,519],{},"technical\u002Fmoney",". Keep such layers small and named after what they hold. A ",[206,522,523],{},"common"," or ",[206,526,527],{},"shared"," layer ends up holding everything, and every other layer depends on it.",[210,530,532],{"id":531},"communicate-through-events","Communicate through events",[199,534,535,536,538,539,542,543,545,546,548],{},"A layer can react to another one without the other knowing it. ",[206,537,227],{}," dispatches ",[206,540,541],{},"OrderPlaced","; ",[206,544,219],{}," requires ",[206,547,227],{}," and listens to it:",[234,550,554],{"className":551,"code":552,"filename":553,"language":250,"meta":239,"style":239},"language-php shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","namespace Functional\\Invoices\\Listeners;\n\nuse Functional\\Orders\\Events\\OrderPlaced;\n\nclass SendInvoice\n{\n    public function handle(OrderPlaced $event): void\n    {\n        \u002F\u002F ...\n    }\n}\n","functional\u002Finvoices\u002Fsrc\u002FListeners\u002FSendInvoice.php",[206,555,556,579,585,607,611,620,625,655,661,668,674],{"__ignoreMap":239},[243,557,558,562,565,568,571,573,576],{"class":245,"line":246},[243,559,561],{"class":560},"sbssI","namespace",[243,563,564],{"class":249}," Functional",[243,566,567],{"class":283},"\\",[243,569,570],{"class":249},"Invoices",[243,572,567],{"class":283},[243,574,575],{"class":249},"Listeners",[243,577,578],{"class":283},";\n",[243,580,581],{"class":245,"line":299},[243,582,584],{"emptyLinePlaceholder":583},true,"\n",[243,586,587,590,592,594,597,599,601,603,605],{"class":245,"line":324},[243,588,589],{"class":560},"use",[243,591,564],{"class":292},[243,593,567],{"class":283},[243,595,596],{"class":292},"Orders",[243,598,567],{"class":283},[243,600,80],{"class":292},[243,602,567],{"class":283},[243,604,541],{"class":292},[243,606,578],{"class":283},[243,608,609],{"class":245,"line":342},[243,610,584],{"emptyLinePlaceholder":583},[243,612,614,617],{"class":245,"line":613},5,[243,615,616],{"class":305},"class",[243,618,619],{"class":249}," SendInvoice\n",[243,621,623],{"class":245,"line":622},6,[243,624,296],{"class":283},[243,626,628,631,634,638,641,643,646,649,652],{"class":245,"line":627},7,[243,629,630],{"class":305},"    public",[243,632,633],{"class":305}," function",[243,635,637],{"class":636},"s2Zo4"," handle",[243,639,640],{"class":283},"(",[243,642,541],{"class":249},[243,644,645],{"class":283}," $",[243,647,648],{"class":292},"event",[243,650,651],{"class":283},"):",[243,653,654],{"class":560}," void\n",[243,656,658],{"class":245,"line":657},8,[243,659,660],{"class":283},"    {\n",[243,662,664],{"class":245,"line":663},9,[243,665,667],{"class":666},"sHwdD","        \u002F\u002F ...\n",[243,669,671],{"class":245,"line":670},10,[243,672,673],{"class":283},"    }\n",[243,675,677],{"class":245,"line":676},11,[243,678,345],{"class":283},[199,680,681,682,684,685,687,688,691,692,695],{},"The dependency goes one way: ",[206,683,227],{}," never references ",[206,686,219],{},". Turn on ",[203,689,690],{"href":81},"event discovery"," to register the listener without ",[206,693,694],{},"Event::listen()",".",[210,697,699],{"id":698},"break-a-cycle","Break a cycle",[199,701,702,704],{},[206,703,122],{}," fails when layers require each other:",[234,706,711],{"className":707,"code":709,"language":710},[708],"language-text","  ERROR  Cycle in the layer requirements: functional\u002Forders -> functional\u002Finvoices -> functional\u002Forders.\n","text",[206,712,709],{"__ignoreMap":239},[199,714,715],{},"Find what each side needs from the other. Move it into a third layer both require, or turn one direction into an event as above. Then remove the requirement that closed the cycle.",[210,717,719],{"id":718},"allow-an-exception","Allow an exception",[199,721,722,723,726,727,731],{},"Some references are fine without a requirement, such as contracts every layer may use. List them in ",[206,724,725],{},"osdd.boundaries.ignore",", see ",[203,728,730],{"href":729},"\u002Fconcepts\u002Fboundaries#ignoring-a-dependency","Ignoring a dependency",". Keep the list short: an ignored dependency is still a dependency.",[210,733,735],{"id":734},"see-the-result","See the result",[234,737,739],{"className":236,"code":738,"language":238,"meta":239,"style":239},"php artisan osdd:graph\n",[206,740,741],{"__ignoreMap":239},[243,742,743,745,747],{"class":245,"line":246},[243,744,250],{"class":249},[243,746,254],{"class":253},[243,748,749],{"class":253}," osdd:graph\n",[234,751,754],{"className":752,"code":753,"language":710},[708],"graph LR\n    functional_invoices[\"functional\u002Finvoices\"]\n    functional_orders[\"functional\u002Forders\"]\n    technical_money[\"technical\u002Fmoney\"]\n    functional_invoices --> functional_orders\n    functional_invoices --> technical_money\n    functional_orders --> technical_money\n",[206,755,753],{"__ignoreMap":239},[199,757,758,762,763,765],{},[203,759,760],{"href":127},[206,761,126],{}," draws what the layers declare. ",[206,764,122],{}," checks that the code matches it.",[767,768,769],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":239,"searchDepth":246,"depth":299,"links":771},[772,775,776,777,778,779],{"id":212,"depth":299,"text":213,"children":773},[774],{"id":376,"depth":324,"text":377},{"id":468,"depth":299,"text":469},{"id":531,"depth":299,"text":532},{"id":698,"depth":299,"text":699},{"id":718,"depth":299,"text":719},{"id":734,"depth":299,"text":735},"Let one layer use another, move shared code to its own layer, and break cycles, while osdd:check stays green.","md",null,{},{"title":60,"description":780},{"loc":61},"YoDV9YuxIiph77EZVTW_0SxM1fZs5tYqPm4DmUZbPJo",[788,790],{"title":56,"path":57,"stem":58,"description":789,"children":-1},"Take a new domain from an empty layer to a routed, authorized, seeded and tested resource.",{"title":64,"path":65,"stem":66,"description":791,"children":-1},"Give a layer its own web, API, console and broadcast routes.",1794437210871]