---
title: "Reading records stored in another site"
manual: "TYPO3 Explained"
version: "main"
permalink: "https://docs.typo3.org/permalink/t3coreapi:extbase-cross-site-reading@main"
source: "ExtensionArchitecture/Extbase/CrossSiteAccess/Reading.rst"
rendered: "2026-09-26T10:15:30+00:00"
---

# Reading records stored in another site {#extbase-cross-site-reading}

Two things have to be settled before a query can return records from another
site: **which pages** to read, and **which language** to ask for. This page
covers the pages. The language has
[its own page](https://docs.typo3.org/permalink/t3coreapi:extbase-cross-site-locales@main).

## Naming the storage pages {#extbase-cross-site-reading-naming}

The storage pages of another site are ordinary page UIDs, and the
[storagePid](https://docs.typo3.org/permalink/t3coreapi:extbase-persistence-storagepid@main) configuration accepts them.
Nothing checks that they belong to the current site.

For a setup with matching language configuration this is all it takes:
configure the shared folder as the storagePid in TypoScript, or let an editor
choose it in the **Behavior > Starting point** field of the plugin, and
every query the repository builds reads from there.

> [!TIP]
> **Hint**
>
> Hard-coding a page UID in TypoScript ties the extension to one
> installation, so prefer a [site setting](https://docs.typo3.org/permalink/t3coreapi:sitehandling-settings@main) or a
> plugin FlexForm field that names the page, and read the value from
> `$this->settings` in the controller.

## Overriding the storage pages for one query {#extbase-cross-site-reading-per-query}

Where the storage pages are decided at runtime — different for each visitor,
each plugin instance or each site — the query settings carry the decision
instead:

**EXT:my_extension/Classes/Domain/Repository/ConferenceRepository.php**

```php
<?php

namespace MyVendor\MyExtension\Domain\Repository;

use MyVendor\MyExtension\Domain\Model\Conference;
use TYPO3\CMS\Core\Context\LanguageAspect;
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
use TYPO3\CMS\Extbase\Persistence\Repository;

class ConferenceRepository extends Repository
{
  /**
   * Reads conferences from storage pages that need not belong to the current
   * site, in the language the caller resolved for those pages.
   *
   * @param int[] $storagePageIds
   * @return QueryResultInterface<Conference>
   */
  public function findAllInStorage(
    array $storagePageIds,
    LanguageAspect $languageAspect,
  ): QueryResultInterface {
    $query = $this->createQuery();
    $querySettings = $query->getQuerySettings();

    $querySettings->setStoragePageIds($storagePageIds);
    $querySettings->setLanguageAspect($languageAspect);

    return $query->execute();
  }
}

```

`setStoragePageIds()` replaces the configured storagePid for this one
query. The repository takes both the pages and the language aspect as
arguments, so it makes no assumption about which site either came from. That
keeps it usable from a plugin, a backend module and a command alike.

> [!NOTE]
> `setRespectStoragePage(false)` also makes records from other sites
> reachable, by dropping the page restriction altogether. It is a blunt
> instrument for this purpose: the query then searches the whole table,
> including records from sites you never intended to expose, and including
> records an editor has filed somewhere unrelated. Name the pages you want
> rather than removing the restriction.

## Finding the storage site {#extbase-cross-site-reading-finding-the-site}

Reading the language configuration of the storage site — which the
[next page](https://docs.typo3.org/permalink/t3coreapi:extbase-cross-site-locales@main) needs — means resolving the
`\TYPO3\CMS\Core\Site\Entity\Site` object it belongs to.
`\TYPO3\CMS\Core\Site\SiteFinder` offers three ways in, and the choice
matters:

| Method | Use it when |
| --- | --- |
| `getSiteByIdentifier()` | The storage site is known by name from configuration. This is the most robust option: the identifier is stable, readable in a site setting, and survives page UIDs changing. |
| `getSiteByPageId()` | Only the storage page UID is known. Resolves the site from the page it sits in. |
| `getSiteByRootPageId()` | The root page UID of the storage site is known. |

> [!NOTE]
> **See also**
>
> [Finding a site object with the SiteFinder class](https://docs.typo3.org/permalink/t3coreapi:sitehandling-sitefinder-object@main)
> — full documentation of `\TYPO3\CMS\Core\Site\SiteFinder`.

### What this means for relations {#extbase-cross-site-reading-relations}

Relation queries ignore the storagePid entirely: Extbase sets
`setRespectStoragePage(false)` on them. Relations therefore reach records
the parent query could never have returned, wherever in the page tree they are
stored.

For cross-site reading this works in your favor — a conference in the shared
folder keeps its categories regardless of which site reads it, and you need do
nothing to make that happen. The same mechanism also means a relation can pull
in a record from a storage folder you did not intend to expose, which is worth
knowing when the related table holds site-specific data.

The language of relations is a separate question, covered on the
[next page](https://docs.typo3.org/permalink/t3coreapi:extbase-cross-site-locales-relations@main).
