Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InvalidArgumentException - Unable to create a proxy for a final class #7598

Closed
JamieYnonan opened this issue Feb 9, 2019 · 7 comments
Closed
Assignees

Comments

@JamieYnonan
Copy link

Q A
Version 2.6.3

Support Question

I can't use final class?

InvalidArgumentException Unable to create a proxy for a final class "Mu\Domain\Model\Role\Role"

final class Role

Mu\Domain\Model\Role\Role:
  type: entity
  table: roles
  id:
    id:
      type: role_id
      generator:
        strategy: NONE
  embedded:
    name:
      class: Mu\Domain\Model\Role\Name
      columnPrefix: false
    description:
      class: Mu\Domain\Model\Role\Description
      columnPrefix: false
    status:
      class: Mu\Domain\Model\Role\Status
      columnPrefix: false
  fields:
    updatedAt:
      type: datetimetz
      column: updated_at
    createdAt:
      type: datetimetz
      column: created_at
  manyToMany:
    permissions:
      fetch: EXTRA_LAZY
      targetEntity: Mu\Domain\Model\Permission\Permission
      joinTable:
        name: role_permissions
        joinColumns:
          role_id:
            referencedColumnName: id
        inverseJoinColumns:
          permission_id:
            referencedColumnName: id

final class User

Mu\Domain\Model\User\User:
  type: entity
  table: users
  id:
    id:
      type: user_id
      generator:
        strategy: NONE
  embedded:
    name:
      class: Mu\Domain\Model\User\Name
      columnPrefix: false
    lastName:
      class: Mu\Domain\Model\User\LastName
      columnPrefix: false
    email:
      class: Mu\Domain\Model\User\Email
      columnPrefix: false
    password:
      class: Mu\Domain\Model\User\Password
      columnPrefix: false
    status:
      class: Mu\Domain\Model\User\Status
      columnPrefix: false
  fields:
    updatedAt:
      type: datetimetz
      column: updated_at
    createdAt:
      type: datetimetz
      column: created_at
  manyToOne:
    role:
      fetch: EXTRA_LAZY
      targetEntity: Mu\Domain\Model\Role\Role
      joinColumn:
        role_id:
          referencedColumnName: id
          nullable: false
@Ocramius
Copy link
Member

Ocramius commented Feb 9, 2019

No, you cannot: that's exactly what the exception says.

@JamieYnonan
Copy link
Author

my question was not precise,
Why can't I use final class? in the relationship many to many I don't have problems, but in many to one I can't use final class.

@Ocramius
Copy link
Member

Ocramius commented Feb 9, 2019

The ORM will need a proxy whenever a lazy association is to be built: this can happen also on collections and many-to-one.

@arnaud-lb
Copy link
Contributor

Should Doctrine forbid final classes for entities entirely, and throw an error during metadata loading ? This would help to spot this kind of errors earlier.

@Ocramius
Copy link
Member

Ocramius commented Feb 9, 2019

@arnaud-lb feasible for 3.x, not for 2.x anymore, as we're pretty much closed for new features.

@bogdan-dubyk
Copy link

I know it's and old closed topic, and I'm not sure doctrine can do something here. But from a domain perspective when you are using DDD and trying to move all the database mapping to the infrastructure layer, most likely to XML, you should not think about how to make a domain model to satisfy database/orm needs, and if some class from business domain perspective should never be extended it makes sense to set it as final.

I remember a similar issue with PHPUnit mocking, which can be solved by dg/bypass-finals package, maybe something similar can be done for doctrine proxies, not sure, just a suggestion.

Anyway, by the end of the day I like doctrine, you are doing a great job, but if the project you are working on is using the DDD paradigm I'm starting to think more and more about not using doctrine as it always leaks to the domain, and trying to tell you how you should write domain if you want to use doctrine.

@derrabus
Copy link
Member

if some class from business domain perspective should never be extended it makes sense to set it as final.

If you want to lazy-load an instance of such a class without the code that uses it being aware of the lazy-loading, you need a proxy that extends your class. And yes, that means it must not be final.

If you want to document that a class must not have child classes however, you can still use the /** @final */ annotation. Static analyzers understand it and warn you if you create subclasses:

I remember a similar issue with PHPUnit mocking, which can be solved by dg/bypass-finals package, maybe something similar can be done for doctrine proxies, not sure, just a suggestion.

A class loader that un-finals classes on the fly might be feasible for tests (still gives me the shivers though), but for production code, that's an absolute no-go. That being said, that loader requires no change from our side. If you want to fuck up your project with such a class loader, we cannot stop you.

I'm not sure doctrine can do something here

No. If you want to have proxies of final classes, you need to build that feature into the PHP runtime itself.

LVoogd added a commit to browncat-nl/feed that referenced this issue Jun 4, 2023
Doctrine unfortunately can't work with final or readonly classes. We are
therefor forced to remove it from the entities.

doctrine/orm#7598
LVoogd added a commit to browncat-nl/feed that referenced this issue Jun 5, 2023
Doctrine unfortunately can't work with final or readonly classes. We are
therefor forced to remove it from the entities.

doctrine/orm#7598
LVoogd added a commit to browncat-nl/feed that referenced this issue Jun 5, 2023
Doctrine unfortunately can't work with final or readonly classes. We are
therefor forced to remove it from the entities.

doctrine/orm#7598
TOP-10-DEV added a commit to TOP-10-DEV/warehouse-management-system that referenced this issue Dec 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants