Giter VIP home page Giter VIP logo

annotated's People

Contributors

alexndr-novikov avatar butschster avatar gam6itko avatar makedo avatar meekstellar avatar msmakouz avatar rauanmayemir avatar roquie avatar roxblnfk avatar serafimarts avatar stylecibot avatar wolfy-j avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

annotated's Issues

Child entities are not added to registry when using attributes🐛

No duplicates 🥲.

  • I have searched for a similar issue in our bug tracker and didn't find any solutions.

What happened?

Problem:
When using inheritance and mark parent and child classes as entities using attributes, \Cycle\Schema\Registry generator does not add children entities to Schema Registry.

How to reproduce:
You can reproduce it if you remove docblock comment for your annotation in tests. You can see an example here
https://github.com/makedo/annotated/tree/fail-test
I change 1 fixture by fully removing docblocks and keep only AttributeReader in tests

Proposed solution:
Remove check for docblock In Cycle\Annotated\Utils\EntityUtils::findParent

Version

annotated v3.1.0, orm v2.1.1, PHP 8.1

ORM Schema

No response

No class alias support for annotation

Если использовать псевдоним названия класса, а не название аннотации, то парсер не найдёт аннотацию, на сколько я понял такое поведение из-за особенностей реализации библиотеки https://github.com/spiral/annotations.
В отличии от аннотаций доктрины, где название аннотации == название класса и есть поддержка псевдонимов.
Т.е. такой вариант использования аннотаций не сработает

namespace App\Entity;

use Cycle\Annotated\Annotation\Entity as CycleEntity;

/**
 * @CycleEntity
 */
class Order
{

Стоит ли внедрять поддержку псевдонимов или есть причины именно такой реализации, где аннотация !== название класса?

doctrine/inflector version

Hi, thank you for this library.

It looks like this package silently depends on doctrine/inflector ^1.4 API, here for example -

$this->inflector = (new \Doctrine\Inflector\Rules\English\InflectorFactory())->build();

This dependency satisfied by cycle/orm, which is requires doctrine/inflector ^1.3, and usually install 1.4

But, It may cause problems (like in my case), when application already has 1.3 version of inflector.

Maybe doctrine/inflector ^1.4 dependency should be added to this package?

[Bug]: Columns declared in non-entity classes are ignored 🐛

No duplicates 🥲.

  • I have searched for a similar issue in our bug tracker and didn't find any solutions.

What happened?

Hi,

In a scenario where some sort of BaseEntity is used to contain Columns appearing across multiple Entitys, those columns are not registered into the Entitys extending this base class.

abstract class EmployedPerson
{
    #[Column(type: 'integer')]
    protected int $id;
}

#[Entity]
class Developer extends EmployedPerson {
    #[Column(type: 'integer')]
    protected int $salary;
}

In the example above, the id column is not added to the Developer entity.

This is probably caused by Configurator:115:

$field->setEntityClass($property->getDeclaringClass()->getName());

where the field is set to entity by a declaring class, but this class is not an entity.

This should work also in combination with JTI, where a following hierarchy could be used:

#[Entity]
class Person {
    #[Column(type: 'primary')]
    protected int $id;
}

abstract class EmployedPerson extends Person
{
    #[Column(type: 'integer')]
    protected int $salary;
}

#[Entity]
#[JoinedTable]
class Developer extends EmployedPerson {
    #[Column(type: 'integer')]
    protected int $foo;
}

In the example above, the Developer table should contain columns id, salary and foo, but currently the salary is ignored.

Version

  • OS: PopOS
  • PHP version: 8.3.7
  • Package version:
    • annotated: 4.1
    • database: 2.11
    • orm: 2.8
    • schema-builder: 2.8

ORM Schema

No response

Adding an index to a JTI table

When adding an index on a child table in JTI, it tries to add to the parent table.

In the branch, I created the test.

For example, I created Entity Person:

/**
 * @Entity
 */
#[Entity]
class Person
{
    /** @Column(type="primary", name="id") */
    #[Column(type: 'primary', name: 'id')]
    protected int $foo_id;

