【问题标题】:Compile Error: Cannot declare class because the name is already in use编译错误:无法声明类,因为该名称已在使用中
【发布时间】:2019-08-23 03:34:17
【问题描述】:

我正在将网站从 symfony 2.6 迁移到 3.4,但我在注册表格和 FOSUserBundle 方面遇到了一些问题。我有这个错误弹出。我检查了他的代码,在他的 src\Pix\UserBundle\Form\RegistrationFormType.php 下看到了另一个文件夹“Type”,其中有一个同名文件:“RegistrationFormType.php”

我尝试使用从那里获取的最新样式修改表单:https://github.com/symfony/symfony/blob/2.8/UPGRADE-2.8.md#form

app/config/config.yml:

fos_user:
    db_driver: orm
    firewall_name: main
    user_class: Pix\UserBundle\Entity\User
    registration:
        form:
            type: Pix\UserBundle\Form\RegistrationFormType
            validation_groups: [ pix_registration, Default ]

Pix/UserBundle/Resources/config/services.yml下的服务文件

services:
    pix_userbundle_registrationformtype:
        class: Pix\UserBundle\Form\Type\RegistrationFormType
        arguments: ["%fos_user.model.user.class%"]
        tags:
            - { name: form.type }

Pix/UserBundle/Form/RegistrationFormType.php:

namespace Pix\UserBundle\Form;

use FOS\UserBundle\Form\Type\RegistrationFormType as BaseRegistrationFormType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;


class RegistrationFormType extends AbstractType
{

    public function __construct($class = "User")
    {
        parent::__construct($class);
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        parent::buildForm($builder, $options);

        $builder
            ->add('username', 'text', array(
                'label' => 'Pseudonyme',
            ))
            ->add('email', 'text', array(
                'label' => 'Adresse mail',
            ))
            ->add('plainPassword', 'repeated', array(
                'type' => 'password',
                'first_options' => array('label' => 'Mot de passe'),
                'second_options' => array('label' => 'Confirmation'),
                'invalid_message' => 'Mot de passe incorrect',
            ))
            ->add('enabled', 'checkbox', array(
                'label' => "Activé",
                'required' => false
            ))

            ->add('firstname', 'text', array(
                'label' => 'Prénom',
            ))
            ->add('lastname', 'text', array(
                'label' => 'Nom',
            ))
            ->add('phone', 'text', array(
                'label' => 'Téléphone',
            ))
            ->add('street', 'text', array(
                'label' => "Adresse postale",
                'required' => true
            ))
            ->add('number', 'text', array(
                'label' => "Numéro d'adresse",
                'required' => true
            ))
            ->add('npa', 'text', array(
                'label' => "Code postal",
                'required' => true
            ))
            ->add('city', 'text', array(
                'label' => "Ville",
                'required' => true
            ))
            ->add('state', 'text', array(
                'label' => "Canton",
                'required' => true
            ))
            ->add('country', 'text', array(
                'label' => "Pays",
                'required' => true
            ))
            ->add('latitude', 'text', array(
                'label' => "Latitude",
                'required' => true
            ))
            ->add('longitude', 'text', array(
                'label' => "Longitude",
                'required' => true
            ))
            ->add('code', 'text', array(
                'label' => 'Code de parrainage',
                'required' => false
            ))
            ->add('pro', 'choice', array(
                'label' => "Professionel",
                'choices'  => array(
                    true => 'Oui',
                    false => 'Non',
                ),
                'expanded' => false,
                'multiple' => false,
                'required' => true
            ))

            ->add('iban', 'text', array(
                'label' => 'IBAN',
                'required' => false
            ))
            ->add('distance', 'text', array(
                'label' => "Rayon d'intervention",
                'required' => false
            ))
            ->add('picture', new DocumentType(), array('required' => false))
            ->add('curriculum', new DocumentType(), array('required' => false))
            ->add('motivation', new DocumentType(), array('required' => false))
            ->add('document', new DocumentType(), array('required' => false))
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Pix\UserBundle\Entity\User'
        ));
    }
    public function getParent()
    {
        return BaseRegistrationFormType::class;
    }
    public function getBlockPrefix()
    {
        return 'pix_userbundle_registrationformtype';
    }
}

