Skip to content

Commit 926b62b

Browse files
write the watches and edits guide page
1 parent 13fb7fd commit 926b62b

3 files changed

Lines changed: 101 additions & 10 deletions

File tree

docs/user-guide/watch-expressions.md

Lines changed: 0 additions & 9 deletions
This file was deleted.
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
---
2+
title: Watches and Edits
3+
---
4+
5+
[Inspecting variables](./inspect-variables.md) tells you what the code is holding.
6+
This page covers the two things you can do beyond that: watch an expression so its
7+
value is in front of you at every stop, and change a value while the script is
8+
paused.
9+
10+
Underneath, both are the same mechanism — the debugger runs a fragment of PHP
11+
inside your paused request — and that is worth knowing, because it explains the
12+
sharp edges on both.
13+
14+
## Watch expressions
15+
16+
A watch is an expression you hand to your editor once, which it then re-evaluates
17+
every time execution stops and shows alongside the variables. Anything valid in
18+
that scope will do:
19+
20+
```php
21+
$order->getTotal()
22+
count($items)
23+
$user->isActive() && $user->getRole() === 'admin'
24+
$items[$i]['sku']
25+
```
26+
27+
The value refreshes at every stop, so stepping through a loop with
28+
`$items[$i]['sku']` on watch turns "what is this iteration working on" into
29+
something you read rather than something you go digging for.
30+
31+
Watches are the natural companion to stepping. A breakpoint tells you *when*, the
32+
variables panel tells you *what is here*, and a watch tells you *what the thing you
33+
actually care about is doing* — especially when it is buried several levels inside
34+
a structure you would otherwise be expanding by hand at every stop.
35+
36+
### What a watch really is
37+
38+
It is not a read. The debugger evaluates the expression as PHP, in the paused
39+
process, exactly as though the line appeared in your code at that point. Four
40+
consequences follow, and all four can surprise you:
41+
42+
**Side effects are real.** `$collection->pop()` in a watch pops the collection —
43+
every time you stop. An expression that writes to the database writes to the
44+
database. Keep watches to questions, not actions.
45+
46+
**Breakpoints inside a watch are ignored.** The debugger switches breakpoints off
47+
while it evaluates. Watch an expression that calls a function you have a breakpoint
48+
in, and that breakpoint stays silent — which is the right behaviour, since the
49+
alternative is stopping inside your own watch.
50+
51+
**Errors are swallowed.** Error reporting is turned off for the evaluation, so a
52+
warning or notice your expression provokes goes nowhere. If a thrown exception is
53+
what ended it, your editor shows the exception message in place of the value.
54+
55+
**Watches evaluate where execution stopped.** Selecting an outer frame in the call
56+
stack changes what the variables panel shows, but a watch is still evaluated in the
57+
frame the debugger actually paused in. An expression naming a local of the caller
58+
will not resolve just because you have that frame selected.
59+
60+
Most editors also offer a one-off "evaluate expression" box for a question you only
61+
want to ask once. It is the same machinery with the same caveats — the only
62+
difference is that nothing is remembered for the next stop.
63+
64+
## Editing values
65+
66+
You can also change a value while the script is paused. In most editors it is a
67+
double-click on the value in the variables panel, or a "set value" item on its
68+
context menu.
69+
70+
What happens is an assignment, executed in the scope of the frame you have selected
71+
`$retries = 0`, run inside the paused request. Execution then carries on with the
72+
new value, exactly as if the code had put it there.
73+
74+
This is the fastest way to reach a branch you cannot otherwise get to. A retry path
75+
that only runs on the third failure, an error handler that needs a malformed
76+
response, a discount that only applies over a threshold: rather than contriving the
77+
input, stop before the branch and set the value that takes you down it.
78+
79+
Editors usually let you say what type you mean — boolean, integer, float or string
80+
— for the cases where `0` should not become the string `"0"`.
81+
82+
Some edits will simply refuse:
83+
84+
- a **typed property** given something its declared type rejects
85+
- a **readonly property** that has already been set
86+
- **constants**, which cannot be assigned to at all
87+
88+
Your editor reports that the change did not take, though often quietly — if a value
89+
snaps back to what it was, that is what happened.
90+
91+
:::warning[You are changing the run, not the code]
92+
93+
An edit lives in the paused request and nowhere else. The file on disk is untouched
94+
and the value is gone when the request ends.
95+
96+
That cuts both ways. Nothing you do here can damage your source — but a bug you
97+
"fixed" by editing a value is still in the code, and the next request will run it
98+
exactly as before.
99+
100+
:::

sidebars.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const sidebars = {
3737
'user-guide/breakpoints',
3838
'user-guide/step-debugging',
3939
'user-guide/inspect-variables',
40-
'user-guide/watch-expressions',
40+
'user-guide/watches-and-edits',
4141
'user-guide/logging',
4242
'user-guide/error-handling',
4343
],

0 commit comments

Comments
 (0)