    /** @Column(type="string") */
    #[Column(type: 'string')]
    public string $type;
}

After that, I created the Buyer entity and extended it from Person, added an index to the index_id column. But the index is trying to add to the people table, which is related to the Person entity.

/**
 * @Entity
 * @Index(columns={"index_id"}, unique=true)
 * @InheritanceJoinedTable
 */
#[Entity]
#[Index(columns: ['index_id'], unique: true)]
#[InheritanceJoinedTable]
class Buyer extends Person
{
    /** @Column(type="integer") */
    #[Column(type: 'integer')]
    private int $index_id;
}

index1

Duplicate namespaces in resources/stubs

For example there is namespace Cycle\Annotated\Annotation; located in resources/stubs and also in src/Annotation. This can't be right, right? It is messing with psalm and other alike tools. Is there any solution for that?

Error generated by psalm looks like this:

ERROR: InvalidNamedArgument - app/Entity/Trait/CreatedAtTrait.php:12:17 - Parameter $type does not exist on function Cycle\Annotated\Annotation\Column::__construct (see https://psalm.dev/238)
        #[Column(type: 'datetime')]

It is probably using the first occurence in alphabet for that namespace?

PHP 8 Attributes

It would be cool if we could use PHP 8 Attributes for defining the schema

Virtual generated column💡

I have an idea!

Hi,

I would like to extend the functionality to support virtual generated columns.

In Doctrine it is possible using this explicit annotation:

#[ORM\Column(type: 'int', columnDefinition: 'INT GENERATED ALWAYS AS (IF(xyz IS TRUE, 100, 200)) VIRTUAL', generated: 'ALWAYS')]
private int $someNumber;

Possibly the freshly added GeneratedColumn attribute might be used to support the functionality?

I am open to bounty this feature.

Annotation name

Shouldn't annotation though be changed to through (i.e. "using", "by means of")?

Migration generator not add precision and scale params for decimal column type in Embeddable class 🐛

No duplicates 🥲.

  • I have searched for a similar issue in our bug tracker and didn't find any solutions.

What happened?

Hello ! Thanks for your product !

I'm create embeddable class for my base entity.

#[Embeddable(columnPrefix: 'property_')]
final class ProductProperty
{
    #[Column(type: 'decimal', nullable: false, default: 0, precision: 2, scale: 10)]
    private int $width = 0;
    
    // and others columns

}

When i generate migration file with the command:

php app.php cycle:migrate

I get such a file that does not include params precision and scale params:

// Parent entity 
final class Product
{
    #[Column(type: 'decimal', nullable: true, precision: 2, scale: 2)]
    private int $minStock = 0;

    #[Embedded(target: 'ProductProperty')]
    private ProductProperty $property;
    
    public function __construct(){
        $this->property = new ProductProperty();
    }
}

// Generated migration for 'Product'

class OrmDefault503ad0138adb712888e44c220d4cf5aa extends Migration
{

    public function up(): void
    {
        $this->table('product')
->addColumn('min_stock', 'decimal', ['nullable' => true, 'defaultValue' => null, 'precision' => 2, 'scale' => 2]); /// This property in base entity
->addColumn('property_width', 'decimal', ['nullable' => false, 'defaultValue' => 0, 'precision' => 0, 'scale' => 0]) // And this in Embedded entity 
     }

}

I will be grateful for your help!

Version

annotated v4.1.0, orm v2.8.1, PHP 8.3

ORM Schema

No response

Check constraint💡

I have an idea!

Hi,

I would love to add a check constraint to my table using attributes.

I imagine the functionality as following, but it is just a draft.

#[Entity]
#[Index(columns: ['a'], unique: true)]
#[Check(expression: 'a > b')]
class EntityDef
{
    #[Column(type: 'integer')]
    private int $a;
    
    #[Column(type: 'integer')]
    private int $b;
}

I am open to bounty this feature.

Update readme.md

Refresh readme, add link to documentation

  • Header block with badges and links to docs, discord, Support us (funding)...
  • Installation block
  • Links to configurations (cycle-orm.dev, spiral.dev)
  • Cleanup
    • Delete annotation examples
    • Headers structure

Enhance documentation pls

Do u know that
/** @HasOne(target=Profile::class, load="eager") */

don't work without
use Cycle\Annotated\Annotation\Relation\HasOne

and so on will all entities from \Relation

and this is not obviously - people need to study your code.

Possible ManyToMany typo?

I'm reading through the docs and I see

    /** @ManyToMany(target = "Tag", though = "UserTag") */
    protected $tags;

At first glance, I read this as "entity has many Tag through UserTag" where UserTag is the join class somewhat. Thought to fix that and realized 👇🏾 this is how it's defined.

https://github.com/cycle/annotated/blob/master/src/Annotation/Relation/ManyToMany.php#L59

Could this be a case of a typo carried over because of IDE smarts? If this isn't the case, what's the thought process? I see this commit introduces "though", but the commit message doesn't really say why.

I know this is 2 years old, so it's a long shot; but I had to ask

Select query with polymorphic relationship does not work

Generated SQL:

 SELECT "serviceAccount"."key" AS "c0", "serviceAccount"."name" AS "c1", "serviceAccount"."id" AS "c2", "serviceAccount"."created_at" AS "c3", "serviceAccount"."updated_at" AS "c4",
"serviceAccount"."deleted_at" AS "c5", "l_serviceAccount_configuration"."timezone" AS "c6", "l_serviceAccount_configuration"."id" AS "c7",
"l_serviceAccount_configuration"."created_at" AS "c8", "l_serviceAccount_configuration"."updated_at" AS "c9", "l_serviceAccount_configuration"."deleted_at" AS "c10",
"l_serviceAccount_configuration"."configuration_id" AS "c11", "l_serviceAccount_configuration"."{relationName}_role" AS "c12", "l_serviceAccount_configuration"."configuration_role"
AS "c13"
FROM "service_accounts" AS "serviceAccount" 
LEFT JOIN "configurations" AS "l_serviceAccount_configuration"
    ON "l_serviceAccount_configuration"."configuration_id" = "serviceAccount"."id" AND "l_serviceAccount_configuration"."deleted_at" IS NULL AND "l_serviceAccount_configuration"."configuration_role" = 'serviceAccount'  
WHERE "serviceAccount"."key" = 'system' AND "serviceAccount"."deleted_at" IS NULL 
LIMIT 1

Sample code to reproduce:

#[Cycle\Entity]
class ServiceAccount 
{
    #[Cycle\Relation\Morphed\MorphedHasOne(
        target: Configuration::class,
//        morphKey: 'configuration_role', // FIX
        load: 'eager'
    )]
    protected ?Configuration $configuration = null;
}

#[Cycle\Entity]
class Configuration
{
 // ...
}

{relationName} – is a template variable which not replaced before query execution.

P.S.

  • PHP 8.1.1
  • cycle\orm: 2.0

💡 Up PHP min version to 8.1

I have an idea!

Need to

  • Bump PHP to ^8.1
  • Update code using Rector
  • Add tests with Embedded Atributes (php 8.1 feature)

Inflector issue

[ErrorException]
 The "Doctrine\Common\Inflector\Inflector::tableize" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.
in /app/vendor/doctrine/inflector/lib/Doctrine/Common/Inflector/Inflector.php:80

Exception Trace:
 Spiral\Boot\ExceptionHandler::handleError() at /app/vendor/doctrine/inflector/lib/Doctrine/Common/Inflector/Inflector.php:80
 Spiral\Boot\ExceptionHandler::handleError() at n/a:n/a
 trigger_error() at /app/vendor/doctrine/inflector/lib/Doctrine/Common/Inflector/Inflector.php:80
 Doctrine\Common\Inflector\Inflector::tableize() at /app/vendor/cycle/annotated/src/Entities.php:191
 Cycle\Annotated\Entities->tableName() at /app/vendor/cycle/annotated/src/Entities.php:106
 Cycle\Annotated\Entities->run() at /app/vendor/cycle/schema-builder/src/Compiler.php:63
 Cycle\Schema\Compiler->compile() at /app/vendor/spiral/framework/src/Bootloader/Cycle/SchemaBootloader.php:113
 Spiral\Bootloader\Cycle\SchemaBootloader->schema() at n/a:n/a
 ReflectionMethod->invokeArgs() at /app/vendor/spiral/core/src/Container.php:506
 Spiral\Core\Container->evaluateBinding() at /app/vendor/spiral/core/src/Container.php:166
 Spiral\Core\Container->make() at /app/vendor/spiral/core/src/Container.php:133
 Spiral\Core\Container->get() at /app/vendor/spiral/prototype/src/Bootloader/PrototypeBootloader.php:170
 Spiral\Prototype\Bootloader\PrototypeBootloader->initCycle() at /app/vendor/spiral/prototype/src/Bootloader/PrototypeBootloader.php:112
 Spiral\Prototype\Bootloader\PrototypeBootloader->boot() at n/a:n/a
 ReflectionMethod->invokeArgs() at /app/vendor/spiral/boot/src/BootloadManager.php:124
 Spiral\Boot\BootloadManager->initBootloader() at /app/vendor/spiral/boot/src/BootloadManager.php:98
 Spiral\Boot\BootloadManager->boot() at /app/vendor/spiral/boot/src/BootloadManager.php:66
 Spiral\Boot\BootloadManager->Spiral\Boot\{closure}() at /app/vendor/spiral/core/src/Container.php:282
 Spiral\Core\Container->runScope() at /app/vendor/spiral/boot/src/BootloadManager.php:67
 Spiral\Boot\BootloadManager->bootload() at /app/vendor/spiral/framework/src/Framework/Kernel.php:35
 Spiral\Framework\Kernel->bootstrap() at /app/vendor/spiral/boot/src/AbstractKernel.php:142
 Spiral\Boot\AbstractKernel::Spiral\Boot\{closure}() at /app/vendor/spiral/core/src/ContainerScope.php:50
 Spiral\Core\ContainerScope::runScope() at /app/vendor/spiral/core/src/Container.php:279
 Spiral\Core\Container->runScope() at /app/vendor/spiral/boot/src/AbstractKernel.php:143
 Spiral\Boot\AbstractKernel::init() at /app/app.php:18

