QueryBuilder每月统计创建的用户数-Symfony 3.4

时间:2018-08-02 15:27:07

标签: php sql symfony statistics query-builder

嘿,我正在尝试进行统计,我想用每个飞蛾的已创建帐户数来制作图形,但是我不知道该怎么做...

现在我的项目如下:

 ProfileRepo :
 namespace AppBundle\Repository;


 use Doctrine\ORM\EntityRepository;

 class ProfileRepository extends EntityRepository
 {
function countNumberUsersPerMonth($year, $month) {
    $query = $this->createQueryBuilder('p')
        ->Where('YEAR(p.created_at) = ?', $year)
        ->andWhere('MONTH(p.created_at) = ?', $month)
        ->getQuery();

    return $query->getOneOrNullResult();
}
}

我的控制器(这里的user_month很重要):

/**
* User controller.
*
* @Security("has_role('ROLE_ADMIN')")
*/
class GraphicController extends Controller
{
/**
 * Lists all user entities.
 *
 * @Route("/graphic", name="graphic")
 */
public function GraphicShow()
{
    $em = $this->getDoctrine()->getManager();

    $users = $em->getRepository('AppBundle:User')->countUsers();
    $not_logged = $em->getRepository('AppBundle:User')->countNotActiveUsers();
    $logged = $em->getRepository('AppBundle:User')->countActiveUsers();
    //$user_month = $em->getRepository('AppBundle:Profile')->countNumberUsersPerMonth(2018, 07);

    $not_logged_result = $not_logged["number"] / $users["number"] * 100;
    $logged_result = $logged["number"] / $users["number"] * 100;

    return $this->render('admin/user/pie_stats.html.twig', array(
        //'user_month' => $user_month,
        'user_not_logged' => $not_logged_result,
        'user_logged' => $logged_result,
        'users' => $users,
        'loggedAs' => $this->getUser(),
        'alert' => 0,
    ));
}

}

个人资料实体:

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

 /**
 * Profile
 *
* @ORM\Table(name="profile", uniqueConstraints=
{@ORM\UniqueConstraint(name="profile_id_uindex", columns={"id"})})
* @ORM\Entity(repositoryClass="AppBundle\Repository\ProfileRepository")
*/
class Profile implements \JsonSerializable
{
/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer", nullable=false)
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="IDENTITY")
 * @ORM\OneToOne(targetEntity="User", inversedBy="Profile")
 */
protected $id;

/**
 * @var string
 *
 * @ORM\Column(name="resume", type="text", length=65535, nullable=true)
 */
protected $resume;

/**
 * @var string
 *
 * @Assert\Image()
 * @ORM\Column(name="avatar_path", type="string", length=255, nullable=true)
 */
protected $avatarPath;

/**
 * @var \DateTime
 *
 * @ORM\Column(name="last_connexion", type="datetime", nullable=false)
 */
protected $lastConnexion;

/**
 * @var \DateTime
 *
 * @ORM\Column(name="birth", type="datetime", nullable=false)
 */
protected $birth;

/**
 * @var string
 *
 * @ORM\Column(name="email", type="string", length=255, nullable=false, unique=true)
 */
protected $email;

/**
 * @var integer
 *
 * @ORM\Column(name="level", type="integer", nullable=false)
 */
protected $level = '1';

/**
 * @var string
 *
 * @ORM\Column(name="phone", type="string", length=60, nullable=true, unique=true)
 * @Assert\Regex(
 *     pattern="/(0|\+)[1-9]([-. ]?[0-9]{2}){4}/",
 *     message="You need to put a french number ! Starting with 0 or +33 !",
 * )
 */
protected $phone;

/**
 * @var string
 *
 * @ORM\Column(name="language", type="text", length=65535, nullable=true)
 */
protected $language;

/**
 * @var boolean
 *
 * @ORM\Column(name="is_male", type="boolean", nullable=false)
 */
protected $isMale = '1';

/**
 * @var \DateTime
 *
 * @ORM\Column(name="created_account", type="datetime", nullable=false)
 */
protected $createdAccount = 'CURRENT_TIMESTAMP';

/**
 * @return int
 */
public function getId()
{
    return $this->id;
}

/**
 * @param int $id
 */
public function setId($id)
{
    $this->id = $id;
}

/**
 * @return string
 */
public function getResume()
{
    return $this->resume;
}

/**
 * @param string $resume
 */
public function setResume($resume)
{
    $this->resume = $resume;
}

/**
 * @return string
 */
public function getAvatarPath()
{
    return $this->avatarPath;
}

/**
 * @param string|null
 */
public function setAvatarPath($avatarPath)
{
    $this->avatarPath = $avatarPath;
}

/**
 * @return \DateTime
 */
public function getLastConnexion()
{
    return $this->lastConnexion;
}

/**
 * @param \DateTime $lastConnexion
 */
public function setLastConnexion(\DateTime $lastConnexion)
{
    $this->lastConnexion = $lastConnexion;
}

/**
 * @return \DateTime
 */
public function getBirth()
{
    return $this->birth;
}

