Nathan
Nathan

Reputation: 1525

issues accessing related values in Symfony/Doctrine

I have a Status table that is used as a reference to identify/flag the state in other tables example:

|  id   |   status   |
|-------|------------|
|  1    | Active     |
|  2    | Disabled   |
|  3    | Admin Only |
|  4    | Archived   |

I am trying to use these values in my isEnabled() function of the Users Entity.

 public function isEnabled() {

    $statusObj = $this->status;
    $statusValue = $statusObj->getStatus();

    if( $statusValue  != "Active" ){
        return false;
    }

    // Simply persisting true works
     return true;
}

With this function is it is currently on login, I get a non-object error.

Error: Call to a member function getStatus() on a non-object

Looking at debug, $status appears to be a proxy object instead of my Status object, but cant quite seem to find anything to point me in the right direction from here.

User.orm.yml

AppBundle\Entity\User:
type: entity
table: user
indexes:
    fk_user_status1_idx:
        columns:
            - status_id
id:
    id:
        type: integer
        nullable: false
        options:
            unsigned: false
            comment: 'user Primary Key'
        id: true
        generator:
            strategy: IDENTITY
fields:
   # ....

manyToOne:
    status:
        targetEntity: Status
        cascade: {  }
        joinColumns:
            status_id:
                referencedColumnName: id
        orphanRemoval: false
manyToMany:
    roles:
        targetEntity: Role
        joinTable:
            name: user_has_role
            joinColumns:
                user_id:
                    referencedColumnName: id
            inverseJoinColumns:
                role_id:
                    referencedColumnName: id
lifecycleCallbacks: {  }

I tried altering fetch: of status in the User.orm.yml file to have values of LAZY and EAGER, neither changed anything.

I tried to make this post succinct, so if I've missed any vital details just let me know.

*** UPDATE ***

I didn't set mapped/inversed options based on a Many To One - Unidirectional Relatioinship. I've now remove the "null" generated values so status matches the documentation linked. The Status Table and Entity include no reference back to users in any way.

While running debug in my IDE I found isEnabled() getting called twice... The first call of isEnabled() looks to be working perfectly. $statsObj is == the proxy object and when I call $statusObj->getStatus() I see it return "Active" as expected. The function then returns true, and the debugger jumps back into isEnabled() a second time. This second run of isEnabled() my user object is NULL. After of Hours of racking my brain trying to find out why isEnabled() is running twice... it finally occurs to me that the first run is on login and the second is coming during the redirect after authentication passes. Turns out the whole problem is that $this->status was never added to the Serialize/Unserialize functions so the status property was null after Unseralize and when inEnabled was called to verify it failed.

The solution is so far from the issue described, unless anyone has any suggestions to make this useful for another i'll just vote to Delete.

Upvotes: 0

Views: 193

Answers (2)

Alvin Bunk
Alvin Bunk

Reputation: 7764

You haven't posted your Status entity code, but you probably need to change like so:

manyToOne:
    status:
        targetEntity: Status
        cascade: {  }
        orphanRemoval: false
          inversedBy: value_in_Status
        joinColumn:
            name: status_id
            referencedColumnName: id

Notice you have "joinColumns" not "joinColumn".

Upvotes: 1

simon.ro
simon.ro

Reputation: 3302

Doctrine wraps your relations in proxies due to their lazy loading mechanism. When accessing $this->status directly you get that proxy object.

Try using the getter instead:

public function isEnabled() {
    if( $this->getStatus()->getStatus() != "Active" ){
        return false;
    }
    ...
}

That looks a bit funny, but $this->getStatus() gives you the Status entity, and the additional getStatus() asks for the field 'status' of Status entity.

Upvotes: 2

Related Questions