Primary Keys are resolving to arrays even when they're not, which makes select->count() not work properly🐛

No duplicates 🥲.

  • I have searched for a similar issue in our bug tracker and didn't find any solutions.

What happened?

When I generate my schema using annotations I have noticed that it will set an integer auto-increment primary key with name $id to an array.

Entity PK definition:

#[Column(type: "primary")]
private int $id;

After persisting the schema to a json file:

        "7": [
            "id"
        ],

It looks like Cycle\Schema\Compiler is the culprit. Line 90 is Schema::PRIMARY_KEY => $entity->getPrimaryFields()->getNames(), and this always returns an array.

The IMPACT of this (at least the one I've seen), is seen in Cycle\ORM\Select::count(). If the $column parameter isn't set, it looks at the primary key definition instead as follows:

        if ($column === null) {
            // @tuneyourserver solves the issue with counting on queries with joins.
            $pk = $this->loader->getPK();
            $column = \is_array($pk)
                ? '*'
                : \sprintf('DISTINCT(%s)', $pk);
        }

        return (int) $this->__call('count', [$column]);

because it's always an array, it always puts in * instead of the DISTINCT() call. In a left join it will then show an incorrect count. It'll be showing the number of results in the SQL instead of the number of results in the SQL for the left/primary table.

I've confirmed this by changing the schema to not be an array, and then the count works accurately. I've also tried select->count('DISTINCT(table.id)'); and this works too (as it emulates what would happen if this was working correctly).

Version

    "cycle/orm": "^2.2",
    "cycle/annotated": "^3.2",
    "cycle/schema-builder": "^2.1",
    "cycle/entity-behavior": "^1.1",

php 8.0.16

ORM Schema

No response

[Bug]: HasOne overrides nullability of BelongsTo

Describe the bug

Hi,
I am trying to integrate CycleORM into a Symfony application, in order to replace Doctrine, and I encountered a strange behavior with relations.

I will show you the example first.

I trimmed all the other tables and managed to reproduce on following 4 entities:

#[Entity(database: 'main')]
class Question
{
    #[Column(type: 'primary')]
    private int $id;

    #[BelongsTo(target: QuestionTextual::class, nullable: true)]
    private ?QuestionTextual $questionTextual = null;

    #[BelongsTo(target: QuestionChoice::class, nullable: true)]
    private ?QuestionChoice $questionChoice = null;

    #[BelongsTo(target: QuestionMultichoice::class, nullable: true)]
    private ?QuestionMultichoice $questionMultichoice = null;
}

#[Entity(database: 'main')]
class QuestionChoice
{
    #[Column(type: 'primary')]
    private readonly int $id;

    #[HasOne(target: Question::class)]
    private Question $question;
}

#[Entity(database: 'main')]
class QuestionTextual
{
    #[Column(type: 'primary')]
    private readonly int $id;

    #[HasOne(target: Question::class)]
    private Question $question;
}

#[Entity(database: 'main')]
class QuestionMultichoice
{
    #[Column(type: 'primary')]
    private readonly int $id;

    #[HasOne(target: Question::class)]
    private Question $question;
 }

Those entities result in following database schema:

create table question_choices
(
    id int auto_increment
        primary key
);

create table question_multichoices
(
    id int auto_increment
        primary key
);

create table question_textuals
(
    id int auto_increment
        primary key
);

create table questions
(
    id                     int auto_increment
        primary key,
    questionChoice_id      int not null,
    questionTextual_id     int null,
    questionMultichoice_id int null,
    constraint questions_foreign_questionchoice_id_66745e0c2f565
        foreign key (questionChoice_id) references question_choices (id)
            on update cascade on delete cascade,
    constraint questions_foreign_questionmultichoice_id_66745e0c2f6fc
        foreign key (questionMultichoice_id) references question_multichoices (id)
            on update cascade on delete cascade,
    constraint questions_foreign_questiontextual_id_66745e0c2f607
        foreign key (questionTextual_id) references question_textuals (id)
            on update cascade on delete cascade
);

create index questions_index_questionchoice_id_66745e0c2f53b
    on questions (questionChoice_id);

create index questions_index_questionmultichoice_id_66745e0c2f6e5
    on questions (questionMultichoice_id);

create index questions_index_questiontextual_id_66745e0c2f5ef
    on questions (questionTextual_id);

The strange thing this issue is about is the nullability of questionChoice_id column. For some reason the column is declared as NOT NULL, while others are nullable - and all the columns have identical attribute declaration.

In this usecase the question has 3 possible types and the tables include some additional settings. In the base table the relation is nullable, because only one of the 3 columns is filled. However in the extending tables the column is not null, because it must have a base table paired to it.

There might be some sort of misunderstanding of the CycleORM relations on my side, but it seems strange to me that one column has different nullability than the others. When the HasOne attribute is removed from the entitiy, the nullability is corrected.

Is this a regression?

I cannot tell as I am a new user of Cycle ORM.

To Reproduce

Use the default setup and sync a database with entitiy declaration above.

Expected behaviour

The column should be nullable.

Media prove

No response

Database

MySQL

Your environment

  • OS: PopOS
  • PHP version: 8.3.7
  • Package version:
    • annotated: 4.1
    • database: 2.11
    • orm: 2.8
    • schema-builder: 2.8

Additional context

No response

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.