[{"data":1,"prerenderedAt":662},["ShallowReactive",2],{"navigation":3,"\u002Fgetting-started\u002Fexisting-application":193,"\u002Fgetting-started\u002Fexisting-application-surround":657},[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":23,"body":195,"description":650,"extension":651,"links":652,"meta":653,"navigation":510,"path":24,"seo":654,"sitemap":655,"stem":25,"__hash__":656},"docs\u002F1.getting-started\u002F4.existing-application.md",{"type":196,"value":197,"toc":643},"minimark",[198,216,221,246,265,269,294,321,347,351,361,433,447,451,470,567,585,599,603,617,636,639],[199,200,201,204,205,208,209,212,213,215],"p",{},[202,203,110],"code",{}," is for fresh projects only: it deletes ",[202,206,207],{},"app\u002F"," and ",[202,210,211],{},"config\u002F",". On an application with code to keep, skip it. Layers then live next to ",[202,214,207],{},", and you move domains into them at your own pace.",[217,218,220],"h2",{"id":219},"_1-install","1. Install",[222,223,228],"pre",{"className":224,"code":225,"language":226,"meta":227,"style":227},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","composer require lomkit\u002Flaravel-osdd\n","bash","",[202,229,230],{"__ignoreMap":227},[231,232,235,239,243],"span",{"class":233,"line":234},"line",1,[231,236,238],{"class":237},"sBMFI","composer",[231,240,242],{"class":241},"sfazB"," require",[231,244,245],{"class":241}," lomkit\u002Flaravel-osdd\n",[199,247,248,249,208,252,255,256,259,260,264],{},"The package defaults apply: layers go to ",[202,250,251],{},"functional\u002F",[202,253,254],{},"technical\u002F",". To change them, create ",[202,257,258],{},"config\u002Fosdd.php"," by hand with the keys of the ",[261,262,263],"a",{"href":167},"configuration reference",". The package does not publish it.",[217,266,268],{"id":267},"_2-create-the-first-layer","2. Create the first layer",[222,270,272],{"className":224,"code":271,"language":226,"meta":227,"style":227},"php artisan osdd:layer functional\u002Fbilling --generators=provider,test --composer-update\n",[202,273,274],{"__ignoreMap":227},[231,275,276,279,282,285,288,291],{"class":233,"line":234},[231,277,278],{"class":237},"php",[231,280,281],{"class":241}," artisan",[231,283,284],{"class":241}," osdd:layer",[231,286,287],{"class":241}," functional\u002Fbilling",[231,289,290],{"class":241}," --generators=provider,test",[231,292,293],{"class":241}," --composer-update\n",[199,295,296,297,300,301,304,305,308,309,312,313,316,317,320],{},"The command writes ",[202,298,299],{},"functional\u002Fbilling\u002Fcomposer.json",", adds a ",[202,302,303],{},".\u002Ffunctional\u002F*"," path repository and a ",[202,306,307],{},"\"functional\u002Fbilling\": \"*\""," requirement to the root ",[202,310,311],{},"composer.json",", then installs the layer. New code for that domain now goes in the layer, with the ",[202,314,315],{},"osdd:*"," ",[261,318,319],{"href":147},"generators",":",[222,322,324],{"className":224,"code":323,"language":226,"meta":227,"style":227},"php artisan osdd:model Invoice --migration --factory --layer=functional\u002Fbilling\n",[202,325,326],{"__ignoreMap":227},[231,327,328,330,332,335,338,341,344],{"class":233,"line":234},[231,329,278],{"class":237},[231,331,281],{"class":241},[231,333,334],{"class":241}," osdd:model",[231,336,337],{"class":241}," Invoice",[231,339,340],{"class":241}," --migration",[231,342,343],{"class":241}," --factory",[231,345,346],{"class":241}," --layer=functional\u002Fbilling\n",[217,348,350],{"id":349},"_3-move-existing-code-into-the-layer","3. Move existing code into the layer",[199,352,353,354,357,358,320],{},"To move ",[202,355,356],{},"App\\Models\\Invoice"," and its table into ",[202,359,360],{},"functional\u002Fbilling",[362,363,364,380,395,409,424],"ol",{},[365,366,367,368,371,372,375,376,379],"li",{},"Move the class to ",[202,369,370],{},"functional\u002Fbilling\u002Fsrc\u002FModels\u002FInvoice.php"," and change its namespace to ",[202,373,374],{},"Functional\\Billing\\Models",". Update the imports that use it: ",[202,377,378],{},"git grep -l 'App\\\\Models\\\\Invoice'",".",[365,381,382,383,386,387,390,391,394],{},"Move its migrations to ",[202,384,385],{},"functional\u002Fbilling\u002Fdatabase\u002Fmigrations\u002F",". Keep their file names: the ",[202,388,389],{},"migrations"," table records them by name, so ",[202,392,393],{},"migrate"," does not run them again. The generated layer provider already loads that folder.",[365,396,397,398,401,402,405,406,379],{},"Move its factory to ",[202,399,400],{},"functional\u002Fbilling\u002Fdatabase\u002Ffactories\u002F"," under ",[202,403,404],{},"Functional\\Billing\\Database\\Factories",", and point the model to it with ",[202,407,408],{},"#[UseFactory(InvoiceFactory::class)]",[365,410,411,412,415,416,419,420,423],{},"Move its policy to ",[202,413,414],{},"functional\u002Fbilling\u002Fsrc\u002FPolicies\u002F",". Laravel finds ",[202,417,418],{},"Functional\\Billing\\Policies\\InvoicePolicy"," for ",[202,421,422],{},"Functional\\Billing\\Models\\Invoice"," on its own.",[365,425,426,427,401,430,379],{},"Move its tests to ",[202,428,429],{},"functional\u002Fbilling\u002Ftests\u002F",[202,431,432],{},"Functional\\Billing\\Tests",[434,435,436],"warning",{},[199,437,438,439,442,443,446],{},"Class names stored in the database change with the namespace: the ",[202,440,441],{},"*_type"," columns of polymorphic relations without a morph map, queued jobs, notifications. Register a morph map with ",[202,444,445],{},"Relation::enforceMorphMap()"," before the move, or update those rows.",[217,448,450],{"id":449},"_4-seed-and-test-the-layers","4. Seed and test the layers",[199,452,453,454,458,459,462,463,466,467,320],{},"Layer seeders run with ",[261,455,456],{"href":131},[202,457,130],{},". To run them from ",[202,460,461],{},"db:seed"," too, call ",[202,464,465],{},"LayersSeeder"," from your ",[202,468,469],{},"DatabaseSeeder",[222,471,475],{"className":472,"code":473,"filename":474,"language":278,"meta":227,"style":227},"language-php shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","use Lomkit\\Osdd\\Seeders\\LayersSeeder;\n\npublic function run(): void\n{\n    $this->call(LayersSeeder::class);\n}\n","database\u002Fseeders\u002FDatabaseSeeder.php",[202,476,477,505,512,532,538,561],{"__ignoreMap":227},[231,478,479,483,487,491,494,496,498,500,502],{"class":233,"line":234},[231,480,482],{"class":481},"sbssI","use",[231,484,486],{"class":485},"sTEyZ"," Lomkit",[231,488,490],{"class":489},"sMK4o","\\",[231,492,493],{"class":485},"Osdd",[231,495,490],{"class":489},[231,497,72],{"class":485},[231,499,490],{"class":489},[231,501,465],{"class":485},[231,503,504],{"class":489},";\n",[231,506,508],{"class":233,"line":507},2,[231,509,511],{"emptyLinePlaceholder":510},true,"\n",[231,513,515,519,522,526,529],{"class":233,"line":514},3,[231,516,518],{"class":517},"spNyl","public",[231,520,521],{"class":517}," function",[231,523,525],{"class":524},"s2Zo4"," run",[231,527,528],{"class":489},"():",[231,530,531],{"class":481}," void\n",[231,533,535],{"class":233,"line":534},4,[231,536,537],{"class":489},"{\n",[231,539,541,544,547,550,552,555,558],{"class":233,"line":540},5,[231,542,543],{"class":489},"    $this->",[231,545,546],{"class":524},"call",[231,548,549],{"class":489},"(",[231,551,465],{"class":237},[231,553,554],{"class":489},"::",[231,556,557],{"class":481},"class",[231,559,560],{"class":489},");\n",[231,562,564],{"class":233,"line":563},6,[231,565,566],{"class":489},"}\n",[199,568,569,570,573,574,208,577,580,581,584],{},"Add one test suite per layer to ",[202,571,572],{},"phpunit.xml",". The ",[202,575,576],{},"Unit",[202,578,579],{},"Feature"," suites of ",[202,582,583],{},"tests\u002F"," stay:",[222,586,588],{"className":224,"code":587,"language":226,"meta":227,"style":227},"php artisan osdd:phpunit\n",[202,589,590],{"__ignoreMap":227},[231,591,592,594,596],{"class":233,"line":234},[231,593,278],{"class":237},[231,595,281],{"class":241},[231,597,598],{"class":241}," osdd:phpunit\n",[217,600,602],{"id":601},"_5-check-the-boundaries","5. Check the boundaries",[222,604,606],{"className":224,"code":605,"language":226,"meta":227,"style":227},"php artisan osdd:check\n",[202,607,608],{"__ignoreMap":227},[231,609,610,612,614],{"class":233,"line":234},[231,611,278],{"class":237},[231,613,281],{"class":241},[231,615,616],{"class":241}," osdd:check\n",[199,618,619,621,622,625,626,628,629,631,632,635],{},[202,620,122],{}," only reads the layers, and never reports references to ",[202,623,624],{},"App\\"," classes: a layer can use ",[202,627,207],{}," code while you move it, and ",[202,630,207],{}," can use the layers. Between layers, the ",[261,633,634],{"href":43},"boundary rule"," applies from the first layer on.",[199,637,638],{},"Repeat steps 2 to 5 for each domain.",[640,641,642],"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 .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}",{"title":227,"searchDepth":234,"depth":507,"links":644},[645,646,647,648,649],{"id":219,"depth":507,"text":220},{"id":267,"depth":507,"text":268},{"id":349,"depth":507,"text":350},{"id":449,"depth":507,"text":450},{"id":601,"depth":507,"text":602},"Add layers to an application that keeps its app\u002F folder, and move domains into them one at a time.","md",null,{},{"title":23,"description":650},{"loc":24},"dQph__tLhAeOxJw9v2jz2O5hL9MTZHO9MAJtSt5GpL0",[658,660],{"title":19,"path":20,"stem":21,"description":659,"children":-1},"Convert a fresh Laravel project to layers, create your first layer and check its boundaries, in five minutes.",{"title":34,"path":35,"stem":36,"description":661,"children":-1},"What a layer is, what its composer.json declares, and how it gets installed.",1794437209294]