---
url: /cookbook/querying-elements-in-document.md
description: >-
  Query WPCE document structures server-side with WPCE\Document::from_post() and
  property-query helper methods.
---

# Querying Elements in Document

You can use the [`WPCE\Document`](https://bitbucket.org/ownbit/ownbit-wpce/src/dev/plugin/includes/WPCE/Document.php)
class to query the document of the current post. It also handles all of the legwork (including caching) so you can
focus on querying the document based on your needs (e.g. with `find_by_property_query()` etc.).

## Example 1: Checking if a page contains a leading element

Sometimes you want to know whether a page contains a certain element or not. For example, you need to know if your page
already contains a leading hero element to otherwise programmatically add a default hero.

```php
function document_has_leading_hero()
{
	$doc = \WPCE\Document::from_post();
	if (empty($doc)) return false;

	$root_node = $doc->get_root_node();
	$first_element = sizeof($root_node->children) > 0 ? $root_node->children[0] : null;
	return !empty($first_element) 
	  && $first_element->id === 'hero' 
	  && ($first_element->visible ?? true);
}
```

## Example 2: Adding a body class based on the first element

Another good example is adding a body class to switch between light and dark header based on the first element:

```php
add_action('pre_get_posts', function () {
  $has_leading_dark_element = false;
  $document = WPCE\Document::from_post();
  
  $dark_elements = ['hero', 'news-hero'];
  
  if (!is_null($document)) {
    $first_child = null;
    foreach ($document->get_root_node()->children as $child) {
      if (($child->visible ?? true) === false) continue;
      $first_child = $child;
      break;
    }
  
    if (!is_null($first_child)) {
      $has_leading_dark_element = in_array($first_child->id, $dark_elements);
    }
  }
  
  add_filter('body_class', fn ($classes) => array_values(array_filter([
    ...$classes,
    $has_leading_dark_element
      ? 'with-header-on-dark'
      : null,
  ])));
})
```

:::tip
The example above is wrapped in the `pre_get_posts` action. Depending on the current point in the WordPress lifecycle,
this might be necessary as the `WPCE\Document::from_post()` methods uses the current global post if no specific other
post is passed (and that might not be available yet!).
:::
