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

Using $this when not in object context #118

Closed
seb-jean opened this issue Feb 4, 2021 · 9 comments
Closed

Using $this when not in object context #118

seb-jean opened this issue Feb 4, 2021 · 9 comments

Comments

@seb-jean
Copy link
Contributor

seb-jean commented Feb 4, 2021

Hi,

I have an error:
In Factory.php line 108: Using $this when not in object context

@kbond
Copy link
Member

kbond commented Feb 4, 2021

Strange. Can you provide some context on how you're creating factories?

@seb-jean
Copy link
Contributor Author

seb-jean commented Feb 5, 2021

I tried with new project Symfony and it's the same.

I have v1.7.0 for this repo and Symfony 5.2.3.

With versions zenstruck/foundry 1.2, 1.3, 1.4, 1.5 and 1.6, no problem.

Repo : https://github.com/seb-jean/foundrytest

// AppFixtures.php
<?php

namespace App\DataFixtures;

use App\Factory\UserFactory;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;

class AppFixtures extends Fixture
{
    public function load(ObjectManager $manager)
    {
        UserFactory::new()->create([
            'email' => 'seb@live.fr',
        ]);

        $manager->flush();
    }
}
// User.php
<?php

namespace App\Entity;

use App\Repository\UserRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;

/**
 * @ORM\Entity(repositoryClass=UserRepository::class)
 */
class User implements UserInterface
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=180, unique=true)
     */
    private $email;

    /**
     * @ORM\Column(type="json")
     */
    private $roles = [];

    /**
     * @var string The hashed password
     * @ORM\Column(type="string")
     */
    private $password;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getEmail(): ?string
    {
        return $this->email;
    }

    public function setEmail(string $email): self
    {
        $this->email = $email;

        return $this;
    }

    /**
     * A visual identifier that represents this user.
     *
     * @see UserInterface
     */
    public function getUsername(): string
    {
        return (string) $this->email;
    }

    /**
     * @see UserInterface
     */
    public function getRoles(): array
    {
        $roles = $this->roles;
        // guarantee every user at least has ROLE_USER
        $roles[] = 'ROLE_USER';

        return array_unique($roles);
    }

    public function setRoles(array $roles): self
    {
        $this->roles = $roles;

        return $this;
    }

    /**
     * @see UserInterface
     */
    public function getPassword(): string
    {
        return (string) $this->password;
    }

    public function setPassword(string $password): self
    {
        $this->password = $password;

        return $this;
    }

    /**
     * @see UserInterface
     */
    public function getSalt()
    {
        // not needed when using the "bcrypt" algorithm in security.yaml
    }

    /**
     * @see UserInterface
     */
    public function eraseCredentials()
    {
        // If you store any temporary, sensitive data on the user, clear it here
        // $this->plainPassword = null;
    }
}
// UserFactory.php
<?php

namespace App\Factory;

use App\Entity\User;
use App\Repository\UserRepository;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Zenstruck\Foundry\RepositoryProxy;
use Zenstruck\Foundry\ModelFactory;
use Zenstruck\Foundry\Proxy;

/**
 * @method static User|Proxy createOne(array $attributes = [])
 * @method static User[]|Proxy[] createMany(int $number, $attributes = [])
 * @method static User|Proxy findOrCreate(array $attributes)
 * @method static User|Proxy random(array $attributes = [])
 * @method static User|Proxy randomOrCreate(array $attributes = [])
 * @method static User[]|Proxy[] randomSet(int $number, array $attributes = [])
 * @method static User[]|Proxy[] randomRange(int $min, int $max, array $attributes = [])
 * @method static UserRepository|RepositoryProxy repository()
 * @method User|Proxy create($attributes = [])
 */
final class UserFactory extends ModelFactory
{
    private $passwordEncoder;

    public function __construct(UserPasswordEncoderInterface $passwordEncoder)
    {
        parent::__construct();

        $this->passwordEncoder = $passwordEncoder;
    }

    protected function getDefaults(): array
    {
        return [
            'email' => self::faker()->email,
            'password' => 'user',
        ];
    }

    protected function initialize(): self
    {
        // see https://github.com/zenstruck/foundry#initialization
        return $this
            ->afterInstantiate(function(User $user, array $attributes) {
                if ($user->getPassword()) {
                    $user->setPassword($this->passwordEncoder->encodePassword($user, $user->getPassword()));
                }
            });
        ;
    }

    protected static function getClass(): string
    {
        return User::class;
    }
}

@kbond
Copy link
Member

kbond commented Feb 5, 2021

Awesome, thanks for the reproducer. I'll dig in later today to see if I can track down the issue.

@kbond
Copy link
Member

kbond commented Feb 5, 2021

Hey @seb-jean, these are the steps I took with the above linked repo:

  1. Clone repo
  2. composer install
  3. php bin/console doctrine:database:create
  4. php bin/console doctrine:schema:create
  5. php bin/console doctrine:fixtures:load

Everything worked as expected - the single User was added to the user table (with the encoded password). I tried php 7.2, 7.4 and 8.0 - all worked.

Is there a different set of steps I should do to get your error?

@kbond
Copy link
Member

kbond commented Feb 5, 2021

Are you by chance using a php version less than 7.2.12?

There was a PHP bug related to invoking reflected closures (which is what this library does) that gave this error. It was fixed in 7.2.12+. Demonstration of the error (need to check "eol versions" to see the failures).

@seb-jean
Copy link
Contributor Author

seb-jean commented Feb 8, 2021

My version of PHP is PHP 7.2.10

@kbond
Copy link
Member

kbond commented Feb 8, 2021

Ah, I bet that's it. Any chance you can upgrade PHP to at least 7.2.12?

@seb-jean
Copy link
Contributor Author

seb-jean commented Feb 8, 2021

With PHP 8.0.2, it's works.

kbond added a commit to kbond/foundry that referenced this issue Feb 9, 2021
@kbond
Copy link
Member

kbond commented Feb 9, 2021

Thanks for confirming!

As a solution, I'm going to bump the min PHP version of foundry to 7.2.12.

@kbond kbond closed this as completed in ecc0e10 Feb 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants