如何在laravel中每月获得最近12个月的用户登录数据

时间:2018-01-17 14:58:41

标签: php mysql laravel laravel-5

我正在尝试每月获取用户登录活动,然后在条形图聊天中显示统计信息。但我面临的问题是它没有给我任何数据。我将首先分享我的代码,这将更容易解释我的问题

我的LoginActivity模型

class LogActivity extends Model
{
    protected $table = 'laravel_logger_activity';

    public function logActivity(){
        $videoPerMonth = array();

        for ($i=1; $i<=12; $i++){
            $age= 12 - $i;
            $userPerMonth[$i] = count(LogActivity::whereNotIn('userId', [1])->whereMonth('created_at', '=', date('n') -$age)->get());

        }
     }
    }

在这个我确实得到每个月的用户活动,但这不准确,因为如果你减去12值的第一个月变为负数。而且我没有得到实际的结果。 因此,在阅读了几篇文章后,我将代码更改为

$userPerMonth =count( LogActivity::whereNotIn('userId', [1])->whereMonth('created_at', '>=', Carbon::now()->subMonth(12))->get());
return json_encode($userPerMonth);

但这会变空。我该怎么办?

我希望按月与活动获取数据 例如2017年11月:300,2017年12月:800,1月201日:100 这样的东西,所以我可以在酒吧聊天 任何人都可以帮我这个 感谢

2 个答案:

答案 0 :(得分:2)

我很想以不同的方式解决这个问题,而不是试图每个月在一个循环中获取用户的登录活动。我会获得用户登录活动的日期范围,例如一年。这将导致运行一个SQL查询而不是每个用户12个。获得数据后,您可以遍历结果并将它们分类到数组或集合中。

或者您可以将其作为此SQL语句的等效项。

SELECT COUNT(*) as login_num, DATE_FORMAT(created, '%m') as login_month, user_id
FROM login_tokens
WHERE created_at >= '2017-01-01 00:00:01' AND created_at <= '2017-12-31 23:59:59'
GROUP BY user_id, login_month

我认为要以雄辩的方式做到这一点,你需要做以下事情;

$logActivity = LogActivity::where(‘created_at’, ‘>=’, ‘2017-01-01 00:00:01’)
                            ->where(‘created’, ‘<=’, ’23:59:59’)
                            ->select(\DB:raw(‘COUNT(*) as login_num, DATE_FORMAT(created, '%m') as login_month, user_id’))
                            ->groupBy(‘user_id’)
                            ->groupBy(‘login_month’)
                            ->get();

这种方法的缺点是您必须了解SQL语言,这可能与MySql,SQLite,MSSQL等不同。

如果您删除get()并将其替换为toSql(),则可以回显查询,这是一个有用的提示。

echo LogActivity::where(‘created_at’, ‘>=’, ‘2017-01-01 00:00:01’)
                  ->where(‘created’, ‘<=’, ’23:59:59’)
                  ->select(\DB:raw(‘COUNT(*) as login_num, DATE_FORMAT(created, '%m') as login_month, user_id’))
                  ->groupBy(‘user_id’)
                  ->groupBy(‘login_month’)
                  ->toSql();
dd();

希望有所帮助。

答案 1 :(得分:0)

我把一个简单的课程组合在一起,这个课程或多或少是我认为你所追求的。请注意,use语句可能不太正确,而且我没有运行此代码,因此请将其用作示例。基本上我在这里所做的就是获取当前日期并从现在开始计算前一年。

然后用于在getActivity方法中从数据库中选择数据。创建一个空数组$dateRange用于存储结果,其中键是年份和月份,即2018-02,2018-01,2017-12-12,2017-11等。

接下来我做一个简单的检查,看看我们是否确实从数据库中得到了任何结果,因为如果没有结果,则每个月的登录数为0。

然后得到一个日期范围,好吧我已经换回标准的PHP日期间隔,因为我不知道我头脑中的Carbon语法,但是因为Carbon扩展了PHP&#39; s DateTime它可能应该工作。但是,这里也可能需要一些调整。因此,按月间隔获取两个日期之间的日期范围。

然后循环浏览此日期范围,使用我们之前定义的$hasLoginActivity变量,如果错误,则将格式化为年月的日期范围添加为键,将值添加为零。

如果我们有结果,则添加具有相同格式的日期范围,并从结果中获取数据。当我们从Laravel的ORM中返回一个集合时,我们应该能够再次使用它see Collections docs。将其存储到变量并在尝试访问该属性之前检查我们是否有结果,否则设置为零。您可以跳过此操作并像$loginActivity->where('login_year_month', $date->format('Y-m'))->login_num;一样访问它,但如果这导致尝试访问空值属性时出错,我无法记住我的头脑。

我希望这会有所帮助。

    <?php 

use Carbon;
use DateInterval;
use DatePeriod;
use LogActivity as LogActivityModel;

class LogActivity 
{
    public function annualActivity(): array
    {
        // Get the current date/time and get a year from now.
        $now = new Carbon();        
        $aYearAgo = $now->clone()->subYears(1);

        // Get any login activity from the last year to now.
        $loginActivity = $this->getActivity($aYearAgo, $now);

        $dateRange = [];

        $hasLoginActvity = $loginActivity->count();

        // Get a date range from a year ago to now and loop through them.
        foreach ($this->getDateRange($aYearAgo, $now) as $date) {
            // If we there were no results, then just create the array with a result set of zero.
            if (! $hasLoginActvity) {
                $dateRange[$date->format('Y-m')] = 0;
                continue;
            } 

            $monthActivity = $loginActivity->where('login_year_month', $date->format('Y-m'));

            $loginCount = $monthActivity ? $monthActivity->login-num : 0;

            // Add to the array the date YYYY-MM as the key i.e. 2018-02 and search the collection for the same date.
            $dateRange[$date->format('Y-m')] = $loginCount;
        }        

        // Return the array date with the year and month as the key and a integer as the value.   
        return $dateRange;    
    }

    private function getActivity(Carbon $aYearAgo, Carbon $now)
    {
        return LogActivityModel::where(‘created_at’, ‘>=’, $aYearAgo->format('Y-m-d H:i:s'))
          ->where(‘created_at’, ‘<=’, $now->format('Y-m-d H:i:s'))
          ->select(\DB:raw(‘COUNT(*) as login_num, DATE_FORMAT(created, '%Y-%m') as login_year_month, user_id’))
          ->groupBy(‘user_id’)
          ->groupBy(‘login_month’)
          ->all();
    }

    private function getDateRange($from, $to)
    {
        // Get a the date range between the two dates with an interval of a month.
        return new DatePeriod($from, new DateInterval('P1M') ,$to);
    }
}