我正在尝试每月获取用户登录活动,然后在条形图聊天中显示统计信息。但我面临的问题是它没有给我任何数据。我将首先分享我的代码,这将更容易解释我的问题
我的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 这样的东西,所以我可以在酒吧聊天 任何人都可以帮我这个 感谢
答案 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);
}
}