错误:在非对象上调用成员函数get()500内部服务器错误 - FatalErrorException(Symfony)

时间:2015-02-24 11:19:09

标签: php symfony

对于Mac和Symfony来说,我是相当新的,如果我缺少任何基本知识,那就很抱歉

基本上尝试使用php类创建表单,这里是

<?php

namespace TeamRock\ApplicationBundle\entity;

class Person{
protected $email;
protected $fullname;

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

public function setEmail($email){
    return $this->$email;
}

public function getFullname(){
    return $this ->$fullname;
}

public function setFullname($fullname){
    return $this -> $fullname;
}
}

?>

然后我有我的班级

 <?php

 namespace TeamRock\ApplicationBundle\form;

 use Symfony\Component\Form\AbstractType;
 use Symfony\Component\Form\FormBuilderInterface;

 class personType extends AbstractType{
     public function buildForm(FormBuilderInterface $builder, array      $options){
    $builder->add ('email','email')->add ('name','text')->add('submit','submit');
 }

 public function getName(){
    return 'person';
 }
 }

 ?>

然后在主控制器上

<?php

namespace TeamRock\ApplicationBundle\Controllers\Calvin;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use TeamRock\ApplicationBundle\entity\Person;
use TeamRock\ApplicationBundle\form\PersonType;

class Homepage
{
  public function __invoke(Request $request)
{
    $person = new person();
    $form = $this->createForm(new PersonType(), $person);
    return new Response("Hello, world!", Response::HTTP_OK, array('form'=>$form->createView()));
}


}
?>

我不断得到的错误是

 Attempted to call method "createForm" on class "TeamRock\ApplicationBundle\Controllers\Calvin\Homepage".
500 Internal Server Error - UndefinedMethodException 

任何帮助都是值得赞赏的人,正如我所说,我对PHP和symfony很新,它的学习曲线很大,所以任何帮助或指针都值得赞赏

我一直在关注这些家伙的视频,仅供参考Andrew Perkins Symfony Tutorials

再次感谢您的任何帮助!

1 个答案:

答案 0 :(得分:2)

如何将控制器用作服务?文档始终是一个好的开始:http://symfony.com/doc/current/cookbook/controller/service.html

对于这个问题,控制器使用createForm方法,该方法恰好在:

中定义
namespace Symfony\Bundle\FrameworkBundle\Controller;
use Symfony\Component\DependencyInjection\ContainerAware;
class Controller extends ContainerAware
{
public function createForm($type, $data = null, array $options = array())
{
    return $this->container->get('form.factory')->create($type, $data, $options);
}

如您所见,createForm方法依赖于容器对象来访问form.factory对象。容器是如何注入的?

namespace Symfony\Component\DependencyInjection;

abstract class ContainerAware implements ContainerAwareInterface
{
protected $container;
public function setContainer(ContainerInterface $container = null)
{
    $this->container = $container;
}

因此,我们需要调用$ controller-&gt; setContainer。如果我们以正常方式使用控制器(即不作为服务),则在Symfony \ Component \ HttpKernel \ HttpKernel :: handleRaw()方法中调用setContainer。但由于我们将控制器定义为服务,因此我们需要注入容器:

# services.yml
homepage__controller:
    class: Whatever\Homepage
    calls:
         - [setContainer, ['@service_container']]

因此,将setContainer调用添加到服务定义应该可以为您提供工作代码。虽然直接在您的响应中添加createView可能无法获得所需的结果。它肯定不会给你HTML。但这是一个不同的问题。

当然,真正的问题是为什么要将控制器定义为服务。几乎在所有情况下,答案都是你不应该。它曾经被推荐用于第三方捆绑包,但不再那么多了。如果您查看FOSUserBundle控制器,您会看到相当多的重复代码,因为它们盲目地将控制器作为服务规则。

有时候它是有道理的。我尽量让控制器保持苗条,只注入实际需要的服务。在这个问题中,控制器需要的唯一服务是表单工厂,因此它应该是唯一注入的服务。而且你不应该扩展基本控制器类。

class HomepageController
{
private $formFactory;
public function setFormFactory($formFactory)
{
    $this->formFactory = $formFactory;
}
public function __invoke(Request $request)
{
    $person = new Person();
    $form = $this->formFactory->create(new PersonType(), $person);
    return new Response("Hello, world!", Response::HTTP_OK, array('form'=>$form->createView()));
}
}

services.yml
my__controller:
    class: Whatever\HomepageController
    calls:
         - [setFormFactory, ['@form.factory']]

我喜欢使用setter注入而不是构造注入这些类型的标准服务。我为自己的自定义服务保存了构造。但是如果你愿意,你当然可以使用参数:['@ form.factory']。

最后,如果您只是学习框架以及PHP OOP,那么只需按照文档中的示例进行操作即可。如果没有这种类型的兔子洞,就有很多值得学习的东西。