[{"data":1,"prerenderedAt":1373},["ShallowReactive",2],{"navigation":3,"\u002Fdigging-deeper\u002Fartisan":307,"\u002Fdigging-deeper\u002Fartisan-surround":1368},{"3.x":4,"2.x":203},[5,32,61,99,121,147,165],{"title":6,"icon":7,"path":8,"stem":9,"children":10,"page":31},"Getting Started","i-heroicons-star","\u002Fgetting-started","1.getting-started",[11,15,19,23,27],{"title":12,"path":13,"stem":14},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction",{"title":16,"path":17,"stem":18},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation",{"title":20,"path":21,"stem":22},"Quick start","\u002Fgetting-started\u002Fquick-start","1.getting-started\u002F3.quick-start",{"title":24,"path":25,"stem":26},"Configuration","\u002Fgetting-started\u002Fconfiguration","1.getting-started\u002F4.configuration",{"title":28,"path":29,"stem":30},"Upgrade guide","\u002Fgetting-started\u002Fupgrade-guide","1.getting-started\u002F5.upgrade-guide",false,{"title":33,"icon":34,"path":35,"stem":36,"children":37,"page":31},"Resources","i-heroicons-document-text","\u002Fresources","2.resources",[38,41,45,49,53,57],{"title":33,"path":39,"stem":40},"\u002Fresources\u002Fresources","2.resources\u002F1.resources",{"title":42,"path":43,"stem":44},"Fields","\u002Fresources\u002Ffields","2.resources\u002F2.fields",{"title":46,"path":47,"stem":48},"Relationships","\u002Fresources\u002Frelations","2.resources\u002F3.relations",{"title":50,"path":51,"stem":52},"Validation","\u002Fresources\u002Fvalidation","2.resources\u002F4.validation",{"title":54,"path":55,"stem":56},"Perimeter","\u002Fresources\u002Fperimeter","2.resources\u002F5.perimeter",{"title":58,"path":59,"stem":60},"Limits","\u002Fresources\u002Flimits","2.resources\u002F6.limits",{"title":62,"icon":63,"path":64,"stem":65,"children":66,"page":31},"Search","i-heroicons-magnifying-glass","\u002Fsearch","3.search",[67,71,75,79,83,87,91,95],{"title":68,"path":69,"stem":70},"Search overview","\u002Fsearch\u002Foverview","3.search\u002F1.overview",{"title":72,"path":73,"stem":74},"Search filters","\u002Fsearch\u002Ffilters","3.search\u002F2.filters",{"title":76,"path":77,"stem":78},"Sorts and selects","\u002Fsearch\u002Fsorts-and-selects","3.search\u002F3.sorts-and-selects",{"title":80,"path":81,"stem":82},"Includes and aggregates","\u002Fsearch\u002Fincludes-and-aggregates","3.search\u002F4.includes-and-aggregates",{"title":84,"path":85,"stem":86},"Scopes and instructions","\u002Fsearch\u002Fscopes-and-instructions","3.search\u002F5.scopes-and-instructions",{"title":88,"path":89,"stem":90},"Text search","\u002Fsearch\u002Ftext-search","3.search\u002F6.text-search",{"title":92,"path":93,"stem":94},"Search engines","\u002Fsearch\u002Fsearch-engines","3.search\u002F7.search-engines",{"title":96,"path":97,"stem":98},"Searching outside HTTP","\u002Fsearch\u002Foutside-http","3.search\u002F8.outside-http",{"title":100,"icon":101,"path":102,"stem":103,"children":104,"page":31},"Writing","i-heroicons-pencil-square","\u002Fwriting","4.writing",[105,109,113,117],{"title":106,"path":107,"stem":108},"Mutate","\u002Fwriting\u002Fmutate","4.writing\u002F1.mutate",{"title":110,"path":111,"stem":112},"Writing relations","\u002Fwriting\u002Frelations","4.writing\u002F2.relations",{"title":114,"path":115,"stem":116},"Versioned rows","\u002Fwriting\u002Fversioned-rows","4.writing\u002F3.versioned-rows",{"title":118,"path":119,"stem":120},"Deleting and restoring","\u002Fwriting\u002Fdeleting","4.writing\u002F4.deleting",{"title":122,"icon":123,"path":124,"stem":125,"children":126,"page":31},"Actions and Metrics","i-heroicons-bolt","\u002Factions-and-metrics","5.actions-and-metrics",[127,131,135,139,143],{"title":128,"path":129,"stem":130},"Actions","\u002Factions-and-metrics\u002Factions","5.actions-and-metrics\u002F1.actions",{"title":132,"path":133,"stem":134},"Queued Actions","\u002Factions-and-metrics\u002Fqueued-actions","5.actions-and-metrics\u002F2.queued-actions",{"title":136,"path":137,"stem":138},"Confirmation","\u002Factions-and-metrics\u002Fconfirmation","5.actions-and-metrics\u002F3.confirmation",{"title":140,"path":141,"stem":142},"Metrics","\u002Factions-and-metrics\u002Fmetrics","5.actions-and-metrics\u002F4.metrics",{"title":144,"path":145,"stem":146},"Exports","\u002Factions-and-metrics\u002Fexports","5.actions-and-metrics\u002F5.exports",{"title":148,"icon":149,"path":150,"stem":151,"children":152,"page":31},"Authorization","i-heroicons-lock-closed","\u002Fauthorization","6.authorization",[153,157,161],{"title":154,"path":155,"stem":156},"Policies","\u002Fauthorization\u002Fpolicies","6.authorization\u002F1.policies",{"title":158,"path":159,"stem":160},"Gates","\u002Fauthorization\u002Fgates","6.authorization\u002F2.gates",{"title":162,"path":163,"stem":164},"Decision Cache","\u002Fauthorization\u002Fdecision-cache","6.authorization\u002F3.decision-cache",{"title":166,"icon":167,"path":168,"stem":169,"children":170,"page":31},"Digging Deeper","i-heroicons-list-bullet","\u002Fdigging-deeper","7.digging-deeper",[171,175,179,183,187,191,195,199],{"title":172,"path":173,"stem":174},"Details","\u002Fdigging-deeper\u002Fdetails","7.digging-deeper\u002F1.details",{"title":176,"path":177,"stem":178},"Events and Hooks","\u002Fdigging-deeper\u002Fevents-and-hooks","7.digging-deeper\u002F2.events-and-hooks",{"title":180,"path":181,"stem":182},"Custom Responses","\u002Fdigging-deeper\u002Fresponses","7.digging-deeper\u002F3.responses",{"title":184,"path":185,"stem":186},"OpenAPI Documentation","\u002Fdigging-deeper\u002Fopenapi","7.digging-deeper\u002F4.openapi",{"title":188,"path":189,"stem":190},"Precognition","\u002Fdigging-deeper\u002Fprecognition","7.digging-deeper\u002F5.precognition",{"title":192,"path":193,"stem":194},"Artisan Commands","\u002Fdigging-deeper\u002Fartisan","7.digging-deeper\u002F6.artisan",{"title":196,"path":197,"stem":198},"Laravel Boost Skill","\u002Fdigging-deeper\u002Fai-skill","7.digging-deeper\u002F7.ai-skill",{"title":200,"path":201,"stem":202},"Translations","\u002Fdigging-deeper\u002Ftranslations","7.digging-deeper\u002F8.translations",[204,215,237,260,297],{"title":6,"icon":7,"path":205,"stem":206,"children":207,"page":31},"\u002F2.x\u002Fgetting-started","2.x\u002F1.getting-started",[208,211],{"title":16,"path":209,"stem":210},"\u002F2.x\u002Fgetting-started\u002Finstallation","2.x\u002F1.getting-started\u002F1.installation",{"title":212,"path":213,"stem":214},"Upgrade Guide","\u002F2.x\u002Fgetting-started\u002Fupgrade-guide","2.x\u002F1.getting-started\u002F2.upgrade-guide",{"title":216,"icon":217,"path":218,"stem":219,"children":220,"page":31},"Endpoints","i-heroicons-arrow-uturn-left","\u002F2.x\u002Fendpoints","2.x\u002F2.endpoints",[221,224,227,230,233],{"title":172,"path":222,"stem":223},"\u002F2.x\u002Fendpoints\u002Fdetails","2.x\u002F2.endpoints\u002F1.details",{"title":62,"path":225,"stem":226},"\u002F2.x\u002Fendpoints\u002Fsearch","2.x\u002F2.endpoints\u002F2.search",{"title":106,"path":228,"stem":229},"\u002F2.x\u002Fendpoints\u002Fmutate","2.x\u002F2.endpoints\u002F3.mutate",{"title":128,"path":231,"stem":232},"\u002F2.x\u002Fendpoints\u002Factions","2.x\u002F2.endpoints\u002F4.actions",{"title":234,"path":235,"stem":236},"Delete","\u002F2.x\u002Fendpoints\u002Fdelete","2.x\u002F2.endpoints\u002F5.delete",{"title":33,"icon":34,"path":238,"stem":239,"children":240,"page":31},"\u002F2.x\u002Fresources","2.x\u002F3.resources",[241,245,249,252,256],{"title":242,"path":243,"stem":244},"Basics","\u002F2.x\u002Fresources\u002Fbasics","2.x\u002F3.resources\u002F1.basics",{"title":246,"path":247,"stem":248},"Exposed Data","\u002F2.x\u002Fresources\u002Fexposed-data","2.x\u002F3.resources\u002F2.exposed-data",{"title":46,"path":250,"stem":251},"\u002F2.x\u002Fresources\u002Frelationships","2.x\u002F3.resources\u002F3.relationships",{"title":253,"path":254,"stem":255},"Validations","\u002F2.x\u002Fresources\u002Fvalidations","2.x\u002F3.resources\u002F4.validations",{"title":257,"path":258,"stem":259},"Interactions","\u002F2.x\u002Fresources\u002Finteractions","2.x\u002F3.resources\u002F5.interactions",{"title":166,"icon":167,"path":261,"stem":262,"children":263,"page":31},"\u002F2.x\u002Fdigging-deeper","2.x\u002F4.digging-deeper",[264,267,271,274,278,282,286,290,294],{"title":128,"path":265,"stem":266},"\u002F2.x\u002Fdigging-deeper\u002Factions","2.x\u002F4.digging-deeper\u002F1.actions",{"title":268,"path":269,"stem":270},"Hooks","\u002F2.x\u002Fdigging-deeper\u002Fhooks","2.x\u002F4.digging-deeper\u002F2.hooks",{"title":158,"path":272,"stem":273},"\u002F2.x\u002Fdigging-deeper\u002Fgates","2.x\u002F4.digging-deeper\u002F3.gates",{"title":275,"path":276,"stem":277},"Authorizations","\u002F2.x\u002Fdigging-deeper\u002Fauthorizations","2.x\u002F4.digging-deeper\u002F4.authorizations",{"title":279,"path":280,"stem":281},"Full Text Search","\u002F2.x\u002Fdigging-deeper\u002Ffull-text-search","2.x\u002F4.digging-deeper\u002F5.full-text-search",{"title":283,"path":284,"stem":285},"Instructions","\u002F2.x\u002Fdigging-deeper\u002Finstructions","2.x\u002F4.digging-deeper\u002F6.instructions",{"title":287,"path":288,"stem":289},"Responses","\u002F2.x\u002Fdigging-deeper\u002Fresponses","2.x\u002F4.digging-deeper\u002F7.responses",{"title":291,"path":292,"stem":293},"Documentation","\u002F2.x\u002Fdigging-deeper\u002Fdocumentation","2.x\u002F4.digging-deeper\u002F8.documentation",{"title":188,"path":295,"stem":296},"\u002F2.x\u002Fdigging-deeper\u002Fprecognition","2.x\u002F4.digging-deeper\u002F9.precognition",{"title":298,"icon":299,"path":300,"stem":301,"children":302,"page":31},"Integrations","i-lucide-puzzle","\u002F2.x\u002Fintegrations","2.x\u002F5.integrations",[303],{"title":304,"path":305,"stem":306},"Flutter","\u002F2.x\u002Fintegrations\u002Fflutter","2.x\u002F5.integrations\u002F1.flutter",{"id":308,"title":192,"body":309,"description":1360,"extension":1361,"links":1362,"meta":1363,"navigation":1364,"path":193,"seo":1365,"sitemap":1366,"stem":194,"__hash__":1367},"docs3x\u002F7.digging-deeper\u002F6.artisan.md",{"type":310,"value":311,"toc":1347},"minimark",[312,325,460,471,490,494,507,554,560,564,569,605,613,620,658,664,734,737,759,789,794,803,809,949,955,967,977,981,1001,1022,1024,1044,1074,1081,1089,1092,1115,1212,1235,1239,1289,1293,1315,1343],[313,314,315,316,320,321,324],"p",{},"The package ships generators for each class it uses. The classes they write pass Pint with the ",[317,318,319],"code",{},"laravel"," preset and Larastan at level 10: they import the classes they use and mark each overriding method with ",[317,322,323],{},"#[\\Override]",".",[326,327,328,341],"table",{},[329,330,331],"thead",{},[332,333,334,338],"tr",{},[335,336,337],"th",{},"Command",[335,339,340],{},"Writes",[342,343,344,355,367,379,391,403,415,427,439],"tbody",{},[332,345,346,352],{},[347,348,349],"td",{},[317,350,351],{},"rest:quick-start",[347,353,354],{},"the resources, controllers, policies and routes of the models you choose",[332,356,357,362],{},[347,358,359],{},[317,360,361],{},"rest:resource PostResource --model=Post",[347,363,364],{},[317,365,366],{},"app\u002FRest\u002FResources\u002FPostResource.php",[332,368,369,374],{},[347,370,371],{},[317,372,373],{},"rest:controller PostsController --resource=PostResource",[347,375,376],{},[317,377,378],{},"app\u002FRest\u002FControllers\u002FPostsController.php",[332,380,381,386],{},[347,382,383],{},[317,384,385],{},"rest:policy PostPolicy --model=Post",[347,387,388],{},[317,389,390],{},"app\u002FPolicies\u002FPostPolicy.php",[332,392,393,398],{},[347,394,395],{},[317,396,397],{},"rest:action ExtendSubscriptions",[347,399,400],{},[317,401,402],{},"app\u002FRest\u002FActions\u002FExtendSubscriptions.php",[332,404,405,410],{},[347,406,407],{},[317,408,409],{},"rest:instruction OddEvenId",[347,411,412],{},[317,413,414],{},"app\u002FRest\u002FInstructions\u002FOddEvenId.php",[332,416,417,422],{},[347,418,419],{},[317,420,421],{},"rest:metric OrdersByStatus --type=partition --group-by=status",[347,423,424],{},[317,425,426],{},"app\u002FRest\u002FMetrics\u002FOrdersByStatus.php",[332,428,429,434],{},[347,430,431],{},[317,432,433],{},"rest:response ArticleResponse",[347,435,436],{},[317,437,438],{},"app\u002FRest\u002FResponses\u002FArticleResponse.php",[332,440,441,450],{},[347,442,443,446,447],{},[317,444,445],{},"rest:base-resource",", ",[317,448,449],{},"rest:base-controller",[347,451,452,453,456,457],{},"the abstract base classes ",[317,454,455],{},"app\u002FRest\u002FResources\u002FResource.php"," and ",[317,458,459],{},"app\u002FRest\u002FControllers\u002FController.php",[313,461,462,465,466,324],{},[317,463,464],{},"rest:check"," writes nothing: it ",[467,468,470],"a",{"href":469},"#checking-the-application","checks the application",[313,472,473,474,477,478,481,482,485,486,489],{},"Every generator keeps an existing class: it prints ",[317,475,476],{},"\u003CType> already exists."," and exits with ",[317,479,480],{},"0",". Pass ",[317,483,484],{},"--force"," (",[317,487,488],{},"-f",") to replace it.",[491,492,20],"h2",{"id":493},"quick-start",[313,495,496,498,499,502,503,506],{},[317,497,351],{}," asks which models to expose, then writes their resources from their tables, their controllers, a policy that allows every ability when Gate finds none, and one route per model behind the ",[317,500,501],{},"auth"," middleware of the guard, ",[317,504,505],{},"auth:sanctum"," by default. It checks the result in a new process before it reports success.",[508,509,514],"pre",{"className":510,"code":511,"language":512,"meta":513,"style":513},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","php artisan rest:quick-start\nphp artisan rest:quick-start --no-interaction --model=Post --model=Tag --install-api\n","bash","",[317,515,516,532],{"__ignoreMap":513},[517,518,521,525,529],"span",{"class":519,"line":520},"line",1,[517,522,524],{"class":523},"sBMFI","php",[517,526,528],{"class":527},"sfazB"," artisan",[517,530,531],{"class":527}," rest:quick-start\n",[517,533,535,537,539,542,545,548,551],{"class":519,"line":534},2,[517,536,524],{"class":523},[517,538,528],{"class":527},[517,540,541],{"class":527}," rest:quick-start",[517,543,544],{"class":527}," --no-interaction",[517,546,547],{"class":527}," --model=Post",[517,549,550],{"class":527}," --model=Tag",[517,552,553],{"class":527}," --install-api\n",[313,555,556,557,559],{},"See ",[467,558,20],{"href":21}," for every option.",[491,561,563],{"id":562},"checking-the-application","Checking the application",[313,565,566,568],{},[317,567,464],{}," checks the routes, policies, perimeters and action row checks of your resources. Run it in CI:",[508,570,572],{"className":510,"code":571,"language":512,"meta":513,"style":513},"php artisan rest:check\nphp artisan rest:check \"App\\Rest\\Controllers\\PostsController\" --json\n",[317,573,574,583],{"__ignoreMap":513},[517,575,576,578,580],{"class":519,"line":520},[517,577,524],{"class":523},[517,579,528],{"class":527},[517,581,582],{"class":527}," rest:check\n",[517,584,585,587,589,592,596,599,602],{"class":519,"line":534},[517,586,524],{"class":523},[517,588,528],{"class":527},[517,590,591],{"class":527}," rest:check",[517,593,595],{"class":594},"sMK4o"," \"",[517,597,598],{"class":527},"App\\Rest\\Controllers\\PostsController",[517,600,601],{"class":594},"\"",[517,603,604],{"class":527}," --json\n",[508,606,611],{"className":607,"code":609,"language":610},[608],"language-text","routes and policies ... 14 routes authenticated, 2 policies found\nrows ... 1 resource with a perimeter, 1 marked #[WithoutPerimeter]\nApp\\Rest\\Resources\\CountryResource ... #[WithoutPerimeter]\nactions ... 1 action checks each row\n","text",[317,612,609],{"__ignoreMap":513},[313,614,615,616,619],{},"Without arguments, it checks every controller that a route uses. It exits with ",[317,617,618],{},"1"," when:",[621,622,623,627,630,641],"ul",{},[624,625,626],"li",{},"a route of a controller has no authentication middleware, or a model has no policy;",[624,628,629],{},"no route uses a controller of the package;",[624,631,632,633,636,637,640],{},"a resource that the routes reach, through their relations too, does not override ",[317,634,635],{},"perimeterQuery()",", so every row is visible to users who pass ",[317,638,639],{},"viewAny",";",[624,642,643,644,646,647,649,650,653,654,657],{},"an action on the ",[317,645,62],{}," or ",[317,648,33],{}," target returns ",[317,651,652],{},"null"," from ",[317,655,656],{},"authorizeEach()",", so no policy ability is checked on each row.",[508,659,662],{"className":660,"code":661,"language":610},[608],"rows ... FAILED\n⇂ App\\Rest\\Resources\\JournalResource does not override perimeterQuery(): every row is visible to users who pass viewAny. Override perimeterQuery() to limit the rows, or mark the resource with #[WithoutPerimeter] when every row is meant for these users\n",[317,663,661],{"__ignoreMap":513},[621,665,666,678,689,729],{},[624,667,668,669,673,674,677],{},"Override ",[467,670,671],{"href":55},[317,672,635],{},", or mark a resource whose rows are meant for all these users, such as countries, with ",[317,675,676],{},"#[Lomkit\\Rest\\Attributes\\WithoutPerimeter]",". A subclass inherits the attribute.",[624,679,680,681,653,684,324],{},"An action that only reads returns ",[317,682,683],{},"'view'",[467,685,687],{"href":686},"\u002Factions-and-metrics\u002Factions#checking-each-row",[317,688,656],{},[624,690,691,694,695,446,698,446,701,446,704,707,708,485,711,446,714,446,717,719,720,485,723,446,726,728],{},[317,692,693],{},"--json"," prints the report as an object: ",[317,696,697],{},"routes",[317,699,700],{},"policies",[317,702,703],{},"problems",[317,705,706],{},"search",", then ",[317,709,710],{},"rows",[317,712,713],{},"perimeter",[317,715,716],{},"without_perimeter",[317,718,703],{},") and ",[317,721,722],{},"actions",[317,724,725],{},"checked",[317,727,703],{},").",[624,730,731,733],{},[317,732,351],{}," checks the routes and the policies only.",[491,735,33],{"id":736},"resources",[508,738,740],{"className":510,"code":739,"language":512,"meta":513,"style":513},"php artisan rest:resource PostResource --model=Post --generate\n",[317,741,742],{"__ignoreMap":513},[517,743,744,746,748,751,754,756],{"class":519,"line":520},[517,745,524],{"class":523},[517,747,528],{"class":527},[517,749,750],{"class":527}," rest:resource",[517,752,753],{"class":527}," PostResource",[517,755,547],{"class":527},[517,757,758],{"class":527}," --generate\n",[621,760,761,776,783],{},[624,762,763,764,767,768,771,772,775],{},"Without ",[317,765,766],{},"--model",", the model is guessed from the class name: ",[317,769,770],{},"PostResource"," gives ",[317,773,774],{},"App\\Models\\Post"," when that class exists.",[624,777,778,779,782],{},"The key field is ",[317,780,781],{},"ID::make()"," with the key name of the model.",[624,784,785,788],{},[317,786,787],{},"rest:resource"," creates the base resource when it is missing.",[790,791,793],"h3",{"id":792},"generating-the-fields-and-relations","Generating the fields and relations",[313,795,796,485,799,802],{},[317,797,798],{},"--generate",[317,800,801],{},"-G",") reads the table of the model and declares one field per column, in the order of the table, then one relation per relation method whose related model has a resource. Run it after the migrations.",[508,804,807],{"className":805,"code":806,"language":610},[608],"PostResource ... 8 fields, 1 relation\nSkipped: author: no resource for App\\Models\\User. Generate one first with php artisan rest:resource UserResource --model=User --generate, then run this command again with --force.\n",[317,808,806],{"__ignoreMap":513},[621,810,811,856,892,906,920,930],{},[624,812,813,814,817,818,446,821,446,824,446,827,446,830,446,833,456,836,839,840,446,843,446,846,446,849,456,852,855],{},"A cast gives the field type when one matches: a backed enum gives ",[317,815,816],{},"Enum",", the JSON casts give ",[317,819,820],{},"Json",[317,822,823],{},"boolean",[317,825,826],{},"integer",[317,828,829],{},"decimal",[317,831,832],{},"float",[317,834,835],{},"date",[317,837,838],{},"datetime"," give ",[317,841,842],{},"Boolean",[317,844,845],{},"Integer",[317,847,848],{},"Number",[317,850,851],{},"Date",[317,853,854],{},"DateTime",". Otherwise the column type decides.",[624,857,858,859,862,863,866,867,870,871,446,874,456,877,880,881,884,885,646,888,891],{},"The columns that the authentication flow writes are left out, with a note: ",[317,860,861],{},"remember_token"," (or the ",[317,864,865],{},"getRememberTokenName()"," of an ",[317,868,869],{},"Authenticatable"," model), ",[317,872,873],{},"two_factor_secret",[317,875,876],{},"two_factor_recovery_codes",[317,878,879],{},"two_factor_confirmed_at",". ",[317,882,883],{},"password"," keeps its field. A hidden column that the model does not let fill, when the model declares ",[317,886,887],{},"$fillable",[317,889,890],{},"$guarded",", is left out with a note too.",[624,893,894,895,898,899,902,903,324],{},"A nullable column gets ",[317,896,897],{},"nullable()",". The timestamps, auto-increment and generated columns get ",[317,900,901],{},"readonly()",". A hidden column gets ",[317,904,905],{},"writeOnly()",[624,907,908,909,912,913,916,917,324],{},"A string column whose length the database reports gets ",[317,910,911],{},"rules('max:\u003Clength>')",". A column that is not nullable and has no default gets ",[317,914,915],{},"creationRules('required')",", and a column with a unique index gets ",[317,918,919],{},"Rule::unique()",[624,921,922,923,926,927,929],{},"A generated ",[317,924,925],{},"BelongsTo"," relation makes its foreign key ",[317,928,901],{},", so clients set it through the relation.",[624,931,932,933,936,937,940,941,944,945,948],{},"A ",[317,934,935],{},"MorphTo"," relation is skipped, with a note that prints the declaration to write by hand. The note names the resources of the morph map models that point back to the relation, through a ",[317,938,939],{},"morphOne()",", a ",[317,942,943],{},"morphMany()"," or a ",[317,946,947],{},"morphToMany()"," of the same morph name:",[508,950,953],{"className":951,"code":952,"language":610},[608],"Skipped: commentable: MorphTo relations are not generated, declare it in relations() by hand with its targets, for example MorphTo::make('commentable', [PostResource::class, VideoResource::class]).\n",[317,954,952],{"__ignoreMap":513},[621,956,957],{},[624,958,959,960,963,964,324],{},"A many-to-many relation with ",[317,961,962],{},"withPivot()"," columns gets ",[317,965,966],{},"pivotFields([...])",[313,968,969,970,972,973,976],{},"When the command runs interactively without ",[317,971,798],{}," and the table exists, it asks ",[317,974,975],{},"Generate the fields and relations from the \u003Ctable> table?",". Read the generated fields before you expose the resource.",[491,978,980],{"id":979},"controllers","Controllers",[508,982,984],{"className":510,"code":983,"language":512,"meta":513,"style":513},"php artisan rest:controller PostsController --resource=PostResource\n",[317,985,986],{"__ignoreMap":513},[517,987,988,990,992,995,998],{"class":519,"line":520},[517,989,524],{"class":523},[517,991,528],{"class":527},[517,993,994],{"class":527}," rest:controller",[517,996,997],{"class":527}," PostsController",[517,999,1000],{"class":527}," --resource=PostResource\n",[313,1002,763,1003,1006,1007,771,1010,1013,1014,1017,1018,1021],{},[317,1004,1005],{},"--resource",", the resource is guessed: ",[317,1008,1009],{},"PostsController",[317,1011,1012],{},"App\\Rest\\Resources\\PostResource",". When nothing is found, the ",[317,1015,1016],{},"$resource"," line is left out and the command warns: set it before ",[317,1019,1020],{},"Rest::resource()"," registers the controller.",[491,1023,154],{"id":700},[508,1025,1027],{"className":510,"code":1026,"language":512,"meta":513,"style":513},"php artisan rest:policy PostPolicy --model=Post\n",[317,1028,1029],{"__ignoreMap":513},[517,1030,1031,1033,1035,1038,1041],{"class":519,"line":520},[517,1032,524],{"class":523},[517,1034,528],{"class":527},[517,1036,1037],{"class":527}," rest:policy",[517,1039,1040],{"class":527}," PostPolicy",[517,1042,1043],{"class":527}," --model=Post\n",[313,1045,1046,1047,446,1050,446,1053,446,1056,456,1059,1062,1063,456,1066,1069,1070,1073],{},"The policy allows every ability to a signed-in user: ",[317,1048,1049],{},"viewAny()",[317,1051,1052],{},"view()",[317,1054,1055],{},"create()",[317,1057,1058],{},"update()",[317,1060,1061],{},"delete()",", plus ",[317,1064,1065],{},"restore()",[317,1067,1068],{},"forceDelete()"," for a model that uses ",[317,1071,1072],{},"SoftDeletes",". The user parameter has the type of the user model of the default guard.",[313,1075,1076,1077,1080],{},"When Gate already finds another policy for the model, the command prints ",[317,1078,1079],{},"The model [App\\Models\\Post] already has the policy [App\\Policies\\ContentPolicy]."," and writes nothing.",[1082,1083,1084],"warning",{},[313,1085,1086,1087,324],{},"Edit the generated policy before production. See ",[467,1088,154],{"href":155},[491,1090,140],{"id":1091},"metrics",[508,1093,1095],{"className":510,"code":1094,"language":512,"meta":513,"style":513},"php artisan rest:metric OrdersByStatus --type=partition --group-by=status\n",[317,1096,1097],{"__ignoreMap":513},[517,1098,1099,1101,1103,1106,1109,1112],{"class":519,"line":520},[517,1100,524],{"class":523},[517,1102,528],{"class":527},[517,1104,1105],{"class":527}," rest:metric",[517,1107,1108],{"class":527}," OrdersByStatus",[517,1110,1111],{"class":527}," --type=partition",[517,1113,1114],{"class":527}," --group-by=status\n",[326,1116,1117,1132],{},[329,1118,1119],{},[332,1120,1121,1126],{},[335,1122,1123],{},[317,1124,1125],{},"--type",[335,1127,1128,1131],{},[317,1129,1130],{},"calculate()"," returns",[342,1133,1134,1147,1160,1172,1184,1195],{},[332,1135,1136,1141],{},[347,1137,1138],{},[317,1139,1140],{},"value",[347,1142,1143,1146],{},[317,1144,1145],{},"$this->count($query)",", without ranges",[332,1148,1149,1154],{},[347,1150,1151],{},[317,1152,1153],{},"trend",[347,1155,1156,1159],{},[317,1157,1158],{},"$this->countByDays($query)",", with the ranges 7, 30 and 90 days",[332,1161,1162,1167],{},[347,1163,1164],{},[317,1165,1166],{},"partition",[347,1168,1169],{},[317,1170,1171],{},"$this->count($query, '\u003Cgroup-by>')",[332,1173,1174,1179],{},[347,1175,1176],{},[317,1177,1178],{},"progress",[347,1180,1181],{},[317,1182,1183],{},"$this->count($query, target: 100)",[332,1185,1186,1190],{},[347,1187,1188],{},[317,1189,326],{},[347,1191,1192],{},[317,1193,1194],{},"$this->rows($query, '\u003Cgroup-by>', ['count' => TableColumn::count()])",[332,1196,1197,1202],{},[347,1198,1199],{},[317,1200,1201],{},"custom",[347,1203,1204,1205,1208,1209],{},"a ",[317,1206,1207],{},"ValueResult",", in a class that extends ",[317,1210,1211],{},"Metric",[313,1213,1214,1217,1218,456,1220,1222,1223,1226,1227,1229,1230,1232,1233,324],{},[317,1215,1216],{},"--group-by"," is required for ",[317,1219,1166],{},[317,1221,326],{},". With ",[317,1224,1225],{},"--no-interaction",", a metric without ",[317,1228,1125],{}," is a ",[317,1231,1140],{}," metric. See ",[467,1234,140],{"href":141},[491,1236,1238],{"id":1237},"actions-instructions-and-responses","Actions, instructions and responses",[621,1240,1241,1264,1276],{},[624,1242,1243,1246,1247,1250,1251,1254,1255,1258,1259,1261,1262,324],{},[317,1244,1245],{},"rest:action"," writes an action with ",[317,1248,1249],{},"handle(ActionFields $fields, Collection $models)"," and a ",[317,1252,1253],{},"fields()"," method that returns ",[317,1256,1257],{},"[]",". It has the ",[317,1260,62],{}," target. See ",[467,1263,128],{"href":129},[624,1265,1266,1269,1270,1273,1274,324],{},[317,1267,1268],{},"rest:instruction"," writes an instruction with ",[317,1271,1272],{},"handle(InstructionFields $fields, Builder $query)",". See ",[467,1275,84],{"href":85},[624,1277,1278,1281,1282,1285,1286,324],{},[317,1279,1280],{},"rest:response"," writes a response with its ",[317,1283,1284],{},"map()"," method. See ",[467,1287,1288],{"href":181},"Custom responses",[491,1290,1292],{"id":1291},"published-stubs","Published stubs",[313,1294,1295,1296,1299,1300,1303,1304,456,1307,1310,1311,1314],{},"The generators read the stubs that ",[317,1297,1298],{},"php artisan stub:publish"," copies to ",[317,1301,1302],{},"stubs\u002Frest.\u003Cname>.stub",", and fall back to the package stubs. A published stub keeps the placeholders that the generator fills, such as ",[317,1305,1306],{},"{{ namespace }}",[317,1308,1309],{},"{{ class }}",". A missing placeholder throws ",[317,1312,1313],{},"Lomkit\\Rest\\Exceptions\\InvalidStubException",", which names the stub and the placeholder.",[313,1316,1317,1320,1321,446,1324,446,1327,446,1330,446,1333,1336,1337,1340,1341,324],{},[317,1318,1319],{},"rest:metric"," reads one stub per type: ",[317,1322,1323],{},"rest.metric-value.stub",[317,1325,1326],{},"rest.metric-trend.stub",[317,1328,1329],{},"rest.metric-partition.stub",[317,1331,1332],{},"rest.metric-progress.stub",[317,1334,1335],{},"rest.metric-table.stub",", and ",[317,1338,1339],{},"rest.metric.stub"," for ",[317,1342,1201],{},[1344,1345,1346],"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}",{"title":513,"searchDepth":520,"depth":534,"links":1348},[1349,1350,1351,1355,1356,1357,1358,1359],{"id":493,"depth":534,"text":20},{"id":562,"depth":534,"text":563},{"id":736,"depth":534,"text":33,"children":1352},[1353],{"id":792,"depth":1354,"text":793},3,{"id":979,"depth":534,"text":980},{"id":700,"depth":534,"text":154},{"id":1091,"depth":534,"text":140},{"id":1237,"depth":534,"text":1238},{"id":1291,"depth":534,"text":1292},"Generate resources from your tables, controllers, policies, actions, metrics and responses, and check perimeters and policies with rest:check.","md",null,{},true,{"title":192,"description":1360},{"loc":193},"cZbwzVnQ9aEMZ6kGp190s3fvcU2B5jrcEb4BwV894oU",[1369,1371],{"title":188,"path":189,"stem":190,"description":1370,"children":-1},"Validate a request live from a form with Laravel Precognition, after the authorization checks and without running the endpoint.",{"title":196,"path":197,"stem":198,"description":1372,"children":-1},"Give your coding agent the conventions of Laravel Rest API with the skill that the package ships for Laravel Boost.",1794181355560]