-->

Call to a member function addPaiementType() on nul

2019-09-11 04:53发布

问题:

I have 3 files:

The first one:

public function register(\Pimple\Container $app)
{
    $app['manager.form'] = function() use ($app) {
        return new Form($app);
    };
}

Second:

class Form
{
    private $form;

    public function __construct(Application $app)
    {
        $this->form = $app['form.factory']->createBuilder(FormType::class);
    }

    public function addDuree()
    {
        $this->form->add('duree', ChoiceType::class, [
            'choices' => [
                '1'  => '1',
                '3'  => '3',
                '6'  => '6',
                '12' => '12'
            ],
            'multiple' => false,
            'expanded' => true,
            'data' => 1
        ]);
    }

    public function addPaiementType()
    {
        $this->form->add('paiementType', ChoiceType::class, [
            'choices' => [
                'virement'  => 'virement',
                'cheque'    => 'cheque',
                'paypal'    => 'paypal',
                'paypal-cb' => 'paypal-cb'
            ],
            'multiple' => false,
            'expanded' => true,
            'data' => 'virement'
        ]);
    }

    public function addTermsAccepted()
    {
        $this->form->add('termsAccepted', CheckboxType::class, [
            'mapped' => false,
            'constraints' => new Assert\IsTrue(),
        ]);
    }

    public function getForm()
    {
        return $this->form->getForm();
    }
}

And the controller:

$form = $app['manager.form']->addDuree()->addPaiementType()->addTermsAccepted();

But Silex give me the error:

Call to a member function addPaiementType() on null

I do not understand why. For me this code structure is equivalent to:

    $form = $app['form.factory']->createBuilder(FormType::class)
    ->add('duree', ChoiceType::class, [
        'choices' => [
            '1'  => '1',
            '3'  => '3',
            '6'  => '6',
            '12' => '12'
        ],
        'multiple' => false,
        'expanded' => true,
        'data' => 1
    ])
    ->add('paiementType', ChoiceType::class, [
        'choices' => [
            'virement'  => 'virement',
            'cheque'    => 'cheque',
            'paypal'    => 'paypal',
            'paypal-cb' => 'paypal-cb'
        ],
        'multiple' => false,
        'expanded' => true,
        'data' => 'virement'
    ])
    ->add('termsAccepted', CheckboxType::class, [
        'mapped' => false,
        'constraints' => new Assert\IsTrue(),
    ])
    ->getForm();

But it seems not... Don't know why.

Thanks for help

回答1:

To use object call chaining, the methods have to return $this. You're not doing that. Your addDuree() has NO return at all, so it implicitly has a return null, which means that this line:

$form = $app['manager.form']->addDuree()->addPaiementType()->addTermsAccepted();

executes as if it was written

 $form = $app['manager.form']->null->addPaiementType()
                               ^^^^

Your should have

function addPaimentType() {
    ... stuff ...
    return $this;
}