PHPackages                             popo/generator - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. popo/generator

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

popo/generator
==============

Plain Old PHP Object (POPO) / Data Structure / Data Transfer Object (DTO) Generator. Convert YAML schema to PHP class.

6.5.0(2y ago)2140.4k↓50%9MITPHPPHP ^8

Since Jul 20Pushed 2y ago1 watchersCompare

[ Source](https://github.com/oliwierptak/popo)[ Packagist](https://packagist.org/packages/popo/generator)[ RSS](/packages/popo-generator/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (13)Versions (79)Used By (9)

POPO
====

[](#popo)

[![Build and run tests](https://github.com/oliwierptak/popo/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/oliwierptak/popo/actions/workflows/main.yml)

**POPO** - "Plain Old Php Object" was inspired by "Plain Old Java Object" (POJO) concept.

POPO generator can also locate, load, validate, and combine schemas to create PHP source code files, representing Arrays / Data Structures / Data Transfer Objects / Doctrine ORM Entities / MongoDB ODM Documents.

POPO Schema can be defined and extended on few levels, and it can be defined in multiple files.

### Examples

[](#examples)

#### Single schema file

[](#single-schema-file)

Simple schema in YAML format, describing properties and relations of POPO objects.

```
#example.popo.yml
$:
  config:
    namespace: App\Example\Readme
    outputPath: tests/

Example:
  Foo:
    property: [
      {name: title}
      {name: bar, type: popo, default: Bar::class}
    ]

  Bar:
    property: [
      {name: title}
    ]
```

#### Multiple schema files

[](#multiple-schema-files)

The same example can be split into multiple files. However, this time, it's the `Bar` that modifies the `Foo` definition.

```
#foo.popo.yml
Example:
  Foo:
    property: [
      {name: title}
    ]
```

```
#bar.popo.yml
Example:
  Foo:
    property: [
      {name: bar, type: popo, default: Bar::class}
    ]

  Bar:
    property: [
      {name: title}
    ]
```

The generated code is the same, but the schema dependencies are inverted.

In both cases, `Foo` object uses `Bar` object as its dependency, and they are both defined under `Example` schema name.

### Generated code usage examples

[](#generated-code-usage-examples)

#### Instantiate data structure from an array.

[](#instantiate-data-structure-from-an-array)

```
use App\Example\Readme\Foo;

$data = [
    'title' => 'A title',
    'bar' => [
        'title' => 'Bar lorem ipsum',
    ],
];

$foo = (new Foo)->fromArray($data);

echo $foo->getTitle();
echo $foo->requireBar()->getTitle();
```

Output:

```
A title
Bar lorem ipsum

```

#### Display hierarchy of objects as an array.

[](#display-hierarchy-of-objects-as-an-array)

```
use App\Example\Readme\Foo;

$foo = (new Foo);
$foo->requireBar()->setTitle('new value');

print_r($foo->toArray());
```

Output:

```
[
    'title' => null,
    'bar' => [
        'title' => 'new value',
    ],
];

```

*Run `bin/popo generate -s tests/fixtures/popo-readme.yml` or `docker-popo generate -s tests/fixtures/popo-readme.yml` to generate files from this example.*

Installation
------------

[](#installation)

```
composer require popo/generator --dev
```

Note: The installation can be skipped when using docker, see *Docker support* section.

Usage
-----

[](#usage)

You can either use it as composer dependency or as docker command.

1. Define schema file, see [tests/fixtures](tests/fixtures/) for examples.
2. Generate POPO files, run:

    - with composer

        ```
        vendor/bin/popo generate -s  -o
        ```
    - with docker

        ```
        docker-popo generate -s  -o
        ```

*For example: `bin/popo generate -s tests/fixtures/popo.yml` or `docker-popo generate -s tests/fixtures/popo.yml`.*

POPO Schema
-----------

[](#popo-schema)

POPO Schema can be defined and extended on few levels- and it can be defined in multiple files.

The schema supports key mapping- inheritance- collections and encapsulation of other POPO objects.

### Schema Definition

[](#schema-definition)

```
$: # file-config, shared configuration for all POPO objects in current schema file
  config:
    namespace: string
    outputPath: string
    namespaceRoot: string|null # if set remaps namespace and outputPath
    extend: string|null # which class POPO objects should extend from
    implement: string|null # which interface POPO objects should implement
    comment: string|null # Class docblock comment
    phpComment: string|null # Generated PHP File docblock comment
    use: array|[] # Import block in generated PHP class
    trait: array|[] # Traits to be used with generated class
    attribute: string|null # Class attributes as string
    attributes: array|[] # Class attributes as key value pairs
    classPluginCollection: array|[]
    phpFilePluginCollection: array|[]
    namespacePluginCollection: array|[]
    propertyPluginCollection: array|[]
    mappingPolicyPluginCollection: array|[]
  default: array # default values
  property: array # shared properties

SchemaName: # schema-config
  $: # shared configuration for all POPO objects in SchemaName, in all schema files
    config:
      namespace: string
      outputPath: string
      namespaceRoot: string|null
      extend: string|null
      implement: string|null
      comment: string|null
      phpComment: string|null
      use: array|[]
      trait: array|[]
      attribute: string|null,
      attributes: array|[]
      classPluginCollection: array|[]
      phpFilePluginCollection: array|[]
      namespacePluginCollection: array|[]
      propertyPluginCollection: array|[]
      mappingPolicyPluginCollection: array|[]
    default: array
    property: [{
      name: string,
      type:
        type: string
        default: string
        supportedTypes: ['array','bool','float','int','string','mixed','const','popo', 'datetime'],
      comment: string|null,
      default: mixed,
      itemType: string|null,
      itemName: string|null,
      extra: {timezone: ..., format: ...},
      attribute: string|null,
      attributes: array|[]
      mappingPolicy: ['none', 'lower', 'upper', 'camel-to-snake', 'snake-to-camel'],
      mappingPolicyValue: string|null
    }]

  PopoName: # popo-config
    config:
      namespace: string
      outputPath: string
      namespaceRoot: string|null
      extend: string|null
      implement: string|null
      comment: string|null
      phpComment: string|null
      use: array|[]
      trait: array|[]
      attribute: string|null,
      attributes: array|[]
      classPluginCollection: array|[]
      phpFilePluginCollection: array|[]
      namespacePluginCollection: array|[]
      propertyPluginCollection: array|[]
      mappingPolicyPluginCollection: array|[]
    default: array
    property: [{
      name: string,
      type:
        type: string
        default: string
        supportedTypes: ['array','bool','float','int','string','mixed','const','popo', 'datetime'],
      comment: string|null,
      default: mixed,
      itemType: string|null,
      itemName: string|null,
      extra: {timezone: ..., format: ...},
      attribute: string|null,
      attributes: array|[]
      mappingPolicy: ['none', 'lower', 'upper', 'camel-to-snake', 'snake-to-camel'],
      mappingPolicyValue: string|null
    }]
```

### Schema configuration options

[](#schema-configuration-options)

#### `namespace`

[](#namespace)

Defines generated class namespace.

```
config:
  namespace: App\Example
  ...
```

#### `outputPath`

[](#outputpath)

Defines output directory.

```
config:
  outputPath: src/
  ...
```

#### `namespaceRoot`

[](#namespaceroot)

Defines the begging of `outputPath` that should be removed. For example to generated files under `src/Example` with `App\Example` namespace.

```
config:
  namespace: App\Example
  outputPath: src/
  namespaceRoot: App\
  ...
```

#### `extend`

[](#extend)

Which class should the generated class extend from. Must start with **\\** or contain `::class`.

```
config:
  extend: \App\Example\AbstractDto::class
  ...
```

#### `implement`

[](#implement)

Which interface should the generated class implement. Must start with **\\** or contain `::class`.

```
config:
  implement: \App\Example\DtoInterface::class
   ...
```

#### `comment`

[](#comment)

Class comment.

```
config:
  comment: |
    @Document(collection="events")
...
```

#### `phpComment`

[](#phpcomment)

Generated PHP file comment.

```
config:
  phpComment: |
    Auto generated.
    @SuppressWarnings(PHPMD)
    @phpcs:ignoreFile
...
```

#### `use`

[](#use)

Import statements.

```
  config:
    use:
      - Doctrine\ODM\MongoDB\Mapping\Annotations\Document
      - Doctrine\ODM\MongoDB\Mapping\Annotations\Field
      - Doctrine\ODM\MongoDB\Mapping\Annotations\Id
    ...
```

#### `trait`

[](#trait)

Traits statements.

```
  config:
    trait:
      - App\Example\MyTrait
    ...
```

#### `attribute`

[](#attribute)

Class attributes value.

```
  config:
    attribute: |
      #[Doctrine\ORM\Mapping\Entity(repositoryClass: LogEventRepository::class)]
    ...
```

#### `attributes`: `array`

[](#attributes-array)

Attribute value as collection. Supported values:

- `name`
- `value`: `mixed`

```
  config:
    attributes:
      - name: Doctrine\ORM\Mapping\Entity
        value: {repositoryClass: LogEventRepository::class}
    ...
```

#### `classPluginCollection`: `array`

[](#classplugincollection-array)

Additional plugins used to generate methods.

```
  config:
    classPluginCollection:
      - \App\Plugin\ExampleMethodPopoPlugin::class
    ...
```

#### `namespacePluginCollection`: `array`

[](#namespaceplugincollection-array)

Additional plugins used to generate namespace block.

```
  config:
    namespacePluginCollection:
      - \App\Plugin\ExampleNamespacePopoPlugin::class
    ...
```

#### `propertyPluginCollection`: `array`

[](#propertyplugincollection-array)

Additional plugins used to generate properties.

```
  config:
    propertyPluginCollection:
      - \App\Plugin\ExamplePropertyPopoPlugin::class
    ...
```

#### `mappingPolicyPluginCollection`: `array`

[](#mappingpolicyplugincollection-array)

Set of plugins used to map property names, e.g. `fooId` =&gt; `FOO_ID`.

```
  config:
    mappingPolicyPluginCollection:
      - \App\Plugin\SpecialCaseMappingPopoPlugin::class
    ...
```

### Property configuration options

[](#property-configuration-options)

#### `name`

[](#name)

The name of the property. The property related methods will be generated based on this value. For example `getFooBar()`. This is required parameter.

```
property:
  - name: title
    ...
```

#### `type`

[](#type)

Property data type, supported are:

- `array`
- `bool`
- `float`
- `int`
- `string`
- `mixed`
- `const`
- `popo`
- `datetime`

Default property type is `string`.

```
property:
  - name: precision
    type: float
    ...
```

#### `comment`

[](#comment-1)

Docblock value for property and methods.

```
property:
  - name: title
    comment: Lorem ipsum
    ...
```

#### `default: mixed`

[](#default-mixed)

Default value.

```
property:
  - name: items
    default: \App\ExampleInterface::TEST_BUZZ
    ...
```

#### `extra: array`

[](#extra-array)

Used by `datetime` data type. Supported values:

- `format`
- `timezone`

```
property:
    - name: created
      type: datetime
      extra:
          timezone: Europe/Paris
          format: D, d M y H:i:s O
    ...
```

#### `itemType`

[](#itemtype)

Used by `array` data type together with `itemName` element. Describes type of single array element.

```
property:
    - name: products
      type: array
      itemType: Product::class
    ...
```

#### `itemName`

[](#itemname)

Used by `array` data type. Describes name of single array element. For example: `setProducts(array $products)`, `addProduct(Product $item)`.

```
property:
    - name: products
      type: array
      itemName: product
    ...
```

#### `attribute`

[](#attribute-1)

Attribute value.

```
property:
    - name: price
      attribute: |
      #[Doctrine\ORM\Mapping\Column(type: Types::INTEGER)]
    ...
```

#### `attributes`: `array`

[](#attributes-array-1)

Attribute value as collection. Supported values:

- `name`
- `value`: `mixed`

```
property:
    - name: id
      attributes:
        - name: Doctrine\ORM\Mapping\Column
          value: ['length: 255']
    ...
```

#### `mappingPolicy: array`

[](#mappingpolicy-array)

Dynamically remaps property names, for example, `fooId` =&gt; `FOO_ID`. Supported values:

- `none`
- `lower`
- `upper`
- `camel-to-snake`
- `snake-to-camel`

```
property:
  - name: fooId
    mappingPolicy:
      - camel-to-snake
      - upper
    ...
```

#### `mappingPolicyValue`

[](#mappingpolicyvalue)

Statically remaps property names, for example, `fooId` =&gt; `FOO_ID`.

```
property:
  - name: fooId
    mappingPolicyValue: FOO_ID
  ...
```

### Schema Inheritance

[](#schema-inheritance)

The `popo-config` values override `schema-file-config` values- and `schema-file-config` values overwrite `schema-config` values.

On top of that there is a `global-config` that is defined when using `--schemaConfigFilename` parameter.

[![POPO Schema](doc/popo_schema.png)](doc/popo_schema.png)

#### `schema-config`

[](#schema-config)

The configuration was defined as a `Schema` property. It will be used by ***all*** POPO objects in ***all*** files under given schema.

#### `schema-file-config`

[](#schema-file-config)

The configuration was defined as a `SchemaFile` property. It will be used by ***all*** POPO objects in ***current*** file.

#### `popo-config`

[](#popo-config)

The configuration was defined as a `POPO` property. It will be used by one ***specific*** POPO objects in ***current*** file.

See [tests/fixtures](tests/fixtures/) for schema examples.

Property name remapping
-----------------------

[](#property-name-remapping)

POPO can remap property keys names, for example change `foo_id` into `fooId`.

See [Property Name Remapping](README_PROPERTY_NAME_REMAPPING.md) doc.

Pluggable architecture
----------------------

[](#pluggable-architecture)

New functionality can be provided on the command line, or via configuration.

See [Plugins](README_PLUGINS.md) doc.

Doctrine Support
----------------

[](#doctrine-support)

See [Doctrine Support](README_DOCTRINE.md) doc.

Command line options
--------------------

[](#command-line-options)

See [Command Line Options](README_COMMAND_LINE.md) doc.

More Examples
-------------

[](#more-examples)

See [fixtures](tests/fixtures/popo.yml) and [tests](tests/suite/App/PopoTest.php) for more usage examples.

Composer script
---------------

[](#composer-script)

Add popo scrip to composer and run `composer popo` in a project.

```
    "scripts": {
        "popo": [
            "bin/popo generate -s "
        ]
    },
    "scripts-descriptions": {
        "popo": "Generate POPO files"
    }

```

Docker support
--------------

[](#docker-support)

With docker you can generate files without installing `POPO` as dependency in the project.

```
docker container run -it --rm oliwierptak/popo /app/bin/popo

```

You can either run the command directly, or create an alias, e.g.:

```
alias docker-popo='docker container run -it --rm oliwierptak/popo /app/bin/popo ${@}'

```

For example:

```
docker-popo generate -s tests/fixtures/popo.yml
docker-popo report -s tests/fixtures/popo.yml

```

See also: [bin/docker-popo](bin/docker-popo).

PHP version compatibility
-------------------------

[](#php-version-compatibility)

- POPO `v1.x` - PHP 7.2+
- POPO `v2.x` - PHP 7.2+
- POPO `v3.x` - PHP 7.4+
- POPO `v4.x` - PHP 7.4+
- POPO `v5.x` - PHP 7.4+
- POPO `v6.x` - PHP 8+

POPO schema example
-------------------

[](#popo-schema-example)

Schema example that produces generated [PopoConfigurator](src/Popo/PopoConfigurator.php) class.

```
$:
  config:
    namespace: Popo
    outputPath: src/
    phpComment: |
      @SuppressWarnings(PHPMD)
      @phpcs:ignoreFile

Popo:
  PopoConfigurator:
    default:
      phpFilePluginCollection:
        - \Popo\Plugin\PhpFilePlugin\StrictTypesPhpFilePlugin::class
        - \Popo\Plugin\PhpFilePlugin\CommentPhpFilePlugin::class
      namespacePluginCollection:
        - \Popo\Plugin\NamespacePlugin\UseStatementPlugin::class
      classPluginCollection:
        - \Popo\Plugin\ClassPlugin\ClassAttributePlugin::class
        - \Popo\Plugin\ClassPlugin\ClassCommentPlugin::class
        - \Popo\Plugin\ClassPlugin\ConstPropertyClassPlugin::class
        - \Popo\Plugin\ClassPlugin\DateTimeMethodClassPlugin::class
        - \Popo\Plugin\ClassPlugin\ExtendClassPlugin::class
        - \Popo\Plugin\ClassPlugin\ImplementClassPlugin::class
        - \Popo\Plugin\ClassPlugin\IsNewClassPlugin::class
        - \Popo\Plugin\ClassPlugin\ListModifiedPropertiesClassPlugin::class
        - \Popo\Plugin\ClassPlugin\MetadataClassPlugin::class
        - \Popo\Plugin\ClassPlugin\ModifiedToArrayClassPlugin::class
        - \Popo\Plugin\ClassPlugin\PopoMethodClassPlugin::class
        - \Popo\Plugin\ClassPlugin\RequireAllClassPlugin::class
        - \Popo\Plugin\ClassPlugin\UpdateMapClassPlugin::class
        - \Popo\Plugin\ClassPlugin\FromArrayClassPlugin::class
        - \Popo\Plugin\ClassPlugin\FromMappedArrayClassPlugin::class
        - \Popo\Plugin\ClassPlugin\ToArrayClassPlugin::class
        - \Popo\Plugin\ClassPlugin\ToMappedArrayClassPlugin::class
        - \Popo\Plugin\ClassPlugin\MappingPolicyMethod\ToArrayLowercasePlugin::class
        - \Popo\Plugin\ClassPlugin\MappingPolicyMethod\ToArrayUppercasePlugin::class
        - \Popo\Plugin\ClassPlugin\MappingPolicyMethod\ToArraySnakeToCamelPlugin::class
        - \Popo\Plugin\ClassPlugin\MappingPolicyMethod\ToArrayCamelToSnakePlugin::class
      propertyPluginCollection:
        - \Popo\Plugin\PropertyPlugin\AddItemPropertyMethodPlugin::class
        - \Popo\Plugin\PropertyPlugin\DefinePropertyPlugin::class
        - \Popo\Plugin\PropertyPlugin\GetPropertyMethodPlugin::class
        - \Popo\Plugin\PropertyPlugin\HasPropertyMethodPlugin::class
        - \Popo\Plugin\PropertyPlugin\RequirePropertyMethodPlugin::class
        - \Popo\Plugin\PropertyPlugin\SetPropertyMethodPlugin::class
      mappingPolicyPluginCollection:
        none: \Popo\Plugin\MappingPolicy\NoneMappingPolicyPlugin::class
        lower: \Popo\Plugin\MappingPolicy\LowerMappingPolicyPlugin::class
        upper: \Popo\Plugin\MappingPolicy\UpperMappingPolicyPlugin::class
        snake-to-camel: \Popo\Plugin\MappingPolicy\SnakeToCamelMappingPolicyPlugin::class
        camel-to-snake: \Popo\Plugin\MappingPolicy\CamelToSnakeMappingPolicyPlugin::class
    property: [
      {name: schemaPath}
      {name: namespace}
      {name: namespaceRoot}
      {name: outputPath}
      {name: phpFilePluginCollection, type: array, itemType: string, itemName: phpFilePluginClass}
      {name: namespacePluginCollection, type: array, itemType: string, itemName: namespacePluginClass}
      {name: classPluginCollection, type: array, itemType: string, itemName: classPluginClass}
      {name: propertyPluginCollection, type: array, itemType: string, itemName: propertyPluginClass}
      {name: mappingPolicyPluginCollection, type: array, itemType: string, itemName: mappingPolicyPluginClass}
      {name: schemaConfigFilename}
      {name: schemaPathFilter}
      {name: schemaFilenameMask, default: '*.popo.yml'}
      {name: shouldIgnoreNonExistingSchemaFolder, type: bool}
    ]}}
```

###  Health Score

41

—

FairBetter than 89% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity33

Limited adoption so far

Community15

Small or concentrated contributor base

Maturity78

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~25 days

Recently: every ~0 days

Total

74

Last Release

1019d ago

Major Versions

1.1.3 → 2.0.02019-12-09

2.6.3 → 3.0.02020-10-25

3.1.0 → 4.0.02021-05-18

4.0.0 → 5.0.02021-07-26

5.10.1 → 6.0.02022-02-25

PHP version history (5 changes)1.0.0PHP ^7.1

2.0.0PHP ^7.2

3.0.0PHP ^7.4

4.0.0PHP ^8

5.6.0PHP ^7.4|^8

### Community

Maintainers

![](https://www.gravatar.com/avatar/73a4cc056d2b09189dda46d01b76e71161dd9b75a226230bed6bec8f414d1cf8?d=identicon)[oliwierptak](/maintainers/oliwierptak)

---

Top Contributors

[![oliwierptak](https://avatars.githubusercontent.com/u/495101?v=4)](https://github.com/oliwierptak "oliwierptak (306 commits)")

---

Tags

builderdata-structuresdata-transfer-objectgeneratorphppojopopopopo-objectsschema-configurationschema-filesschema-inheritanceyaml-configuration

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/popo-generator/health.svg)

```
[![Health](https://phpackages.com/badges/popo-generator/health.svg)](https://phpackages.com/packages/popo-generator)
```

###  Alternatives

[symfony/maker-bundle

Symfony Maker helps you create empty commands, controllers, form classes, tests and more so you can forget about writing boilerplate code.

3.4k111.1M568](/packages/symfony-maker-bundle)[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M651](/packages/sylius-sylius)[simplesamlphp/simplesamlphp

A PHP implementation of a SAML 2.0 service provider and identity provider.

1.1k12.4M193](/packages/simplesamlphp-simplesamlphp)[shopware/platform

The Shopware e-commerce core

3.3k1.5M3](/packages/shopware-platform)[symplify/monorepo-builder

Not only Composer tools to build a Monorepo.

5205.3M82](/packages/symplify-monorepo-builder)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.3M152](/packages/sulu-sulu)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