/**
 * @param \DateTime $birth
 */
public function setBirth(\DateTime $birth)
{
    $this->birth = $birth;
}

/**
 * @return string
 */
public function getEmail()
{
    return $this->email;
}

/**
 * @param string $email
 */
public function setEmail($email)
{
    $this->email = $email;
}

/**
 * @return int
 */
public function getLevel()
{
    return $this->level;
}

/**
 * @param int $level
 */
public function setLevel($level)
{
    $this->level = $level;
}

/**
 * @return string
 */
public function getPhone()
{
    return $this->phone;
}

/**
 * @param string|null
 */
public function setPhone($phone)
{
    $this->phone = $phone;
}

/**
 * @return string
 */
public function getLanguage()
{
    return $this->language;
}

/**
 * @param string $language
 */
public function setLanguage($language)
{
    $this->language = $language;
}

/**
 * @return \DateTime
 */
public function getCreatedAccount()
{
    return $this->createdAccount;
}

/**
 * @param \DateTime $createdAccount
 */
public function setCreatedAccount(\DateTime $createdAccount)
{
    $this->createdAccount = $createdAccount;
}

/**
 * @return bool
 */
public function isMale()
{
    return $this->isMale;
}

/**
 * @param bool $isMale
 */
public function setIsMale($isMale)
{
    $this->isMale = $isMale;
}

function jsonSerialize()
{
    return array(
        "id"       => $this->id,
        "male"  => $this->isMale,
        "language" => $this->language,
        "level" => $this->level,
        "email" => $this->email,
        "resume" => $this->resume,
    );
}
}

最后确定我的渲染效果(可以正常工作,但默认情况下让值)

{% extends 'admin/user/pie_donuts.html.twig' %}
{% block javascripts_stats %}
<script type="text/javascript">
/* -------------------------------------------------------------------
-----------
*
*  # Echarts - Area charts
*
*  Demo JS code for echarts_areas.html page
*
* ---------------------------------------------------------------------------- */


// Setup module
// ------------------------------

var EchartsAreas = function() {


    //
    // Setup module components
    //

    // Area charts
    var _areaChartExamples = function() {
        if (typeof echarts == 'undefined') {
            console.warn('Warning - echarts.min.js is not loaded.');
            return;
        }

        // Define elements
        var area_basic_element = document.getElementById('area_basic');
        var area_stacked_element = document.getElementById('area_stacked');
        var area_reversed_axis_element = document.getElementById('area_reversed_axis');
        var area_multiple_element = document.getElementById('area_multiple');
        var area_values_element = document.getElementById('area_values');
        var area_zoom_element = document.getElementById('area_zoom');


        //
        // Charts configuration
        //

        // Zoom option
        if (area_zoom_element) {

            // Initialize chart
            var area_zoom = echarts.init(area_zoom_element);


            //
            // Chart config
            //

            // Options
            area_zoom.setOption({

                // Define colors
                color: ['#b6a2de','#26A69A','#ffb980','#d87a80'],

                // Global text styles
                textStyle: {
                    fontFamily: 'Roboto, Arial, Verdana, sans-serif',
                    fontSize: 13
                },

                // Chart animation duration
                animationDuration: 2000,

                // Setup grid
                grid: {
                    left: 0,
                    right: 40,
                    top: 35,
                    bottom: 60,
                    containLabel: true
                },

                // Add legend
                legend: {
                    data: ['Users'],
                    itemHeight: 8,
                    itemGap: 20
                },

                // Add tooltip
                tooltip: {
                    trigger: 'axis',
                    backgroundColor: 'rgba(0,0,0,0.75)',
                    padding: [10, 15],
                    textStyle: {
                        fontSize: 13,
                        fontFamily: 'Roboto, sans-serif'
                    }
                },

                // Horizontal axis
                xAxis: [{
                    type: 'category',
                    boundaryGap: false,
                    axisLabel: {
                        color: '#333'
                    },
                    axisLine: {
                        lineStyle: {
                            color: '#999'
                        }
                    },
                    data: ['2017/1/17','2017/1/18','2017/1/19','2017/1/20','2017/1/23','2017/1/24','2017/1/25','2017/1/26','2017/2/3','2017/2/6','2017/2/7','2017/2/8','2017/2/9','2017/2/10','2017/2/13','2017/2/14','2017/2/15','2017/2/16','2017/2/17','2017/2/20','2017/2/21','2017/2/22','2017/2/23','2017/2/24','2017/2/27','2017/2/28','2017/3/1分红40万','2017/3/2','2017/3/3','2017/3/6','2017/3/7']
                }],

                // Vertical axis
                yAxis: [{
                    type: 'value',
                    axisLabel: {
                        formatter: '{value} ',
                        color: '#333'
                    },
                    axisLine: {
                        lineStyle: {
                            color: '#999'
                        }
                    },
                    splitLine: {
                        lineStyle: {
                            color: '#eee'
                        }
                    },
                    splitArea: {
                        show: true,
                        areaStyle: {
                            color: ['rgba(250,250,250,0.1)', 'rgba(0,0,0,0.01)']
                        }
                    }
                }],

                // Zoom control
                dataZoom: [
                    {
                        type: 'inside',
                        start: 30,
                        end: 70
                    },
                    {
                        show: true,
                        type: 'slider',
                        start: 30,
                        end: 70,
                        height: 40,
                        bottom: 0,
                        borderColor: '#ccc',
                        fillerColor: 'rgba(0,0,0,0.05)',
                        handleStyle: {
                            color: '#585f63'
                        }
                    }
                ],

                // Add series
                series: [
                    {
                        name: 'Software',
                        type: 'line',
                        smooth: true,
                        symbolSize: 6,
                        areaStyle: {
                            normal: {
                                opacity: 0.25
                            }
                        },
                        itemStyle: {
                            normal: {
                                borderWidth: 2
                            }
                        },
                        data: [152,156,479,442,654,835,465,704,643,136,791,254,688,119,948,316,612,378,707,404,485,226,754,142,965,364,887,395,838,113,662]
                    },
                ]
            });
        }


        //
        // Resize charts
        //

        // Resize function
        var triggerChartResize = function() {
            area_basic_element && area_basic.resize();
            area_stacked_element && area_stacked.resize();
            area_reversed_axis_element && area_reversed_axis.resize();
            area_multiple_element && area_multiple.resize();
            area_values_element && area_values.resize();
            area_zoom_element && area_zoom.resize();
        };

        // On sidebar width change
        $(document).on('click', '.sidebar-control', function() {
            setTimeout(function () {
                triggerChartResize();
            }, 0);
        });

        // On window resize
        var resizeCharts;
        window.onresize = function () {
            clearTimeout(resizeCharts);
            resizeCharts = setTimeout(function () {
                triggerChartResize();
            }, 200);
        };
    };


    //
    // Return objects assigned to module
    //

    return {
        init: function() {
            _areaChartExamples();
        }
    }
}();