最后是 Pix/UserBundle/Form/Type/RegistrationFormType.php:

namespace Pix\UserBundle\Form\Type;

use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use FOS\UserBundle\Form\Type\RegistrationFormType;
use Symfony\Component\Form\AbstractType;
use Pix\UserBundle\Form\DocumentType;
use Pix\UserBundle\Entity\AbilityRepository;
use Symfony\Component\Form\Extension\Core\Type\TextType; 

class RegistrationFormType extends AbstractType
{

    public function __construct($class = "User")
    {
        parent::__construct($class);
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        parent::buildForm($builder, $options);
        $builder->remove('username');
        $builder
            ->add('firstname', TexType::class, array(
                'label' => 'Prénom',
            ))
            ->add('lastname', TexType::class, array(
                'label' => 'Nom',
            ))
            ->add('phone', TexType::class, array(
                'label' => 'Téléphone',
            ))
            ->add('street', 'hidden')
            ->add('number', 'hidden')
            ->add('npa', 'hidden')
            ->add('city', 'hidden')
            ->add('state', 'hidden')
            ->add('country', 'hidden')
            ->add('latitude', 'hidden')
            ->add('longitude', 'hidden')
            ->add('code', TexType::class, array(
                'label' => 'Code de parrainage',
                'required' => false
            ))
            /*
            ->add('contact', 'choice', array(
                'label' => 'Moyen de contact favorisé',
                'choices'  => array(
                    true => 'Par téléphone',
                    false => 'Par e-mail',
                ),
                'expanded' => true,
                'multiple' => false,
                'required' => true
            ))
            */
            ->add('pro', 'choice', array(
                'label' => false,
                'choices'  => array(
                    true => 'Oui',
                    false => 'Non',
                ),
                'expanded' => false,
                'multiple' => false,
                'required' => true
            ))

            ->add('iban', TexType::class, array(
                'label' => 'IBAN',
                'required' => false
            ))
            ->add('distance', TexType::class, array(
                'label' => "Rayon d'intervention",
                'required' => false
            ))
            ->add('picture', new DocumentType(), array('required' => false))
            ->add('curriculum', new DocumentType(), array('required' => false))
            ->add('motivation', new DocumentType(), array('required' => false))
            ->add('document', new DocumentType(), array('required' => false))

            ->add('abilities', 'entity', array(
                'label' => 'Domaines de compétence',
                'attr' => array(
                    'class'=>'form-control multiselect'
                ),
                'class' => 'PixUserBundle:Ability',
                'property' => 'title',
                'multiple' => true,
                'expanded' => true,
                'required' => false,
                'query_builder' => function(AbilityRepository $er) {
                    return $er->getAbilities();
                },
            ))
            ->add('condition', 'checkbox', array('label' => "J'ai lu et j'accepte les conditions générales."))
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Pix\UserBundle\Entity\User',
            'intention'  => 'registration'
        ));
    }
    public function getBlockPrefix()
    {
        return 'pix_userbundle_registrationformtype';
    }
    public function getParent()
    {
    return RegistrationFormType::class;
    }
}

【问题讨论】:

  • 删除这一行 use FOS\UserBundle\Form\Type\RegistrationFormType; - 通过声明您定义或使用名为 RegistrationFormType 的类的 use 语句 - 与此类同名,那么这部分 return RegistrationFormType::class; 是不明确的。
  • 这是两种不同的形式,尽管它们看起来很相似,或者其中一个文件是旧版本并且不需要。无论哪种方式,为什么网站管理员在那里有一个具有相同类名的use 是没有意义的。 FOS\UserBundle\Form\Type\RegistrationFormType 存在吗?请记住,对于 Symfony,他们建议将每个表单放在自己的类中,但它们也应该有可区分的名称。
  • 我遇到了同样的问题。修复命名空间后,错误消息消失了。

标签: php symfony


【解决方案1】:

这主要是因为你的 import 或 use 语句与你定义的类同名:

use FOS\UserBundle\Form\Type\RegistrationFormType;

