Locators

Common ways to find an element, ranked. Lazy, auto-waiting, and strict for single-target actions.

PlaywrightPHP Locators
playwright-php.dev

User-first

Call Note
getByRole('button', ['name' => 'Save']) Preferred: ARIA role plus accessible name
getByRole('heading', ['level' => 2]) Headings, by level
getByLabel('Email') Form fields, via their <label>
getByPlaceholder('Search...') Inputs without labels
getByText('Welcome back') Visible text, substring by default
getByText('Welcome', ['exact' => true]) Whole-string match
getByAltText('Company logo') Images, by alt text
getByTitle('Dismiss') The title attribute

Tip. If a locator is hard to write, the page is hard to use: role-first locating doubles as an accessibility audit.

Selectors & chaining

Call Note
getByTestId('cart-total') Escape hatch, for data-testid
locator('.card > h2') CSS, when you must
locator('//button[@type="submit"]') XPath, last resort
$list->getByRole('link') Chain: scope inside any locator
->filter(['hasText' => 'Pending']) Narrow by text
->filter(['has' => $checkbox]) Narrow by descendant locator
->and($other) / ->or($other) Combine conditions

Gotcha. CSS selectors bind to markup, not meaning: they break on refactor. Reach for them after roles, labels, and test ids.

Lists & strictness

Call Note
->first() / ->last() Ends of a match list
->nth(2) Zero-indexed position
->count() How many match right now
->all() Array of locators to iterate
->allTextContents() Extract every matched text
$page->frameLocator('#checkout') Reach into iframes
->screenshot('menu.png') Snapshot just that element

Gotcha. Actions are strict: two matches throw. Disambiguate with filter() or nth(), don't loosen the locator.

Priority order

role → label → placeholder → text → testid → css

Lazy by design

$btn = $page->getByRole('button'); // no DOM touched yet

Deeper reads

PHP 8.2+ · MIT · playwright-php.dev/cheatsheets/locators Not affiliated with Microsoft