diff --git a/en/extending-modx/tutorials/using-custom-database-tables.md b/en/extending-modx/tutorials/using-custom-database-tables.md
index 1f314d3ef..bd1ffa2fd 100644
--- a/en/extending-modx/tutorials/using-custom-database-tables.md
+++ b/en/extending-modx/tutorials/using-custom-database-tables.md
@@ -12,7 +12,7 @@ MODX 3 brings PHP Namespaces to your XML Schema and class files, and a new boots
**NOTE**: This was converted from the previous "StoreFinder" example.
-**ALSO NOTE**: This methodology is not backwards compatible to MODX 2.x. This tutorial is intended to be run and used in MODX 3. You can see the equivalent guide for 2.x here: [Using Custom Database Tables](/2.x/en/extending-modx/tutorials/using-custom-database-tables "Using Custom Database Tables")
+**ALSO NOTE**: This methodology is not backwards compatible to MODX 2.x. This tutorial is intended to be run and used in MODX 3. You can see the equivalent guide for 2.x here: [Using Custom Database Tables](/2.x/en/extending-modx/tutorials/using-custom-database-tables "Using Custom Database Tables"). For a shorter upgrade checklist (Composer, `metadata.mysql.php`, `instanceof`, `addPackage`), see [xPDO 3](getting-started/upgrading-to-3.0/xpdo).
## Key Terminology and Standards
diff --git a/en/extending-modx/xpdo/index.md b/en/extending-modx/xpdo/index.md
index bfee308bd..286d27d9b 100644
--- a/en/extending-modx/xpdo/index.md
+++ b/en/extending-modx/xpdo/index.md
@@ -7,7 +7,7 @@ note: "This page is a stub. You can help by expanding it."
xPDO is the object-relational-bridge that is built into MODX. Simply put, it's how MODX connects to the database, and how it interacts with different tables.
-In MODX 2.x, the `modX` class directly extends `xPDO`. While in hindsight that's not the best development pattern, it does mean that whenever you have access to the `modX` instance, you can use any of the `xPDO` methods on it as well.
+In MODX 2.x and 3.x, the `modX` class extends `xPDO`, so any time you have the `modX` instance you can call xPDO methods on it. In MODX 3 that parent is the namespaced `xPDO\xPDO` class loaded through Composer. For upgrade and Extra migration details, see [xPDO 3](getting-started/upgrading-to-3.0/xpdo).
## What is xPDO?
@@ -17,10 +17,10 @@ xPDO is our name for open eXtensions to PDO. It's a light-weight ORB (object-rel
In the context of xPDO, the following terms are important to know:
-- **Packages** are collections of models. In the MODX core, all models are part of the `modx` package, plus there are a few sub-packages like `modx.media` and `modx.package`. To make xPDO aware of the models in a package, it needs to be registered with `$xpdo->addPackage()`.
+- **Packages** are collections of models. In the MODX 3 core, models live under namespaces such as `MODX\Revolution` (plus sub-packages like Sources and Transport). Register a package with `$xpdo->addPackage()` (and a `$namespacePrefix` when you use PSR-4).
- **Models** are classes that represent a specific database table. They are the abstraction you will use most often; rather than interacting with SQL directly, you load a model, adjust its properties, and save it.
-- **Schemas** are XML files that define the different models that are available in a package, and what their fields (properties) are. They are used only in development, during which they will be processed (typically called being "built") into the model classes and maps.
-- **Maps** are PHP files containing arrays that define the metadata for packages and schemas. They are in the database driver-specific model directory (e.g. `model/modx/mysql/modresource.map.inc.php`). These files are not typically managed manually, instead they are generated from a schema file.
+- **Schemas** are XML files that define the different models that are available in a package, and what their fields (properties) are. They are used only in development, during which they will be processed (typically called being "built") into the model classes and maps. In MODX 3 set `version="3.0"` and put the PHP namespace in the `package` attribute.
+- **Maps** are PHP metadata for packages and schemas. In MODX 3 / xPDO 3 a package ships `metadata.{dbtype}.php` (with a `class_map`) plus platform files under a driver folder (for example `mysql/`). Older 2.x docs often show only `*.map.inc.php` files; regenerate with schema `version="3.0"` when you target MODX 3.
There are a lot more things to learn about xPDO, but if you understand these 4 you have a solid foundation to make sense of the rest of the documentation.
diff --git a/en/getting-started/upgrading-to-3.0/breaking-changes.md b/en/getting-started/upgrading-to-3.0/breaking-changes.md
index 9062a6d2d..140ec7eb8 100644
--- a/en/getting-started/upgrading-to-3.0/breaking-changes.md
+++ b/en/getting-started/upgrading-to-3.0/breaking-changes.md
@@ -15,6 +15,7 @@ The biggest breaking changes can be summarised as follows:
- [It's no longer possible to use a custom core folder/path](getting-started/upgrading-to-3.0/core-folder)
- [sqlsrv support has been removed](getting-started/upgrading-to-3.0/sqlsrv)
- [A large number of (previously unnamespaced) classes have been renamed and moved](getting-started/upgrading-to-3.0/class-names), including processors and model classes.
+- [xPDO 3 ships via Composer with PSR-4 models; migrate custom packages](getting-started/upgrading-to-3.0/xpdo)
- [All processors have been renamed, including base processors](getting-started/upgrading-to-3.0/processors)
- [modAction and related functionality has been removed](getting-started/upgrading-to-3.0/actions)
- modRestClient has been removed [#15781](https://github.com/modxcms/revolution/pull/15781) and has been [replaced with a new PSR-7/17/18 HTTP service](extending-modx/services/http)
diff --git a/en/getting-started/upgrading-to-3.0/class-names.md b/en/getting-started/upgrading-to-3.0/class-names.md
index 7dae91297..3462ab890 100644
--- a/en/getting-started/upgrading-to-3.0/class-names.md
+++ b/en/getting-started/upgrading-to-3.0/class-names.md
@@ -45,6 +45,8 @@ This layer of backwards compatibility is likely to be fully removed in MODX 4.0.
| \xPDO\Transport\xPDOTransport | \xPDOTransport |
| \xPDO\Transport\xPDOObjectVehicle | \xPDOObjectVehicle |
+How Composer, PSR-4, `metadata.mysql.php`, and Extra `addPackage` calls fit together: [xPDO 3](getting-started/upgrading-to-3.0/xpdo).
+
### MODX Core & Controllers
| New Class | Old Class |
diff --git a/en/getting-started/upgrading-to-3.0/index.md b/en/getting-started/upgrading-to-3.0/index.md
index c8778ca7b..56c86bd39 100644
--- a/en/getting-started/upgrading-to-3.0/index.md
+++ b/en/getting-started/upgrading-to-3.0/index.md
@@ -19,6 +19,7 @@ After upgrading the core and upgrading your extras, you may encounter some break
- ⚠️ Important: [MODX 3.0 required PHP 7.2; current 3.x (3.2+) requires PHP 8.1+](getting-started/upgrading-to-3.0/requirements)
- ⚠️ Important: [sqlsrv support has been removed](getting-started/upgrading-to-3.0/sqlsrv)
- [A list of breaking changes can be found here](getting-started/upgrading-to-3.0/breaking-changes), most notably [many core classes have been moved and renamed](getting-started/upgrading-to-3.0/class-names)
+- [xPDO 3, Composer, and migrating custom models](getting-started/upgrading-to-3.0/xpdo)
- [The manager language is now dynamic](getting-started/upgrading-to-3.0/manager-language)
- [Various system settings have been removed or changed](getting-started/upgrading-to-3.0/system-settings)
diff --git a/en/getting-started/upgrading-to-3.0/xpdo.md b/en/getting-started/upgrading-to-3.0/xpdo.md
new file mode 100644
index 000000000..aa68776b2
--- /dev/null
+++ b/en/getting-started/upgrading-to-3.0/xpdo.md
@@ -0,0 +1,149 @@
+---
+title: "xPDO 3"
+description: "Composer, PSR-4, and migrating custom models from MODX 2.x to MODX 3 / xPDO 3."
+sortorder: 5
+---
+
+MODX 3 ships **xPDO 3** under `core/vendor/xpdo/` (Composer package `xpdo/xpdo`). The library no longer lives as loose files under `core/xpdo/`. Model classes use PHP namespaces and PSR-4 autoloading.
+
+This page is the upgrade-oriented reference. For a full walkthrough that builds a new Extra from scratch, use [Using Custom Database Tables](extending-modx/tutorials/using-custom-database-tables). For API methods, start at [xPDO](extending-modx/xpdo).
+
+## What changed for you
+
+| Topic | MODX 2 / xPDO 2 | MODX 3 / xPDO 3 |
+| --- | --- | --- |
+| Where xPDO lives | `core/xpdo/` | `core/vendor/xpdo/` (bundled with the release) |
+| Autoload | MODX / xPDO class loaders | Composer `autoload.php` + PSR-4 |
+| Core models | `core/model/modx/*.class.php` | `core/src/Revolution/` under `MODX\Revolution\` |
+| Schema `package` | Short package folder name (`modx`) | PHP namespace (`MODX\Revolution\`) |
+| Base classes | `xPDOObject`, `xPDOSimpleObject` | `xPDO\Om\xPDOObject`, `xPDO\Om\xPDOSimpleObject` |
+| Package metadata | `metadata.mysql.php` plus per-class maps under `mysql/` (schema `version` 1.x) | Same filename, but schema `version="3.0"` metadata with `namespace`, `namespacePrefix`, and a `class_map` for PSR-4 |
+| `addPackage` | Path + package folder | Path + namespaced package + optional `$namespacePrefix` |
+
+`modX` still extends `xPDO\xPDO`, so `$modx->getObject()`, `newQuery()`, and friends stay on the main MODX instance.
+
+## Vendor layout and PSR-4
+
+A normal download or Package Manager upgrade already includes `core/vendor/` and `core/vendor/autoload.php`. You do **not** need a project-level `composer.json` or a manual `composer install` to get xPDO 3. Setup and front controllers load that bundled autoloader. You do not `require` individual xPDO class files.
+
+Composer matters if you develop from a Git checkout of Revolution, rebuild core models, or ship an Extra that manages its own Composer dependencies. Those workflows use the release `composer.json` (or the Extra’s) and write libraries into `core/vendor/`.
+
+MODX core code maps through Composer as well (`"MODX\\": "core/src/"`). That is why the [core folder must stay at `/core/`](getting-started/upgrading-to-3.0/core-folder) in the project root.
+
+## Core model layout
+
+Schemas still live under `core/model/schema/` (for example `modx.mysql.schema.xml`). Generated classes and maps go to `core/src/`:
+
+- Class: `core/src/Revolution/modResource.php` → `MODX\Revolution\modResource`
+- Package metadata: `core/src/Revolution/metadata.mysql.php`
+- Platform maps: `core/src/Revolution/mysql/*.php`
+
+Core rebuild (Git / contributor workflow):
+
+```bash
+composer run-script parse-schema
+```
+
+That runs `core/vendor/bin/xpdo parse-schema` with `--psr4=MODX\\` into `core/src/`. Details: [Building model/schema](contribute/code/tooling/model).
+
+## Loading an Extra package
+
+Register a namespaced model from a component bootstrap (paths vary; `$namespace['path']` is the Extra core path):
+
+```php
+$modx->addPackage(
+ 'ToDo\\Model',
+ $namespace['path'] . 'src/',
+ null,
+ 'ToDo\\'
+);
+```
+
+- First argument: PHP package / namespace segment that holds `metadata.{dbtype}.php`.
+- Second: filesystem root for that PSR-4 prefix (often `.../src/`).
+- Third: table prefix override, or `null` to use the site prefix.
+- Fourth: `$namespacePrefix` so xPDO registers PSR-4 correctly when the package path is nested under that prefix.
+
+After `addPackage` succeeds, use FQCNs:
+
+```php
+$item = $modx->newObject(\ToDo\Model\Task::class);
+$item = $modx->getObject(\ToDo\Model\Task::class, $id);
+```
+
+See [xPDO.addPackage](extending-modx/xpdo/class-reference/xpdo/xpdo.addpackage) for prefix pitfalls.
+
+## Schema and generated files
+
+Minimal MODX 3 schema shape:
+
+```xml
+
+
+
+
+```
+
+Generate classes with your build script or the xPDO CLI (`core/vendor/bin/xpdo parse-schema ...`). Expect:
+
+- `src/Model/Task.php` with `namespace ToDo\Model;`
+- `src/Model/metadata.mysql.php` (`version` ≥ `3.0`, `namespace`, `namespacePrefix`, `class_map`)
+- `src/Model/mysql/Task.php` (platform map)
+
+MODX 2.x Extras already shipped a `metadata.mysql.php`. For MODX 3 regenerate it from a `version="3.0"` schema so it includes the namespace fields and `class_map`. A 2.x metadata file (or a layout that never got a 3.0 metadata rebuild) will not register PSR-4 the same way and can log a package metadata warning.
+
+## Migrating a 2.x Extra model
+
+Work through this checklist for each custom package:
+
+1. **Move classes** into a `src/` tree that mirrors the PHP namespace (`MyExtra\Model\...`).
+2. **Rewrite the schema**: set `package` to the PHP namespace, `version="3.0"`, and namespaced `extends` / relation `class` values (`xPDO\Om\...`, `MODX\Revolution\...` when you relate to core objects).
+3. **Regenerate** maps and classes. Commit `metadata.mysql.php` and the `mysql/` maps your generator writes.
+4. **Update `addPackage`** to the four-argument (or namespaced) form and load it from [`bootstrap.php`](extending-modx/namespaces) when the Extra boots.
+5. **Replace string class keys** in PHP with `::class` or FQCNs in `getObject`, `newObject`, `newQuery`, processors, and vehicle attributes.
+6. **Fix `instanceof` and type hints** to the namespaced classes. Short names like `modResource` or your old `MyObject` are not real PHP classes in 3.x.
+7. **Drop** `require`/`include` of `xpdo.class.php` or per-class model files. Rely on the bundled vendor autoloader + `addPackage`.
+
+### Before / after (core object)
+
+```php
+// MODX 2.x
+$resource = $modx->getObject('modResource', $id);
+if ($resource instanceof modResource) { /* ... */ }
+
+// MODX 3.x
+use MODX\Revolution\modResource;
+
+$resource = $modx->getObject(modResource::class, $id);
+if ($resource instanceof modResource) { /* ... */ }
+```
+
+`$modx->getObject('modResource', $id)` may still resolve through `loadClass` translation and log a deprecation. Prefer the namespaced form. `instanceof modResource` against the old global name is always false. Full alias table: [Changed Class Names](getting-started/upgrading-to-3.0/class-names).
+
+### Before / after (custom package)
+
+```php
+// MODX 2.x
+$modx->addPackage('myextra', MODX_CORE_PATH . 'components/myextra/model/');
+$row = $modx->getObject('myExtraItem', $id);
+
+// MODX 3.x
+$modx->addPackage('MyExtra\\Model', MODX_CORE_PATH . 'components/myextra/src/', null, 'MyExtra\\');
+$row = $modx->getObject(\MyExtra\Model\Item::class, $id);
+```
+
+## xPDO CLI
+
+xPDO 3 exposes `core/vendor/bin/xpdo`. The core uses it from Composer scripts (`parse-schema`). Extras can call the same binary with their schema path and `--psr4=YourPrefix\\`. Wire it into the Extra’s own `composer.json` if you maintain the package with Composer.
+
+## Related pages
+
+- [Using Custom Database Tables](extending-modx/tutorials/using-custom-database-tables) — step-by-step Extra model
+- [Changed Class Names](getting-started/upgrading-to-3.0/class-names) — aliases and `instanceof`
+- [Core folder](getting-started/upgrading-to-3.0/core-folder) — why `/core/` is fixed
+- [Directory structure](getting-started/directory-structure) — `vendor/` and `src/`
+- [xPDO.addPackage](extending-modx/xpdo/class-reference/xpdo/xpdo.addpackage)
+- [Building model/schema](contribute/code/tooling/model) — core schema rebuild
diff --git a/ru/extending-modx/tutorials/using-custom-database-tables.md b/ru/extending-modx/tutorials/using-custom-database-tables.md
index 22a992f6e..1c8d00ecc 100644
--- a/ru/extending-modx/tutorials/using-custom-database-tables.md
+++ b/ru/extending-modx/tutorials/using-custom-database-tables.md
@@ -11,7 +11,7 @@ MODX 3 приносит пространства имён PHP в XML-схему
**ПРИМЕЧАНИЕ**: материал переработан из прежнего примера StoreFinder.
-**ЕЩЁ ПРИМЕЧАНИЕ**: эта методология не обратно совместима с MODX 2.x. Руководство рассчитано на MODX 3. Эквивалент для 2.x: [Using Custom Database Tables](/2.x/en/extending-modx/tutorials/using-custom-database-tables "Using Custom Database Tables")
+**ЕЩЁ ПРИМЕЧАНИЕ**: эта методология не обратно совместима с MODX 2.x. Руководство рассчитано на MODX 3. Эквивалент для 2.x: [Using Custom Database Tables](/2.x/en/extending-modx/tutorials/using-custom-database-tables "Using Custom Database Tables"). Краткий чеклист апгрейда (Composer, `metadata.mysql.php`, `instanceof`, `addPackage`): [xPDO 3](getting-started/upgrading-to-3.0/xpdo).
## Ключевые термины и стандарты
diff --git a/ru/extending-modx/xpdo/index.md b/ru/extending-modx/xpdo/index.md
index 7de1d3b80..fa07f15d5 100644
--- a/ru/extending-modx/xpdo/index.md
+++ b/ru/extending-modx/xpdo/index.md
@@ -5,7 +5,7 @@ translation: "extending-modx/xpdo"
xPDO - это объектно-реляционный мост, встроенный в MODX. Проще говоря, это то, как MODX подключается к базе данных и как он взаимодействует с различными таблицами.
-В MODX 2.x, класс `modX` непосредственно расширяет `xPDO`. Хотя в ретроспективе это не лучший шаблон разработки, это означает, что всякий раз, когда у вас есть доступ к экземпляру `modX`, вы можете использовать любой из методов `xPDO` на нем.
+В MODX 2.x и 3.x класс `modX` расширяет `xPDO`, поэтому на экземпляре MODX доступны методы xPDO. В MODX 3 родитель — namespaced-класс `xPDO\xPDO` из Composer. Апгрейд и миграция Extra: [xPDO 3](getting-started/upgrading-to-3.0/xpdo).
## Что такое xPDO?
@@ -19,10 +19,10 @@ xPDO (open eXtensions to PDO) - это легковесная ORB (object-relati
В контексте xPDO важно знать следующие термины:
-- **Packages** - коллекции моделей. В ядре MODX все модели являются частью пакета `modx`, плюс есть несколько подпакетов, таких как`modx.media` и `modx.package`. Чтобы xPDO узнал о моделях в пакете, его необходимо зарегистрировать с помощью `$xpdo->addPackage()`.
+- **Packages** - коллекции моделей. В ядре MODX 3 модели живут в namespaces вроде `MODX\Revolution` (плюс подпакеты Sources, Transport). Регистрируйте пакет через `$xpdo->addPackage()` (и `$namespacePrefix` при PSR-4).
- **Models** - классы, которые представляют конкретную таблицу базы данных. Это абстракция, которую вы будете использовать чаще всего: вместо непосредственного взаимодействия с SQL вы загружаете модель, настраиваете ее свойства и сохраняете.
-- **Schemas** - XML-файлы, которые определяют различные модели, доступные в пакете, и их поля (свойства). Они используются только в разработке, во время которой они будут обрабатываться (обычно называемые «встроенными») в модельных классах и картах.
-- **Maps** - php-файлы, содержащие массивы, которые определяют метаданные для пакетов и схем. Они находятся в директории модели драйвера базы данных (например: `model/modx/mysql/modresource.map.inc.php`). Эти файлы обычно не обрабатываются вручную, а создаются из файла схемы.
+- **Schemas** - XML-файлы, которые определяют различные модели, доступные в пакете, и их поля (свойства). Они используются только в разработке, во время которой они будут обрабатываться (обычно называемые «встроенными») в модельных классах и картах. В MODX 3 укажите `version="3.0"` и PHP-namespace в атрибуте `package`.
+- **Maps** - PHP-метаданные пакетов и схем. В MODX 3 / xPDO 3 пакет отдаёт `metadata.{dbtype}.php` (с `class_map`) и файлы платформы в каталоге драйвера (например `mysql/`). В старых доках 2.x часто фигурируют только `*.map.inc.php`. Для MODX 3 перегенерируйте schema с `version="3.0"`.
Есть еще много вещей, которые нужно узнать о xPDO, но если вы понимаете эти 4, у вас есть прочная основа, чтобы разобраться в остальной части документации.
diff --git a/ru/getting-started/upgrading-to-3.0/breaking-changes.md b/ru/getting-started/upgrading-to-3.0/breaking-changes.md
index db88866f6..0ec137e3a 100644
--- a/ru/getting-started/upgrading-to-3.0/breaking-changes.md
+++ b/ru/getting-started/upgrading-to-3.0/breaking-changes.md
@@ -15,6 +15,7 @@ translation: "getting-started/upgrading-to-3.0/breaking-changes"
- [Больше нельзя использовать свой каталог или путь к core](getting-started/upgrading-to-3.0/core-folder)
- [Поддержка sqlsrv удалена](getting-started/upgrading-to-3.0/sqlsrv)
- [Большое число (ранее без namespace) классов переименовано и перенесено](getting-started/upgrading-to-3.0/class-names), включая процессоры и классы моделей.
+- [xPDO 3 через Composer и PSR-4; миграция кастомных пакетов](getting-started/upgrading-to-3.0/xpdo)
- [Все процессоры переименованы, включая базовые](getting-started/upgrading-to-3.0/processors)
- [modAction и связанный функционал удалены](getting-started/upgrading-to-3.0/actions)
- modRestClient удалён [#15781](https://github.com/modxcms/revolution/pull/15781) и [заменён новым HTTP-сервисом PSR-7/17/18](extending-modx/services/http)
diff --git a/ru/getting-started/upgrading-to-3.0/class-names.md b/ru/getting-started/upgrading-to-3.0/class-names.md
index c44aed059..b6917407c 100644
--- a/ru/getting-started/upgrading-to-3.0/class-names.md
+++ b/ru/getting-started/upgrading-to-3.0/class-names.md
@@ -46,6 +46,8 @@ translation: "getting-started/upgrading-to-3.0/class-names"
| \xPDO\Transport\xPDOTransport | \xPDOTransport |
| \xPDO\Transport\xPDOObjectVehicle | \xPDOObjectVehicle |
+Как связаны Composer, PSR-4, `metadata.mysql.php` и вызовы `addPackage` в Extra: [xPDO 3](getting-started/upgrading-to-3.0/xpdo).
+
### Ядро и процессоры MODX
| Новый класс | Старый класс |
diff --git a/ru/getting-started/upgrading-to-3.0/index.md b/ru/getting-started/upgrading-to-3.0/index.md
index 31102d31d..79d2283b8 100644
--- a/ru/getting-started/upgrading-to-3.0/index.md
+++ b/ru/getting-started/upgrading-to-3.0/index.md
@@ -18,6 +18,7 @@ translation: "getting-started/upgrading-to-3.0"
- ⚠️ Важно: [MODX 3.0 требовал PHP 7.2, текущие 3.x (3.2+) требуют PHP 8.1+](getting-started/upgrading-to-3.0/requirements)
- ⚠️ Важно: [поддержка sqlsrv удалена](getting-started/upgrading-to-3.0/sqlsrv)
- [Список критических изменений](getting-started/upgrading-to-3.0/breaking-changes), в частности [многие классы ядра перенесены и переименованы](getting-started/upgrading-to-3.0/class-names)
+- [xPDO 3, Composer и миграция кастомных моделей](getting-started/upgrading-to-3.0/xpdo)
- [Язык менеджера теперь динамический](getting-started/upgrading-to-3.0/manager-language)
- [Различные системные настройки удалены или изменены](getting-started/upgrading-to-3.0/system-settings)
diff --git a/ru/getting-started/upgrading-to-3.0/xpdo.md b/ru/getting-started/upgrading-to-3.0/xpdo.md
new file mode 100644
index 000000000..23df68e5b
--- /dev/null
+++ b/ru/getting-started/upgrading-to-3.0/xpdo.md
@@ -0,0 +1,150 @@
+---
+title: "xPDO 3"
+description: "Composer, PSR-4 и миграция кастомных моделей с MODX 2.x на MODX 3 / xPDO 3."
+sortorder: 5
+translation: "getting-started/upgrading-to-3.0/xpdo"
+---
+
+В MODX 3 **xPDO 3** лежит в `core/vendor/xpdo/` (пакет Composer `xpdo/xpdo`). Библиотека больше не лежит россыпью в `core/xpdo/`. Классы моделей живут в PHP-namespaces и грузятся через PSR-4.
+
+Эта страница — ориентир для апгрейда. Пошаговая сборка нового Extra: [Использование пользовательских таблиц БД](extending-modx/tutorials/using-custom-database-tables). Справочник API: [xPDO](extending-modx/xpdo).
+
+## Что меняется для вас
+
+| Тема | MODX 2 / xPDO 2 | MODX 3 / xPDO 3 |
+| --- | --- | --- |
+| Где лежит xPDO | `core/xpdo/` | `core/vendor/xpdo/` (входит в релиз) |
+| Autoload | загрузчики MODX / xPDO | Composer `autoload.php` + PSR-4 |
+| Модели ядра | `core/model/modx/*.class.php` | `core/src/Revolution/` в `MODX\Revolution\` |
+| Атрибут `package` в schema | короткое имя пакета (`modx`) | PHP-namespace (`MODX\Revolution\`) |
+| Базовые классы | `xPDOObject`, `xPDOSimpleObject` | `xPDO\Om\xPDOObject`, `xPDO\Om\xPDOSimpleObject` |
+| Метаданные пакета | `metadata.mysql.php` плюс поклассовые карты в `mysql/` (schema `version` 1.x) | Тот же файл, но metadata schema `version="3.0"` с `namespace`, `namespacePrefix` и `class_map` для PSR-4 |
+| `addPackage` | путь + папка пакета | путь + namespaced package + опциональный `$namespacePrefix` |
+
+`modX` по-прежнему расширяет `xPDO\xPDO`, поэтому `$modx->getObject()`, `newQuery()` и остальное остаются на экземпляре MODX.
+
+## Vendor и PSR-4
+
+Обычная загрузка дистрибутива или обновление через Package Manager уже кладёт `core/vendor/` и `core/vendor/autoload.php`. Для получения xPDO 3 **не** нужен свой `composer.json` у сайта и **не** нужен ручной `composer install`. Setup и фронт-контроллеры подключают bundled autoloader. Отдельные файлы классов xPDO подключать не нужно.
+
+Composer нужен, если вы собираете Revolution из Git, пересобираете модели ядра или ведёте Extra со своими Composer-зависимостями. В этих случаях используется `composer.json` релиза (или Extra), а библиотеки пишутся в `core/vendor/`.
+
+Код ядра MODX тоже идёт через Composer (`"MODX\\": "core/src/"`). Поэтому [каталог core должен оставаться `/core/`](getting-started/upgrading-to-3.0/core-folder) в корне проекта.
+
+## Раскладка моделей ядра
+
+Схемы по-прежнему в `core/model/schema/` (например `modx.mysql.schema.xml`). Сгенерированные классы и карты — в `core/src/`:
+
+- Класс: `core/src/Revolution/modResource.php` → `MODX\Revolution\modResource`
+- Метаданные пакета: `core/src/Revolution/metadata.mysql.php`
+- Карты платформы: `core/src/Revolution/mysql/*.php`
+
+Пересборка ядра (Git / contributor):
+
+```bash
+composer run-script parse-schema
+```
+
+Скрипт вызывает `core/vendor/bin/xpdo parse-schema` с `--psr4=MODX\\` в `core/src/`. Подробнее: [Building model/schema](contribute/code/tooling/model).
+
+## Загрузка пакета Extra
+
+Регистрация namespaced-модели из bootstrap компонента (пути зависят от Extra; `$namespace['path']` — core path Extra):
+
+```php
+$modx->addPackage(
+ 'ToDo\\Model',
+ $namespace['path'] . 'src/',
+ null,
+ 'ToDo\\'
+);
+```
+
+- Первый аргумент: PHP-пакет / сегмент namespace, где лежит `metadata.{dbtype}.php`.
+- Второй: корень файловой системы для этого PSR-4 префикса (часто `.../src/`).
+- Третий: свой table prefix или `null` для префикса сайта.
+- Четвёртый: `$namespacePrefix`, чтобы xPDO корректно повесил PSR-4, когда путь пакета вложен под этот префикс.
+
+После успешного `addPackage` работайте с FQCN:
+
+```php
+$item = $modx->newObject(\ToDo\Model\Task::class);
+$item = $modx->getObject(\ToDo\Model\Task::class, $id);
+```
+
+Про подводные камни prefix: [xPDO.addPackage](extending-modx/xpdo/class-reference/xpdo/xpdo.addpackage).
+
+## Schema и сгенерированные файлы
+
+Минимальная schema для MODX 3:
+
+```xml
+
+
+
+
+```
+
+Генерация — вашим build-скриптом или CLI xPDO (`core/vendor/bin/xpdo parse-schema ...`). На выходе ожидайте:
+
+- `src/Model/Task.php` с `namespace ToDo\Model;`
+- `src/Model/metadata.mysql.php` (`version` ≥ `3.0`, `namespace`, `namespacePrefix`, `class_map`)
+- `src/Model/mysql/Task.php` (карта платформы)
+
+В Extra на MODX 2.x `metadata.mysql.php` уже был. Для MODX 3 перегенерируйте его из schema с `version="3.0"`, чтобы появились namespace-поля и `class_map`. Metadata 2.x (или раскладка без пересборки под 3.0) не регистрирует PSR-4 так же и может писать warning по package metadata.
+
+## Миграция модели Extra с 2.x
+
+Пройдите чеклист для каждого кастомного пакета:
+
+1. **Перенесите классы** в дерево `src/`, зеркалящее PHP-namespace (`MyExtra\Model\...`).
+2. **Перепишите schema**: `package` = PHP-namespace, `version="3.0"`, namespaced `extends` и `class` у связей (`xPDO\Om\...`, при связях с ядром — `MODX\Revolution\...`).
+3. **Перегенерируйте** карты и классы. Закоммитьте `metadata.mysql.php` и карты в `mysql/`.
+4. **Обновите `addPackage`** до namespaced-формы и вызывайте его из [`bootstrap.php`](extending-modx/namespaces) при загрузке Extra.
+5. **Замените строковые имена классов** на `::class` или FQCN в `getObject`, `newObject`, `newQuery`, процессорах и атрибутах vehicle.
+6. **Исправьте `instanceof` и type hint’ы** на namespaced-классы. Короткие имена вроде `modResource` или старого `MyObject` в 3.x не являются реальными PHP-классами.
+7. **Уберите** `require`/`include` для `xpdo.class.php` и отдельных model-файлов. Опирайтесь на bundled vendor autoloader и `addPackage`.
+
+### Было / стало (объект ядра)
+
+```php
+// MODX 2.x
+$resource = $modx->getObject('modResource', $id);
+if ($resource instanceof modResource) { /* ... */ }
+
+// MODX 3.x
+use MODX\Revolution\modResource;
+
+$resource = $modx->getObject(modResource::class, $id);
+if ($resource instanceof modResource) { /* ... */ }
+```
+
+`$modx->getObject('modResource', $id)` ещё может отработать через перевод в `loadClass` и записать deprecation в лог. Лучше namespaced-форма. `instanceof modResource` со старым global-именем всегда false. Таблица алиасов: [Изменение имён классов](getting-started/upgrading-to-3.0/class-names).
+
+### Было / стало (свой пакет)
+
+```php
+// MODX 2.x
+$modx->addPackage('myextra', MODX_CORE_PATH . 'components/myextra/model/');
+$row = $modx->getObject('myExtraItem', $id);
+
+// MODX 3.x
+$modx->addPackage('MyExtra\\Model', MODX_CORE_PATH . 'components/myextra/src/', null, 'MyExtra\\');
+$row = $modx->getObject(\MyExtra\Model\Item::class, $id);
+```
+
+## CLI xPDO
+
+В xPDO 3 есть `core/vendor/bin/xpdo`. Ядро вызывает его из Composer-скриптов (`parse-schema`). Extra может вызывать тот же бинарник со своим schema-путём и `--psr4=YourPrefix\\`. При желании пропишите это в `composer.json` пакета.
+
+## Связанные страницы
+
+- [Использование пользовательских таблиц БД](extending-modx/tutorials/using-custom-database-tables) — пошаговая модель Extra
+- [Изменение имён классов](getting-started/upgrading-to-3.0/class-names) — алиасы и `instanceof`
+- [Каталог core](getting-started/upgrading-to-3.0/core-folder) — почему `/core/` фиксирован
+- [Структура каталогов](getting-started/directory-structure) — `vendor/` и `src/`
+- [xPDO.addPackage](extending-modx/xpdo/class-reference/xpdo/xpdo.addpackage)
+- [Building model/schema](contribute/code/tooling/model) — пересборка schema ядра