class RegistrationFormType extends AbstractType
{

以这段代码为例:

namespace foo{

    class class1{

    }

}
namespace bar{
    //use foo\class1;

    class class1{

    }
}

Sandbox

这可以正常工作并且不会产生错误(如预期的那样),但是如果您取消注释此行:

use foo\class1;

输出

<br />
<b>Fatal error</b>:  Cannot declare class bar\class1 because the name is already in use in <b>[...][...]</b> on line <b>14</b><br />

Sandbox

我们应该同意,上面的例子大致相当于你正在做的事情(就是这样)。

所以基本上发生的事情是你定义了这个使用声明:

use FOS\UserBundle\Form\Type\RegistrationFormType; 

这允许您在没有命名空间的情况下使用此类 RegistrationFormType,但由于您还定义了相同的类名,因此您会收到错误(见下文模棱两可)。

你可以给它起别名,像这样:

 use FOS\UserBundle\Form\Type\RegistrationFormType as FOSRegistrationFormType;

然后,当您需要该命名空间中的某些内容时,您只需使用 FOSRegistrationFormType。也就是说,您使用它的唯一地方(也许)就是这种方法:

public function getParent()
{
    return RegistrationFormType::class;
}

我说“也许”是因为它的方式模棱两可。我不知道您是否想要名为RegistrationFormType 的当前对象的类,或者您是否想要FOS\UserBundle\Form\Type\RegistrationFormType::class。 PHP 也不知道这一点。如果它是对象的类,那么只需执行 __CLASS__ 并删除该 use 语句。如果它是另一个(或者你在我看不到的地方需要那个类),那么只需给它取别名并执行FOSRegistrationFormType::class

我同意这个错误消息可能会更好,它应该类似于使用类名RegistrationFormType 是模棱两可的等等。但事实并非如此,所以我们必须处理它......这个让我绊倒了几次,这就是为什么我基本上立即意识到它的原因。

我将分享我对简单沙箱代码的最后修改:

namespace foo{

    class class1{

    }

}
namespace bar{
    use foo\class1 as f;

    class class1{
        public function test(){
            echo f::class;
        }
    }

    (new class1)->test();
}

输出

 foo\class1

Sandbox

显然使用比f 更详细的别名,但是,这显示了如何为它取别名,然后从别名中获取类,类似于您的代码所做的。

PS虽然它很丑,但如果你只使用一次,你没有理由不能只使用完全限定的名称(命名空间/类),只要确保有是领先的\(想想相对路径是如何工作的),如下所示:

  \FOS\UserBundle\Form\Type\RegistrationFormType::class

希望对你有帮助。

【讨论】:

    【解决方案2】:

    由于 services.yml 文件中的配置错误,我遇到了这个错误:

    App\:
        resource: '../src/*'
        exclude: '../src/{Entity,Migrations,Tests,Kernel.php}'
    
    Example\:
        resource: '../src/Example/*'
        public: true
    

    这将导致 Symfony 尝试将 Example 命名空间下的类加载为 App\Example

    您还需要确保将任何自定义命名空间添加到 App 的排除列表中,如下所示:

    App\:
        resource: '../src/*'
        exclude: '../src/{Entity,Migrations,Tests,Kernel.php,Example}'
    

    【讨论】:

      【解决方案3】:

      在为实体形成 Doctrine 缓存时,我遇到了名称冲突。

      在这种情况下会出现冲突(说明性示例):

      class AlphaBeta {}
      

      为其生成一个缓存文件:__CG__AlphaBeta.php

      namespace Alpha;
      
      class Beta {}
      

      还为它生成了一个缓存文件:__CG__AlphaBeta.php,并获得了名称冲突!那些。只存储一个类的缓存,这会引发错误!

      附:实体文件缓存的路径是这样的:./var/cache/prod/doctrine/orm/Proxies

      【讨论】:

        猜你喜欢
        • 2021-08-17
        • 2020-06-21
        • 2023-03-10
        • 2019-07-12
        • 2016-11-03
        • 2020-03-20
        • 2020-10-10
        • 2023-03-14
        • 1970-01-01
        相关资源
        最近更新 更多