// Initialize module
// ------------------------------

document.addEventListener('DOMContentLoaded', function() {
    EchartsAreas.init();
});

   {%endblock%}

编辑->因此,目标是填充2个我将作为参数传递后的数组,第一个填充日期,因此每个飞蛾的日期(例如,到2017年)以及该月创建的人员填充另一个,所以我不知道如何创建2个数组:每个数组每个月都有一个日期,例如[1.01.2028,1.02.2018,1.03.208 ....],另一个数组[23,21,398。 ..]在所示月份创建的用户对应的女巫 因此,我像这样每月从用户那里开始使用数组:

function countNumberUsersPerMonth($year, $month) {
$query = $this->createQueryBuilder('p')
    ->Where('YEAR(p.created_at) = ?', $year)
    ->andWhere('MONTH(p.created_at) = ?', $month)
    ->getQuery();

return $query->getOneOrNullResult();
}

但是我很确定这不是正确的方法

喜欢:

enter image description here

哦,有人可以为此提供帮助:)

1 个答案:

答案 0 :(得分:1)

首先,更改此内容:

/**
 * @var \DateTime
 *
 * @ORM\Column(name="last_connexion", type="datetime", nullable=false)
 */
protected $lastConnexion;

/**
 * @var \DateTime
 *
 * @ORM\Column(name="created_account", type="datetime", nullable=false)
 */
protected $createdAccount = 'CURRENT_TIMESTAMP';

对此:

//You don't need to write nullable=false, it's the default option.
/**
 * @var \DateTime
 *
 * @ORM\Column(name="last_connexion", type="datetime")
 */
protected $lastConnexion;

/**
 * @var \DateTime
 *
 * @ORM\Column(name="created_account", type="datetime")
 */
protected $createdAccount;

//Wil set/update timestamps on pre-persist/pre-update
/**
 * @ORM\PrePersist
 * @ORM\PreUpdate
 */
public function updatedTimestamps() {
    $this->lastConnexion(new \DateTime());
    //Will occur only once, on pre-persists.
    if($this->createdAccount() == null) {
        $this->setCreation(new \DateTime());
    }
}

要获取每月创建的用户数,您将需要使用基本SQL查询:

src / AppBundle / Repository / ProfileRepository.php

class ProfileRepository extends \Doctrine\ORM\EntityRepository {
            public function countByMonth() {
        try {
            $stmt=$this->getEntityManager()
                       ->getConnection()
                       ->prepare("SELECT CONCAT(YEAR(`p`.`created_account`), '-', MONTH(`p`.`created_account`)) AS `month`, COUNT(`p`.`id`) AS `total` FROM `profile` AS `p` GROUP BY YEAR(`p`.`created_account`), MONTH(`p`.`created_account`)");
            $stmt->execute();
            return $stmt->fetchAll();
        } catch(DBALException $e) {
            return $e;
        }
    }
}

结果应该是这样的:

array:2 [▼
  0 => array:2 [▼
    "month" => "2018-6"
    "total" => "47"
  ]
  1 => array:2 [▼
    "month" => "2018-7"
    "total" => "13"
  ]
]

剩下要做的就是用纯PHP处理您的结果... 应该很容易...;)