【问题标题】:TypeError when rendering navbar in Symfony 4在 Symfony 4 中渲染导航栏时出现 TypeError
【发布时间】:2019-06-23 17:25:28
【问题描述】:

在渲染添加了用户导航栏的索引页面时,我在 Symfony 4.2.2 项目的 TraceableVoter 构造函数中有一个 TypeError。 Security.yaml 文件附在下面的这个问题上。

所有项目源代码都是来自 Udemy 的 Symfony 4 课程的完整副本。
TypeError 带有以下 Traceback:

传递给 Symfony\Component\Security\Core\Event\VoteEvent::__construct() 的参数 4 必须是整数类型,给定 null,在 /home/vagrant/symfony-01/vendor/symfony/security- 中调用第 40 行的 core/Authorization/Voter/TraceableVoter.php Twig_Environment->render('micro-post/index.html.twig', array('posts' => array(object(MicroPost), object(MicroPost), object(MicroPost), object(MicroPost), object(MicroPost)) , 对象(MicroPost), 对象(MicroPost), 对象(MicroPost), 对象(MicroPost), 对象(MicroPost)))) 在 src/Controller/MicroPostController.php(第 81 行)

来自 intex.html 的导航栏


<nav class="navbar navbar-dark navbar-expand-md sticky-top bg-dark p-0">
    <a class="navbar-brand col-sm-3 col-md-2 mr-0"
       href="{{ path('micro_post_index') }}">Micro Post App</a>
    <div class="w-100 order-1 order-md-0">
        <ul class="navbar-nav px-3">
            {% if is_granted('ROLE_USER') %}
                <li class="nav-item text-nowrap">
                    <a class="nav-link" href="{{ path('micro_post_add') }}">Add new</a>
                </li>
            {% endif %}
        </ul>
    </div>

    <div class="order-2 order-md-1">
        <ul class="navbar-nav px-3">
            {% if is_granted('ROLE_USER') %}
                <li class="nav-item text-nowrap">
                    <a class="nav-link"
                       href="#">{{ app.user.fullName }}</a>
                </li>
                <li class="nav-item text-nowrap">
                    <a class="nav-link"
                       href="{{ path('security_logout') }}">Sign out</a>
                </li>
            {% else %}
                <li class="nav-item text-nowrap">
                    <a class="nav-link"
                       href="{{ path('security_login') }}">Sign in</a>
                </li>
            {% endif %}
        </ul>
    </div>
</nav>

在 MicroPostController.php 中处理索引页面

    /**
     * @Route("/", name="micro_post_index")
     * */
    public function index()
    {
        $html = $this->twig->render('micro-post/index.html.twig', ['posts' => $this->microPostRepository->findAll()]);
        return new Response($html);
    }

security.yaml

security:
    encoders:
        App\Entity\User:
            algorithm: bcrypt
        app_user_provider:
            entity:
                class: App\Entity\User
                property: username
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            anonymous: true
            pattern: ^/
            form_login:
                check_path: security_login
                login_path: security_login
                csrf_token_generator: security.csrf.token_manager
                default_target_path: micro_post_index
            logout:
                path: security_logout
                target: micro_post_index
    access_control:
        - { path: ^/micro-post, roles: ROLE_USER }

这不是重复的问题。转换角色toArray() 不能解决我的问题。 这是完整的堆栈跟踪:

TypeError:
Argument 4 passed to Symfony\Component\Security\Core\Event\VoteEvent::__construct() must be of the type integer, null given, called in /home/vagrant/symfony-01/vendor/symfony/security-core/Authorization/Voter/TraceableVoter.php on line 40

  at vendor/symfony/security-core/Event/VoteEvent.php:31
  at Symfony\Component\Security\Core\Event\VoteEvent->__construct(object(ExampleVoter), object(Request), array('ROLE_USER'), null)
     (vendor/symfony/security-core/Authorization/Voter/TraceableVoter.php:40)
  at Symfony\Component\Security\Core\Authorization\Voter\TraceableVoter->vote(object(AnonymousToken), object(Request), array('ROLE_USER'))
     (vendor/symfony/security-core/Authorization/AccessDecisionManager.php:73)
  at Symfony\Component\Security\Core\Authorization\AccessDecisionManager->decideAffirmative(object(AnonymousToken), array('ROLE_USER'), object(Request))
     (vendor/symfony/security-core/Authorization/AccessDecisionManager.php:60)
  at Symfony\Component\Security\Core\Authorization\AccessDecisionManager->decide(object(AnonymousToken), array('ROLE_USER'), object(Request))
     (vendor/symfony/security-core/Authorization/TraceableAccessDecisionManager.php:61)
  at Symfony\Component\Security\Core\Authorization\TraceableAccessDecisionManager->decide(object(AnonymousToken), array('ROLE_USER'), object(Request))
     (vendor/symfony/security-http/Firewall/AccessListener.php:67)
  at Symfony\Component\Security\Http\Firewall\AccessListener->handle(object(GetResponseEvent))
     (vendor/symfony/security-bundle/Debug/WrappedListener.php:46)
  at Symfony\Bundle\SecurityBundle\Debug\WrappedListener->handle(object(GetResponseEvent))
     (vendor/symfony/security-bundle/Debug/TraceableFirewallListener.php:35)
  at Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener->handleRequest(object(GetResponseEvent), object(Generator))
     (vendor/symfony/security-http/Firewall.php:90)
  at Symfony\Component\Security\Http\Firewall->onKernelRequest(object(GetResponseEvent))
     (vendor/symfony/security-bundle/EventListener/FirewallListener.php:48)
  at Symfony\Bundle\SecurityBundle\EventListener\FirewallListener->onKernelRequest(object(GetResponseEvent), 'kernel.request', object(TraceableEventDispatcher))
     (vendor/symfony/event-dispatcher/Debug/WrappedListener.php:111)
  at Symfony\Component\EventDispatcher\Debug\WrappedListener->__invoke(object(GetResponseEvent), 'kernel.request', object(EventDispatcher))
     (vendor/symfony/event-dispatcher/EventDispatcher.php:212)
  at Symfony\Component\EventDispatcher\EventDispatcher->doDispatch(array(object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener)), 'kernel.request', object(GetResponseEvent))
     (vendor/symfony/event-dispatcher/EventDispatcher.php:44)
  at Symfony\Component\EventDispatcher\EventDispatcher->dispatch('kernel.request', object(GetResponseEvent))
     (vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php:145)
  at Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher->dispatch('kernel.request', object(GetResponseEvent))
     (vendor/symfony/http-kernel/HttpKernel.php:126)
  at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
     (vendor/symfony/http-kernel/HttpKernel.php:67)
  at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
     (vendor/symfony/http-kernel/Kernel.php:198)
  at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
     (public/index.php:25)

