Skip to content

Instantly share code, notes, and snippets.

@roxblnfk
Last active April 8, 2021 05:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save roxblnfk/15a16ebf2fcee9d23bedd99b1252121c to your computer and use it in GitHub Desktop.
Save roxblnfk/15a16ebf2fcee9d23bedd99b1252121c to your computer and use it in GitHub Desktop.
Cycle ORM attributes

Cycle ORM: Атрибуты

Теперь в Cycle ORM для описания схемы наравне с аннотациями можно использовать атрибуты.

Плавность перехода с аннотаций на атрибуты обеспечат:

  1. В аннотациях и атрибутах используются одни и те же классы, с теми же параметрами.
  2. По умолчанию аннотации можно использовать совместно с атрибутами.
  3. Совместимость с PHP >=7.2
    Несмотря на то, что атрибуты нативно поддерживаются только с PHP 8, начинать использовать их можно уже сейчас.
    Одно лишь условие: каждый атрибут должен умещаться в одной строке, иначе вы получите синтаксическую ошибку на ранних версиях php.

Примеры

Аннотация @Entity

/**
 * @Entity(role = "eComplete", mapper = "CompleteMapper", repository = "Repository/CompleteRepository")
 */
class Complete 
{
}

Аналогичный атрибут

#[Entity(role: "eComplete", mapper: CompleteMapper::class, repository: "Repository/CompleteRepository")]
class Complete
{
}

PHP 8 не позволяет вкладывать атрибуты в атрибуты, поэтому некоторые параметры, ранее подразумевающие вложенность, вынесены отдельно.

Было

/**
 * @Entity()
 * @Table(
 *      columns = {
 *          "name":   @Column(type="string"),
 *          "status": @Column(type="enum(active,disabled)", default="active")
 *      },
 *      indexes = {
 *          @Index(columns={"status"}),
 *          @Index(columns={"name"}, unique=true, name="name_index")
 *      }
 * )
 */
class Entity
{
}

Стало

#[Entity]
#[Column(name: 'name', type: 'string')]
#[Column(name: 'status', type: 'enum(active,disabled)', default: 'active')]
#[Index(columns: ['status'])]
#[Index(name: "name_index", columns: ['name'], unique: true)]
class Entity
{
}

В случае аннотаций вынос параметров тоже будет работать:

/**
 * @Entity()
 * @Column(name="name", type="string"),
 * @Column(name="status", type="enum(active,disabled)", default="active")
 * @Index(columns={"status"}),
 * @Index(columns={"name"}, unique=true, name="name_index")
 */
class Entity
{
}

Параметр inverse для связей также вынесен в отдельный атрибут.

Было

class Before
{
    /**
     * @HasOne(target=Simple::class, load="eager", inverse = @Inverse(as="user", type="belongsTo", load="lazy"))
     */
    protected $simple;
 }

Стало (Аннотации)

class After
{
    /**
     * @HasOne(target=Simple::class, load="eager")
     * @Inverse(as="user", type="belongsTo", load="lazy")
     */
    protected $simple;
}

Стало (Атрибуты)

class After 
{
    #[HasOne(target: Simple::class, load: "eager")]
    #[Inverse(as: "user", type: "belongsTo", load: "lazy")]
    protected $simple;
}

Вы можете использовать совместно и атрибуты, и аннотации, пока не завершите миграцию:

#[Entity(role: 'user_post')]
class Post
{
    #[Column(type: 'primary')]
    protected $id;

    /** @ManyToMany(target="Tag", though="Tag/Context", orderBy={"id": "DESC"}) */
    protected $tags;

    /** @Embedded(target="Metadata", load="lazy") */
    protected $metadata;
}

Настройка

Для того, чтобы атрибуты заработали на вашем проекте, просто обновите пакет cycle/annotated минимум до версии 2.3.

По умолчанию в генераторах схемы будет настроен SelectiveReader, обеспечивающий парсинг одновременно аннотаций и атрибутов. Вы можете переопределить SelectiveReader в генераторах в пользу, например, AnnotationReader или AttributeReader, если вам нужно использовать только один источник данных.
Список генераторов, принимающих ReaderInterface:

\Cycle\Annotated\Embeddings
\Cycle\Annotated\Entities
\Cycle\Annotated\MergeColumns
\Cycle\Annotated\MergeIndexes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment