【问题标题】:Twig and Doctrine- Count each related entity and display in Twig loopTwig and Doctrine - 计算每个相关实体并在 Twig 循环中显示
【发布时间】:2015-11-26 05:21:14
【问题描述】:

我在教义上有一对多的关系。我想计算每个相关字段并在 Twig for 循环中显示它们

到目前为止

Vp 与 Voters 相关。Vp 有很多 Voters,Voters 有一个 Vp 我想计算每个 Vp 的每个相关选民

 public function getAllVp()
{
    return $this
        ->createQueryBuilder('v')
        ->select('vp.id,COUNT(v.id) as num')
        ->from('Voters', 'v')
        ->join('v.Vp', 'vp')
        ->orderBy('v.id', 'ASC')
        ->getQuery()
        ->getResult()
    ;
}

我想在 Twig 中这样使用

{% for vp in vps %}
 {{ vp.firstname }}
 {{ vp.num }}//number of voters
{% endfor %}

控制器

   $vice_president = $em->getRepository('Bundle:Vp')->getAllVp();

    return $this->render('Bundle:Vp:all_vp.html.twig', array(
        'vps' => $vice_president,
    )); 

教义

 fields:
    firstname:
        type: string
        length: 255
    lastname:
        type: string
        length: 255
    photo:
        type: string
        length: 255

oneToMany:
    voters:
        targetEntity: Voters
        mappedBy: vp   

我收到了这个错误

[Semantical Error] line 0, col 94 near 'vp, Voters v': Error: Class Project\Bundle\DuterteBundle\Entity\Vp 没有名为 Vp 的关联

如何在 Doctrine 中正确实现这一点?

更新

voters.orm.yml

manyToOne:
    vp:
        targetEntity: Vp
        cascade: {  }
        mappedBy: null
        inversedBy: voters
        joinColumn:
            name:  vp_id
            referencedColumnName: id
        orphanRemoval: false 

我可以通过简单地调用相关的'voters'并在 Twig 中添加一个过滤器来实现这一点。但我的目的是计算学说中的数据,在其他模板中重用它或将其转换为 json 以供将来使用,例如在 Angular 中JS

 {% if vp.voters|length > 0 %}
   <tr {% if loop.index is odd %}class="color"{% endif %}>
     <td>{{ vp.id }}</td>
     <td>{{ vp.getFullName() }}</td>
     <td>{{ vp.voters|length|number_format }}</td>  
   </tr>            
{% endif %}

上面是一个工作代码,但我想在 Doctrine 中进行计数,而不是在模板中

预期结果

id  fullname     counts
1   George Bush  45
2   ali gail     1999
4   Mae Young    45
......

【问题讨论】:

  • 拜托,你能发布选民实体的学说映射吗?
  • @Delphine 我会更新我的问题。

标签: symfony doctrine-orm twig


【解决方案1】:

首先,您可以在选民映射中删除mappedBy: null

面向 PHP :

好的,你可以试试这个 PHP 解决方案,在你的实体 Vp 中添加一个新方法,例如:

public function getVotersCount(){
    return count($this->voters);
}

在你的树枝视图中你可以这样做:

{{ vp.getVotersCount() }}

以教义为导向: (http://docs.doctrine-project.org/en/latest/reference/events.html#lifecycle-events)

在您的副总裁实体 orm 映射中:

fields:
    firstname:
        type: string
        length: 255
    lastname:
        type: string
        length: 255
    photo:
        type: string
        length: 255

oneToMany:
    voters:
        targetEntity: Voters
        mappedBy: vp   
lifecycleCallbacks:
    postLoad: [ countVotersOnPostLoad ]

还有一个新属性,一个 getter 和 countVoters 方法:

protected $votersCount;

public function getVotersCount(){

    return $this->votersCount;
}

public function countVotersOnPostLoad ()
{
    $this->votersCount = count($this->voters);
}

在您看来,只需这样做:

{{ vp.votersCount }}

【讨论】:

  • 这绝对是可能的答案。1。你知道如何根据 (get.VotersCount()) 和 2 对它进行排序。在其他模板中,我只想显示投票人数最多的 vp?
  • 也许您可以尝试类似的方法:public function getVpWithMaxVoters(){ return $this -&gt;createQueryBuilder('vp') -&gt;from('Voters', 'v') -&gt;leftJoin('v.Vp', 'vp') -&gt;orderBy('COUNT(v.id', 'DESC') -&gt;getQuery() -&gt;setMaxResult(1) -&gt;getResult() ; } 在您的存储库中但是您应该发布一个新主题
【解决方案2】:

我的解决方法是创建一个服务。

<?php

namespace Project\Bundle\DutBundle\Twig;

class AllVpExtension extends \Twig_Extension
{
 protected $em;

 public function __construct($em)
 {
   this->em = $em;
 }

 public function getFunctions()
{
   return array(
//this is the name of the function you will use in twig
  new \Twig_SimpleFunction('number_votes_vp', array($this, 'b'))
 );
}

public function getName()
{
  //return 'number_employees';
  return 'vp_app_extension';
}   

public function b($id)
{
 $qb=$this->em->createQueryBuilder();
 $qb->select('count(v.id)')
  ->from('DutBundle:Voters','v')
  ->join('v.vp','c')
  ->where('c.id = :x')
  ->setParameter('x',$id);
$count = $qb->getQuery()->getSingleScalarResult(); 
return $count;
}

}

现在为了统计每个vp的相关选民,我可以调用一个服务并将结果发送给twig

  public function all_vpAction()
{

    $em = $this->getDoctrine()->getManager();

    $vice_president = $em->getRepository('DutBundle:Vp')->findAll();

    //communicate to service container
    $data = $this->container->get('duterte.twig.vp_app_extension');
    $datas = array();

    foreach ($vice_president as $value) {
       $datas[] = array('id' => $value->getId(),'firstname' => $value->getFirstname()  . ' ' . $value->getLastname(),'numbers' => (int)$data->b($value->getId()));
    }

    $vice = $datas;

    return $this->render('DutBundle:Vp:all_vp.html.twig', array(
        'vps' => $vice,
    ));   

   //or we can wrap this in json

    $serializer = $this->container->get('jms_serializer');

    $jsonContent= $serializer->serialize($vice,'json');

    return $jsonContent;
}

通过此设置,我可以将其包装到 json 中,并使用自定义 twig 过滤器,我可以显示在 Angular 或普通 Twig 模板中排序的数据,或两者兼而有之

顺便说一下,我的看法

{% extends '::base.html.twig' %}

{% block body %}

{% block stylesheets %}
    {{ parent() }}
    <style type="text/css">
        #img-responsive{
        height: 320px;
        /*width: 300px;*/
    }
 </style>
 {% endblock %}
 <div class="section-heading">
    <h2>Best Tandem Of the Day</h2>
 </div>

<div class="row">
    <div class="col-sm-6 col-md-4">
        <div class="thumbnail">
            <img src="/img/dut.jpg" id="img-responsive">
            <div class="caption">
                <h3>President</h3>
            </div>
        </div>
    </div>
    <div class="col-sm-6 col-md-4">
        <div class="thumbnail">
            <img src="/img/unknown.jpg" id="img-responsive">
            <div class="caption">
                <h3>Vice-President</h3>
            </div>
        </div>
    </div>
</div>
<hr />
<div ng-app="myApp" ng-controller="customersCtrl">
  Search Here: <input type="text" placeholder="search" ng-model="searchMe"/><br />
<table class="table">
    //names//
    <thead>
        <tr>
            <th>Full Name</th>
            <th>Middlename</th>
            <th>Lastname</th>
        </tr>
    </thead>
    <tbody>
        <tr ng-repeat="x in names">
            <td>//x.id//</td> 
            <td>//x.firstname//</td>
            <td>//x.numbers//</td>
        </tr>
    </tbody> 
</table>
</div>  
<div class="table-responsive">
    <table class="table table-hover table-bordered table-condensed" id="table1">
        <thead>
            <tr>
                <th>#</th>
                <th>Bet</th>
                <th>Votes</th>
                <!--th>Photo</th-->
            </tr>
        </thead>
        <tbody>
            {% for v in vps | sortbyfield('numbers') %}
                {% if v.numbers > 0 %}
            <tr>
                <td>{{ v.id }}</td>
                <td>{{ v.firstname }}</td>
                <td>{{ v.numbers }}</td>
            </tr>
        {% endif %}
            {% endfor %}
       </tbody>
    </table>
</div>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script src="//code.angularjs.org/1.4.8/angular.js"></script>
<script>
    var app = angular.module('myApp', []);

    app.config(function($interpolateProvider) {
    $interpolateProvider.startSymbol('//');
    $interpolateProvider.endSymbol('//');
    });

    app.controller('customersCtrl',['$scope','$http',function($scope, $http) {
        $http.get("{{ path('vp_president') }}")
        .success(function (response) {
            $scope.names= JSON.parse(response);
        });
   </script>    
 {% endblock %}

【讨论】:

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