【问题讨论】:

标签: php html symfony authentication symfony4


【解决方案1】:

对您的 MicroPostController.php(索引操作)有一些评论,

  • 当你渲染模板视图时,你只需要做$this-&gt;render('path_to_template);而不是$this-&gt;twig-&gt;render('path_to_template)
  • 您不必将 Twig 视图传递给任何变量并返回 Response()

  • 如果您想在 Symfony 4.x 中使用 Entity Repository,请使用 Dependency Injections strong> 所以你的 index 需要一个参数,比如 public

function index(MicroPostRepository $microPostRepository) {}

那你的控制器一定是这样的

/**
 * @Route("/", name="micro_post_index")
 * */
public function index(MicroPostRepository $microPostRepository)
{
    return $this->render('micro-post/index.html.twig', [
        'posts' => $microPostRepository->findAll()
    ]);
}

最后,要解决问题,请检查您的 User Entity 并将您的 Roles getters 替换为

public function getRoles()
{
    return $this->roles->toArray();
}

要创建用户实体,最佳做法是使用 Maker Bundle 并避免此错误

php bin/console make:user

【讨论】:

  • 不幸的是,这不起作用。首先,return $this-&gt;roles-&gt;toArray(); 不会影响此错误,因为 $roles 已经是 ArrayCollection 类型。而 $microPostRepository 是 MicroPostController 的一个属性,所以我像 $this->$microPostRepository 一样传递它
【解决方案2】:

给出了错误的 app.js 路径 - build\js\app.js。 通过向基本模板添加有效的app.js 路径解决:

base.html.twig

...

{% block javascripts %}
    <script src="{{ asset('build/app.js') }}"></script>
{% endblock %}

</body>

【讨论】:

    【解决方案3】:

    我也有同样的问题。 TraceableVoter-&gt;vote 方法中有 $result 变量。它应该返回一个整数。我转储了这个变量,真的有int 0。但由于某些原因,VoteEvent 类将此值视为 null。因此,在TraceableVoter的第38行之后,我添加了intval($result);

    public function vote(TokenInterface $token, $subject, array $attributes)
    {
        $result = $this->voter->vote($token, $subject, $attributes);
    
        $result = intval($result);//here
    
        $this->eventDispatcher->dispatch('debug.security.authorization.vote', new VoteEvent($this->voter, $subject, $attributes, $result));
    
        return $result;
    }
    

    我是 symfony 的新手,所以我不知道我的决定是否正确,但它确实有效。

    【讨论】:

      【解决方案4】:

      确保您没有内部有函数没有返回的投票者。

      当您的投票过程的结果为空时会发生此错误。

      【讨论】:

        【解决方案5】:

        我认为 Alex_B 是对的。问题是 Voter - 它返回 null。如果你在第 43 课(is_granted)上,你有 ExampleVoter 和空方法投票。所以我刚刚让它像这样返回 0 的 false:

        App\Security\ExampleVoter.php

        namespace App\Security;
        
        use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
        use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
        
        class ExampleVoter implements VoterInterface
        {
        
          public function vote(TokenInterface $token, $subject, array $attributes)
          {
        
          return false;
        
          }
        }
        

        一切正常。我也是 symfony 的新手,希望它能解决你的问题。

        【讨论】:

          【解决方案6】:

          在默认的 symfony 设置中,可能有对 VoterInterface 的覆盖,你可以在 src/Security/ExampleVoter.php 中找到它

          public function vote(TokenInterface $token, $subject, array $attributes)
              {
                  // TODO: Implement vote() method.
              }
          

          这里的问题要么返回 0;要么返回 0;或删除文件夹以停止覆盖。

          【讨论】:

            猜你喜欢
            • 2015-05-12
            • 1970-01-01
            • 2016-07-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多