[{"data":1,"prerenderedAt":1549},["ShallowReactive",2],{"navigation":3,"\u002Fdocs\u002Fphp":135,"\u002Fdocs\u002Fphp-surround":1545},[4],{"title":5,"path":6,"stem":7,"children":8,"page":134},"Docs","\u002Fdocs","docs",[9,13,17,21,25,29,33,37,41,45,49,53,57,61,70,74,78,82,86,90,94,98,102,106,110,114,118,122,126,130],{"title":10,"path":11,"stem":12},"AI harnesses: LLM tools, MCP servers and agents","\u002Fdocs\u002Fai-tools","docs\u002Fai-tools",{"title":14,"path":15,"stem":16},"Architecture","\u002Fdocs\u002Farchitecture","docs\u002Farchitecture",{"title":18,"path":19,"stem":20},"Web \u002F native bridges","\u002Fdocs\u002Fbridges","docs\u002Fbridges",{"title":22,"path":23,"stem":24},"Broadcast channels and tests","\u002Fdocs\u002Fchannels-and-tests","docs\u002Fchannels-and-tests",{"title":26,"path":27,"stem":28},"CLI reference","\u002Fdocs\u002Fcli","docs\u002Fcli",{"title":30,"path":31,"stem":32},"Completeness: how far an answer reaches","\u002Fdocs\u002Fcompleteness","docs\u002Fcompleteness",{"title":34,"path":35,"stem":36},"Configuration","\u002Fdocs\u002Fconfiguration","docs\u002Fconfiguration",{"title":38,"path":39,"stem":40},"External systems","\u002Fdocs\u002Fexternal","docs\u002Fexternal",{"title":42,"path":43,"stem":44},"Generated, copied and vendored files","\u002Fdocs\u002Fgenerated","docs\u002Fgenerated",{"title":46,"path":47,"stem":48},"Installing and updating cg","\u002Fdocs\u002Finstall","docs\u002Finstall",{"title":50,"path":51,"stem":52},"Java","\u002Fdocs\u002Fjava","docs\u002Fjava",{"title":54,"path":55,"stem":56},"Kotlin","\u002Fdocs\u002Fkotlin","docs\u002Fkotlin",{"title":58,"path":59,"stem":60},"Known limitations","\u002Fdocs\u002Flimitations","docs\u002Flimitations",{"title":62,"path":63,"stem":64,"children":65},"MCP server","\u002Fdocs\u002Fmcp","docs\u002Fmcp",[66],{"title":67,"path":68,"stem":69},"code-graph MCP: sample outputs (real calls via the MCP Python SDK stdio client)","\u002Fdocs\u002Fmcp\u002Fsample_outputs","docs\u002Fmcp\u002Fsample_outputs",{"title":71,"path":72,"stem":73},"Rust, C and C++","\u002Fdocs\u002Fnative","docs\u002Fnative",{"title":75,"path":76,"stem":77},"Port gaps: cg parity","\u002Fdocs\u002Fparity","docs\u002Fparity",{"title":79,"path":80,"stem":81},"PHP","\u002Fdocs\u002Fphp","docs\u002Fphp",{"title":83,"path":84,"stem":85},"Planned changes","\u002Fdocs\u002Fplans","docs\u002Fplans",{"title":87,"path":88,"stem":89},"Platform-specific code","\u002Fdocs\u002Fplatforms","docs\u002Fplatforms",{"title":91,"path":92,"stem":93},"Protocol links","\u002Fdocs\u002Fprotocols","docs\u002Fprotocols",{"title":95,"path":96,"stem":97},"Python","\u002Fdocs\u002Fpython","docs\u002Fpython",{"title":99,"path":100,"stem":101},"Quick start","\u002Fdocs\u002Fquickstart","docs\u002Fquickstart",{"title":103,"path":104,"stem":105},"Graph schema","\u002Fdocs\u002Fschema","docs\u002Fschema",{"title":107,"path":108,"stem":109},"Attack surface","\u002Fdocs\u002Fsurface","docs\u002Fsurface",{"title":111,"path":112,"stem":113},"Swift","\u002Fdocs\u002Fswift","docs\u002Fswift",{"title":115,"path":116,"stem":117},"TypeScript \u002F JavaScript frameworks","\u002Fdocs\u002Fts-frameworks","docs\u002Fts-frameworks",{"title":119,"path":120,"stem":121},"How we validate","\u002Fdocs\u002Fvalidation","docs\u002Fvalidation",{"title":123,"path":124,"stem":125},"Validation log","\u002Fdocs\u002Fvalidation-log","docs\u002Fvalidation-log",{"title":127,"path":128,"stem":129},"Value facts and resolutions","\u002Fdocs\u002Fvalue-facts","docs\u002Fvalue-facts",{"title":131,"path":132,"stem":133},"Visual view","\u002Fdocs\u002Fviz","docs\u002Fviz",false,{"id":136,"title":79,"body":137,"description":593,"extension":1540,"meta":1541,"navigation":1542,"path":80,"seo":1543,"stem":81,"__hash__":1544},"docs\u002Fdocs\u002Fphp.md",{"type":138,"value":139,"toc":1529},"minimark",[140,145,185,199,236,247,291,303,307,344,474,505,565,586,596,612,616,634,669,696,734,740,782,786,815,818,954,967,971,987,1069,1087,1091,1119,1179,1255,1400,1414,1424,1440,1444,1525],[141,142,144],"h2",{"id":143},"class-properties-88","Class properties (#88)",[146,147,148,149,153,154,157,158,161,162,165,166,169,170,173,174,176,177,180,181,184],"p",{},"A declared instance property (",[150,151,152],"code",{},"private array $items = [];",") or a constructor-promoted one\n(",[150,155,156],{},"public function __construct(private Pricer $pricer)",") is a ",[150,159,160],{},"property:\u003CClass>::$\u003Cname>"," node with attrs\n",[150,163,164],{},"property: stored",". A promoted property also has ",[150,167,168],{},"promoted: true",". A static property and a docblock ",[150,171,172],{},"@property"," are\nnot stored properties. A docblock ",[150,175,172],{}," is usually a Laravel model attribute, which is a column\n(",[150,178,179],{},"READS_COLUMN"," \u002F ",[150,182,183],{},"WRITES_COLUMN",").",[146,186,187,188,180,191,194,195,198],{},"Reads and writes are ",[150,189,190],{},"READS_PROP",[150,192,193],{},"WRITES_PROP"," edges onto that node, with attr ",[150,196,197],{},"receiver",":",[200,201,202,213,230],"ul",{},[203,204,205,208,209,212],"li",{},[150,206,207],{},"$this->x"," binds ",[150,210,211],{},"exact",". The property can be declared on the class, an ancestor or a used trait.",[203,214,215,208,218,221,222,225,226,229],{},[150,216,217],{},"$v->x",[150,219,220],{},"resolved"," when the type of ",[150,223,224],{},"$v"," is known: a typed parameter, a typed property, a local built by\n",[150,227,228],{},"new",", or a return type.",[203,231,232,233,184],{},"An unknown receiver binds nothing (stat ",[150,234,235],{},"property_refs_unresolved",[146,237,238,239,242,243,246],{},"A plain ",[150,240,241],{},"= v"," is a write. These are writes with ",[150,244,245],{},"via",", plus the read the walk records:",[200,248,249,269,283],{},[203,250,251,254,255,254,258,254,261,264,265,268],{},[150,252,253],{},"+=",", ",[150,256,257],{},".=",[150,259,260],{},"++",[150,262,263],{},"--"," (",[150,266,267],{},"via: compound",");",[203,270,271,254,274,254,277,264,280,268],{},[150,272,273],{},"$this->items[] = v",[150,275,276],{},"$this->map[k] = v",[150,278,279],{},"unset($this->map[k])",[150,281,282],{},"via: item",[203,284,285,264,288,184],{},[150,286,287],{},"unset($this->x)",[150,289,290],{},"via: unset",[146,292,293,180,296,180,299,302],{},[150,294,295],{},"cg readers Cart.items",[150,297,298],{},"cg writers Cart::$items",[150,300,301],{},"cg writers App\\Cart::$items"," list them. The facts Laravel\nreads for model attributes and relations are unchanged, so every other edge stays the same. This was checked on koel\nand laravel.io.",[141,304,306],{"id":305},"column-writes-by-mass-assignment-177","Column writes by mass assignment (#177)",[146,308,309,254,312,254,315,254,318,321,322,325,326,329,330,332,333,335,336,339,340,343],{},[150,310,311],{},"$book->update($request->validated())",[150,313,314],{},"Book::create($data)",[150,316,317],{},"$book->fill(...)",[150,319,320],{},"new Book($data)"," followed by ",[150,323,324],{},"save()"," and a query-builder ",[150,327,328],{},"->update($data)"," write columns whose names are not in the call. cg takes the keys from the request array the argument carries and records ",[150,331,183],{}," at ",[150,334,220],{},", so ",[150,337,338],{},"cg writers books.age_rating"," and ",[150,341,342],{},"cg routes --reaches books.age_rating"," list the route that writes the column.",[345,346,347,360],"table",{},[348,349,350],"thead",{},[351,352,353,357],"tr",{},[354,355,356],"th",{},"argument",[354,358,359],{},"keys",[361,362,363,396,417,432,445],"tbody",{},[351,364,365,377],{},[366,367,368,254,371,254,374],"td",{},[150,369,370],{},"$request->validated()",[150,372,373],{},"$request->safe()",[150,375,376],{},"$request->validate()",[366,378,379,380,383,384,387,388,391,392,395],{},"the FormRequest ",[150,381,382],{},"rules()"," keys, or the inline ",[150,385,386],{},"validate([...])"," keys, top-level only (",[150,389,390],{},"items.*.qty"," is ",[150,393,394],{},"items",")",[351,397,398,410],{},[366,399,400,180,403,406,407],{},[150,401,402],{},"->only([...])",[150,404,405],{},"->except([...])"," on the request or on ",[150,408,409],{},"safe()",[366,411,412,413,416],{},"the literal keys; for ",[150,414,415],{},"except",", the request's keys minus them",[351,418,419,422],{},[366,420,421],{},"a local or a parameter holding one of these",[366,423,424,425,428,429,395],{},"followed through assignments and call arguments (",[150,426,427],{},"$service->save($book, $request->validated())"," writes from ",[150,430,431],{},"save",[351,433,434,442],{},[366,435,436,254,439],{},[150,437,438],{},"array_merge($request->validated(), [...])",[150,440,441],{},"[...$request->validated(), 'k' => v]",[366,443,444],{},"both key sets",[351,446,447,464],{},[366,448,449,254,452,254,455,254,458,254,461],{},[150,450,451],{},"$request->all()",[150,453,454],{},"input()",[150,456,457],{},"post()",[150,459,460],{},"query()",[150,462,463],{},"json()",[366,465,466,469,470,473],{},[150,467,468],{},"heuristic",": the model's ",[150,471,472],{},"$fillable"," keys (no rules are consulted, any input key may arrive)",[146,475,476,477,180,480,180,483,486,487,490,491,494,495,497,498,180,501,504],{},"Receivers: a model instance, ",[150,478,479],{},"Model::create(...)",[150,481,482],{},"updateOrCreate",[150,484,485],{},"firstOrCreate"," (the values array), a relation (",[150,488,489],{},"$book->reviews()->create(...)","), ",[150,492,493],{},"new Model($data)"," when the same function calls ",[150,496,324],{}," on it, and ",[150,499,500],{},"Model::where(...)->update(...)",[150,502,503],{},"DB::table('books')->update(...)",".",[146,506,507,508,510,511,514,515,518,519,522,523,526,527,530,531,533,534,180,537,540,541,544,545,254,548,551,552,554,555,558,559,561,562,504],{},"Then the model's mass-assignment rules apply. A key outside a declared ",[150,509,472],{}," gets no edge (a rule key ",[150,512,513],{},"reviewer_note"," that ",[150,516,517],{},"Book::$fillable"," does not list is validated but never written). ",[150,520,521],{},"$guarded"," keys are dropped, ",[150,524,525],{},"$guarded = []"," keeps every rule key, and ",[150,528,529],{},"$guarded = ['*']"," without ",[150,532,472],{}," keeps none. ",[150,535,536],{},"forceFill",[150,538,539],{},"forceCreate"," ignore both, and query-builder writes (",[150,542,543],{},"->update"," on a builder, ",[150,546,547],{},"insert",[150,549,550],{},"upsert",") never consult ",[150,553,472],{},". ",[150,556,557],{},"cg plan check"," still reports a new column that ",[150,560,472],{}," lacks as ",[150,563,564],{},"model_fillable",[146,566,567,568,264,571,574,575,264,578,581,582,585],{},"The edge has ",[150,569,570],{},"attrs.via",[150,572,573],{},"update(validated())",") and ",[150,576,577],{},"attrs.keys_from",[150,579,580],{},"[\"UpdateBookRequest::rules\", \"Book::$fillable\"]","); ",[150,583,584],{},"cg node"," prints them:",[587,588,594],"pre",{"className":589,"code":591,"language":592,"meta":593},[590],"language-text","$ cg node 'App\\Http\\Controllers\\Admin\\BookController::update' --db out\u002Fapi.db\n  outgoing (9):\n    -> WRITES_COLUMN column:books.age_rating  @app\u002FHttp\u002FControllers\u002FAdmin\u002FBookController.php:30 resolved  via update(validated()) keys from UpdateBookRequest::rules ∩ Book::$fillable\n","text","",[150,595,591],{"__ignoreMap":593},[146,597,598,599,602,603,606,607,504],{},"Keys built at run time stay out (",[150,600,601],{},"$data[$field] = ..."," in a loop, ",[150,604,605],{},"Arr::only($data, $allowed)"," with a computed list). See ",[608,609,611],"a",{"href":610},"\u002Fdocs\u002Flimitations#plans-value-facts-and-the-visual-view","limitations",[141,613,615],{"id":614},"database-connections-on-table-edges-179","Database connections on table edges (#179)",[146,617,618,619,254,622,254,625,254,627,629,630,633],{},"Every ",[150,620,621],{},"READS_TABLE",[150,623,624],{},"WRITES_TABLE",[150,626,179],{},[150,628,183],{}," edge from Laravel code has ",[150,631,632],{},"attrs.connection",", the database connection the query goes to. It is taken from, in order:",[635,636,637,653,660],"ol",{},[203,638,639,640,254,643,254,646,321,649,652],{},"the query's own selection, in the same chain or on the same builder variable: ",[150,641,642],{},"Book::on($name)->where(...)",[150,644,645],{},"DB::connection($name)->table('books')",[150,647,648],{},"$book->setConnection($name)",[150,650,651],{},"$book->update(...)",";",[203,654,655,656,659],{},"the model's ",[150,657,658],{},"$connection"," property;",[203,661,662,665,666,504],{},[150,663,664],{},"database.default"," from ",[150,667,668],{},"config\u002Fdatabase.php",[146,670,671,674,675,678,679,682,683,686,687,690,691,695],{},[150,672,673],{},"$name"," can be a literal, a ",[150,676,677],{},"config()"," key, a method that returns a name registered with ",[150,680,681],{},"Config::set('database.connections.{$name}', ...)",", or an interpolated string. A dynamic name keeps its pattern (",[150,684,685],{},"legacy_{store.id}","); a name that cannot be resolved (a parameter, a property set from elsewhere) is ",[150,688,689],{},"?",". Mass-assignment writes (",[608,692,694],{"href":693},"#column-writes-by-mass-assignment-177","above",") get the same attribute from the model they write.",[146,697,698,699,702,703,706,707,264,710,254,713,254,716,254,719,722,723,726,727,339,730,733],{},"Edges on the default connection carry the attribute too, so ",[150,700,701],{},"--connection mysql"," works. Other attributes: ",[150,704,705],{},"connection_default"," (the project default), ",[150,708,709],{},"connection_via",[150,711,712],{},"Book::on",[150,714,715],{},"DB::connection",[150,717,718],{},"setConnection",[150,720,721],{},"Shipment::$connection","; absent on the default), ",[150,724,725],{},"connection_from"," (the method that returns a dynamic name), ",[150,728,729],{},"connection_model",[150,731,732],{},"connection_fallback"," (the model and the connection it would have used without the override).",[587,735,738],{"className":736,"code":737,"language":592,"meta":593},[590],"$ cg impact 'ArchiveService::legacyBooks' --no-paths --db out\u002Fapi.db\ntargets: ['method:App\\\\Services\\\\ArchiveService::legacyBooks']\nconnections: legacy_{store.id} (Book::on via ArchiveService::legacyConnection, app\u002FServices\u002FArchiveService.php:13; Book default: mysql)\ncallers (transitive): 1\n  d=1 [Http\u002FControllers\u002FAdmin] App\\Http\\Controllers\\Admin\\ArchiveController::index\nentry points: 1\n  http_route       GET \u002Fv1\u002F{store}\u002Fadmin\u002Farchive  conf=resolved\n",[150,739,737],{"__ignoreMap":593},[146,741,742,254,745,254,748,339,751,754,755,758,759,762,763,767,768,771,772,776,777,264,779,184],{},[150,743,744],{},"reaches",[150,746,747],{},"routes --reaches",[150,749,750],{},"writers",[150,752,753],{},"readers"," add ",[150,756,757],{},"conn=\u003Cname>"," to an edge that is not on the default connection, and ",[150,760,761],{},"--connection NAME"," keeps only the edges on one connection (",[608,764,766],{"href":765},"\u002Fdocs\u002Fcli#database-connections","CLI","). A table used on several connections stays one node; its ",[150,769,770],{},"attrs.connections"," counts the edges per connection (",[608,773,775],{"href":774},"\u002Fdocs\u002Fexternal#tables-on-several-connections","external systems","). A connection chosen at run time from data is ",[150,778,689],{},[608,780,611],{"href":781},"\u002Fdocs\u002Flimitations#index-and-answers",[141,783,785],{"id":784},"inline-guards","Inline guards",[146,787,788,791,792,795,796,799,800,264,803,254,806,254,809,254,812,184],{},[150,789,790],{},"cg routes"," lists access checks a Laravel action runs before its own work on an ",[150,793,794],{},"inline:"," line, separate from route middleware. ",[150,797,798],{},"--json"," stores them on ",[150,801,802],{},"inline_guards",[150,804,805],{},"name",[150,807,808],{},"kind",[150,810,811],{},"at",[150,813,814],{},"conditional",[146,816,817],{},"Counted:",[200,819,820,858,868,884,924],{},[203,821,822,254,825,180,828,180,831,834,835,254,838,180,841,844,845,180,848,180,851,854,855,504],{},[150,823,824],{},"$this->authorize(...)",[150,826,827],{},"Gate::authorize",[150,829,830],{},"Gate::denies",[150,832,833],{},"Gate::allows"," with ",[150,836,837],{},"abort(403)",[150,839,840],{},"abort_if",[150,842,843],{},"abort_unless"," of ",[150,846,847],{},"can",[150,849,850],{},"hasPermission",[150,852,853],{},"hasRole",", and ",[150,856,857],{},"$request->user()->cannot(...)",[203,859,860,861,864,865,504],{},"A FormRequest ",[150,862,863],{},"authorize()"," that does more than ",[150,866,867],{},"return true",[203,869,870,873,874,877,878,180,881,883],{},[150,871,872],{},"$this->middleware('can:...')"," in the constructor and ",[150,875,876],{},"HasMiddleware::middleware()",", including ",[150,879,880],{},"only",[150,882,415],{},", copied onto that controller's routes.",[203,885,886,887,180,890,893,894,180,897,900,901,904,905,908,909,912,913,254,916,919,920,923],{},"A call on the same class, trait, or parent (two calls deep) that aborts ",[150,888,889],{},"401",[150,891,892],{},"403"," or throws ",[150,895,896],{},"AuthorizationException",[150,898,899],{},"AccessDeniedHttpException"," before any write. The access-check heuristic or ",[150,902,903],{},"auth.extra_patterns"," names that method when it rejects, or when the caller aborts on its result (",[150,906,907],{},"abort_unless($this->ensureAccess($order), 403)","). A discarded result does not count: ",[150,910,911],{},"Gate::allows()"," with no abort, ",[150,914,915],{},"return Gate::allows(...)",[150,917,918],{},"can()"," stored for a template, or ",[150,921,922],{},"$this->ensureAccess($order)"," called and ignored. A check after a write does not count.",[203,925,926,927,930,931,180,934,844,937,180,939,942,943,946,947,949,950,953],{},"A shared-secret compare: ",[150,928,929],{},"hash_equals"," or ",[150,932,933],{},"===",[150,935,936],{},"!==",[150,938,677],{},[150,940,941],{},"env()"," against a request header or input, aborting on mismatch. Kind ",[150,944,945],{},"secret",". A ",[150,948,933],{}," between two request values is not a secret check, and ",[150,951,952],{},"=="," is not either.",[146,955,956,957,554,959,962,963,966],{},"A check inside a branch is ",[150,958,814],{},[150,960,961],{},"--unguarded"," hides a route with an unconditional inline check. ",[150,964,965],{},"--unguarded --strict"," uses route middleware only. The walk stops at the action's first write. Kernel middleware groups are still not copied onto each route.",[141,968,970],{"id":969},"request-keys-the-handler-reads","Request keys the handler reads",[146,972,973,974,977,978,254,980,254,983,986],{},"A route's ",[150,975,976],{},"attrs.request.keys"," holds validated keys (FormRequest ",[150,979,382],{},[150,981,982],{},"$request->validate",[150,984,985],{},"Validator::make",") and keys the handler reads. Reads are known but never required. These reads count, anywhere in the handler and one level into a non-public method of the same controller:",[200,988,989,1030,1038,1044],{},[203,990,991,180,994,180,997,180,1000,180,1003,180,1006,180,1009,180,1012,180,1015,180,1018,180,1021,180,1024,339,1027,652],{},[150,992,993],{},"$request->input",[150,995,996],{},"query",[150,998,999],{},"get",[150,1001,1002],{},"post",[150,1004,1005],{},"string",[150,1007,1008],{},"integer",[150,1010,1011],{},"float",[150,1013,1014],{},"boolean",[150,1016,1017],{},"date",[150,1019,1020],{},"enum",[150,1022,1023],{},"has",[150,1025,1026],{},"filled('k')",[150,1028,1029],{},"request('k')",[203,1031,1032,180,1035,652],{},[150,1033,1034],{},"$request->only([...])",[150,1036,1037],{},"except([...])",[203,1039,1040,1041,652],{},"the property form ",[150,1042,1043],{},"$request->search",[203,1045,1046,180,1049,264,1052,490,1055,264,1058,1061,1062,1065,1066,504],{},[150,1047,1048],{},"paginate()",[150,1050,1051],{},"simplePaginate()",[150,1053,1054],{},"page",[150,1056,1057],{},"cursorPaginate()",[150,1059,1060],{},"cursor","), and ",[150,1063,1064],{},"per_page"," when it is read or passed as ",[150,1067,1068],{},"$perPage",[146,1070,1071,1074,1075,1078,1079,1082,1083,1086],{},[150,1072,1073],{},"cg link"," reports ",[150,1076,1077],{},"request_unknown_field"," for a query key only when the route has explicit validation and the key is neither validated nor read (severity ",[150,1080,1081],{},"low","; an unknown body key stays ",[150,1084,1085],{},"medium","). A route with reads only gives no unknown-key findings.",[141,1088,1090],{"id":1089},"outbound-http","Outbound HTTP",[146,1092,1093,1096,1097,930,1100,1103,1104,1107,1108,1111,1112,1115,1116,1118],{},[150,1094,1095],{},"Illuminate\\Support\\Facades\\Http",", an injected ",[150,1098,1099],{},"Illuminate\\Http\\Client\\Factory",[150,1101,1102],{},"PendingRequest",", and Guzzle\n",[150,1105,1106],{},"Client"," become ",[150,1109,1110],{},"http:"," client endpoints (",[150,1113,1114],{},"HTTP_CALLS","). ",[150,1117,1073],{}," matches them to another backend's routes.",[146,1120,1121,1122,180,1124,180,1126,180,1129,180,1132,180,1135,854,1138,1141,1142,1145,1146,332,1149,554,1151,254,1154,254,1157,254,1160,254,1163,254,1166,1169,1170,339,1173,1176,1177,184],{},"Detected calls: ",[150,1123,999],{},[150,1125,1002],{},[150,1127,1128],{},"put",[150,1130,1131],{},"patch",[150,1133,1134],{},"delete",[150,1136,1137],{},"head",[150,1139,1140],{},"send($method, $url)"," \u002F Guzzle\n",[150,1143,1144],{},"request($method, $uri)"," when the verb is a literal or a small set of literals from a parameter. A verb that does\nnot resolve is ",[150,1147,1148],{},"ANY",[150,1150,468],{},[150,1152,1153],{},"baseUrl()",[150,1155,1156],{},"withHeaders",[150,1158,1159],{},"withToken",[150,1161,1162],{},"withBody",[150,1164,1165],{},"asJson",[150,1167,1168],{},"acceptJson",",\n",[150,1171,1172],{},"timeout",[150,1174,1175],{},"retry"," are read along the chain. A helper whose path or verb is a parameter is expanded at its\ncall sites (",[150,1178,245],{},[146,1180,1181,1182,1185,1186,1169,1189,254,1192,1195,1196,1199,1200,1203,1204,254,1207,1210,1211,1214,1215,1218,1219,1221,1222,1169,1225,1228,1229,254,1232,254,1235,1238,1239,1242,1243,254,1246,254,1249,1169,1252,184],{},"SendGrid, Mailgun, Postmark, Resend, Twilio and Vonage SDK clients (",[150,1183,1184],{},"$client = new \\SendGrid($key)"," then ",[150,1187,1188],{},"->send()",[150,1190,1191],{},"Mailgun::create",[150,1193,1194],{},"new Client($sid, $token)"," ",[150,1197,1198],{},"->messages->create",", ...) and Laravel mailers (",[150,1201,1202],{},"config\u002Fmail.php"," +\n",[150,1205,1206],{},"config\u002Fservices.php",[150,1208,1209],{},"Mail::"," callers, notification ",[150,1212,1213],{},"via()"," channels) are not client endpoints: they are\n",[150,1216,1217],{},"external:saas:\u003Cprovider>"," systems (",[608,1220,38],{"href":39},"). So are MessageBird and Plivo clients, ",[150,1223,1224],{},"minishlink\u002Fweb-push",[150,1226,1227],{},"edamov\u002Fpushok",", Laravel FCM \u002F APNs notification channels, ",[150,1230,1231],{},"kreait\u002Ffirebase-php",[150,1233,1234],{},"renoki-co\u002Fphp-k8s",[150,1236,1237],{},"docker-php",", aws-sdk-php\n",[150,1240,1241],{},"KmsClient"," and Google Secret Manager (",[150,1244,1245],{},"external:gcp:\u003Cservice>",[150,1247,1248],{},"external:k8s:\u003Capi-group>",[150,1250,1251],{},"external:docker:\u003Ctarget>",[150,1253,1254],{},"external:aws:kms",[146,1256,1257,1258,1261,1262,180,1265,1169,1268,1270,1271,1274,1275,254,1277,1169,1280,254,1283,339,1286,1289,1290,1292,1293,930,1296,1299,1300,1303,1304,1306,1307,1195,1310,1313,1314,335,1317,1319,1320,1323,1324,1326,1327,1330,1331,1334,1335,1337,1338,254,1341,254,1344,254,1347,1350,1351,1354,1355,1358,1359,254,1362,1365,1366,1369,1370,254,1373,1376,1377,1185,1380,1383,1384,1387,1388,1391,1392,1395,1396,1399],{},"A constructor-promoted or assigned ",[150,1259,1260],{},"$this->baseUrl"," is followed from the container (",[150,1263,1264],{},"singleton",[150,1266,1267],{},"bind",[150,1269,228],{}," inside the provider, ",[150,1272,1273],{},"when()->needs()->give()",") through ",[150,1276,677],{},[150,1278,1279],{},"config()->get()",[150,1281,1282],{},"Config::get()",[150,1284,1285],{},"$app['config']->get()",[150,1287,1288],{},"$app->make('config')->get()"," to ",[150,1291,941],{},". A config array\n(",[150,1294,1295],{},"$cfg = config('services.payments')",[150,1297,1298],{},"->get('services.payments', [])",", then ",[150,1301,1302],{},"$cfg['base_url']",") resolves\nthe same way; a sibling key such as ",[150,1305,945],{}," is not read. The endpoint gets ",[150,1308,1309],{},"origin_kind",[150,1311,1312],{},"env"," and\n",[150,1315,1316],{},"attrs.base",[150,1318,1073],{}," strips the base path. The sample value comes from ",[150,1321,1322],{},".env.example"," or an ",[150,1325,941],{},"\ndefault. ",[150,1328,1329],{},".env"," is not read, an empty example value is shown as the env name only, and a value that is not\na URL is not stored. A relative ",[150,1332,1333],{},"Http::get('\u002Fpath')"," stays relative unless ",[150,1336,1153],{}," was set.\n",[150,1339,1340],{},"rawurlencode",[150,1342,1343],{},"urlencode",[150,1345,1346],{},"trim",[150,1348,1349],{},"strval",", a ",[150,1352,1353],{},"(string)"," cast and ",[150,1356,1357],{},"Str::of(...)->toString()"," are\ntransparent, so a path segment keeps the variable's last name (",[150,1360,1361],{},"{paymentId}",[150,1363,1364],{},"$order->id"," -> ",[150,1367,1368],{},"{id}",").\nLiteral array bodies (",[150,1371,1372],{},"post($url, ['order_id' => ...])",[150,1374,1375],{},"withBody(json_encode([...]))",", and\n",[150,1378,1379],{},"$json = json_encode($payload)",[150,1381,1382],{},"withBody($json)"," or Guzzle ",[150,1385,1386],{},"'body' => $json",") are ",[150,1389,1390],{},"body_keys","\nin the same shape the TypeScript extractor writes. ",[150,1393,1394],{},"json_encode"," is unwrapped once, after assignments in the same function, and the inner variable is followed\nthrough a helper parameter. A variable with no assignment stays opaque. ",[150,1397,1398],{},"cg api-calls"," prints\nthose keys under the call site.",[587,1401,1405],{"className":1402,"code":1403,"language":1404,"meta":593,"style":593},"language-php shiki shiki-themes cg-light cg-light cg-dark","return $this->http->send($method, rtrim($this->baseUrl, '\u002F') . $path);\n","php",[150,1406,1407],{"__ignoreMap":593},[1408,1409,1412],"span",{"class":1410,"line":1411},"line",1,[1408,1413,1403],{},[146,1415,1416,1419,1420,1423],{},[150,1417,1418],{},"Http::fake(['*\u002Fpayments' => ...])"," in a feature test links the test to the client method (",[150,1421,1422],{},"TEST_HTTP","). It is\nnot an application call.",[146,1425,1426,1427,339,1430,1433,1434,1195,1436,1439],{},"Symfony HttpClient, ",[150,1428,1429],{},"curl_*",[150,1431,1432],{},"file_get_contents"," are not client endpoints. A host known only at run time is\nkept with ",[150,1435,1309],{},[150,1437,1438],{},"unknown"," and is not matched by host.",[141,1441,1443],{"id":1442},"route-attributes","Route attributes",[146,1445,1446,1447,1450,1451,554,1454,339,1457,1460,1461,1464,1465,1468,1469,180,1472,180,1475,180,1478,180,1481,180,1484,1464,1487,180,1490,180,1493,1496,1497,180,1499,1502,1503,1505,1506,391,1509,1512,1513,1516,1517,1520,1521,184],{},"spatie\u002Flaravel-route-attributes on a controller are routes, with the same ",[150,1448,1449],{},"route:\u003CMETHOD> \u003Curi>"," nodes as\n",[150,1452,1453],{},"routes\u002F*.php",[150,1455,1456],{},"#[Prefix('api')]",[150,1458,1459],{},"#[Middleware('api')]"," on the class combine with ",[150,1462,1463],{},"#[Prefix]"," \u002F\n",[150,1466,1467],{},"#[Middleware]"," on the method. ",[150,1470,1471],{},"#[Get]",[150,1473,1474],{},"#[Post]",[150,1476,1477],{},"#[Put]",[150,1479,1480],{},"#[Patch]",[150,1482,1483],{},"#[Delete]",[150,1485,1486],{},"#[Options]",[150,1488,1489],{},"#[Head]",[150,1491,1492],{},"#[Any]",[150,1494,1495],{},"#[Route]"," supply the path, and ",[150,1498,805],{},[150,1500,1501],{},"middleware"," arguments are the route name and\nextra middleware. The same method and path in ",[150,1504,1453],{}," stays one route. Inline guards on the action\napply here too.\n",[150,1507,1508],{},"Route::webhooks('payments\u002Fhooks', 'payments')",[150,1510,1511],{},"POST \u002Fpayments\u002Fhooks"," for spatie\u002Flaravel-webhook-client\nwhen that name is in ",[150,1514,1515],{},"config\u002Fwebhook-client.php",". A controller that extends Cashier's webhook controller, or\na subclass of one, receives one event per ",[150,1518,1519],{},"handle\u003CEvent>"," method\n(",[608,1522,1524],{"href":1523},"\u002Fdocs\u002Fprotocols#webhook-verification","Webhook verification",[1526,1527,1528],"style",{},"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);}",{"title":593,"searchDepth":1530,"depth":1531,"links":1532},4,2,[1533,1534,1535,1536,1537,1538,1539],{"id":143,"depth":1531,"text":144},{"id":305,"depth":1531,"text":306},{"id":614,"depth":1531,"text":615},{"id":784,"depth":1531,"text":785},{"id":969,"depth":1531,"text":970},{"id":1089,"depth":1531,"text":1090},{"id":1442,"depth":1531,"text":1443},"md",{},true,{"title":79,"description":593},"7WRdNQ01l29C9h46LDNO3rVoNR0j-eWX_ZNxAVNd-UA",[1546,1548],{"title":75,"path":76,"stem":77,"description":1547,"children":-1},"cg parity compares two graphs of the same app on two platforms (an iOS app in Swift \u002F SwiftUI\nand its Android port in Kotlin \u002F Compose). It lists types, functions, enum cases and constants\nof the source graph that have no counterpart in the target.",{"title":83,"path":84,"stem":85,"description":593,"children":-1},1792170235484]