J'ai actuellement une table de page_views qui enregistre une ligne chaque fois qu'un visiteur accède à une page, enregistrant l'adresse IP/id de l'utilisateur et l'identifiant de la page elle-même. Je devrais ajouter que la colonne created_at est de type: timestamp, elle inclut donc les heures/minutes/secondes. Lorsque j'essaie des requêtes groupBy, il ne regroupe pas les mêmes jours en raison de la différence en secondes.
created_at page_id user_id
========== ======= =======
10-11-2013 3 1
10-12 2013 5 5
10-13 2013 5 2
10-13 2013 3 4
... ... ...
J'aimerais obtenir des résultats basés sur les vues/jour, afin d'obtenir quelque chose comme:
date views
==== =====
10-11-2013 15
10-12 2013 45
... ...
Je pense avoir besoin de creuser dans les requêtes DB :: raw () pour y parvenir, mais tout aperçu aiderait grandement, merci
Edit: Ajout de la clarification du format created_at.
Je pense avoir trouvé une solution à cela, la clé est la fonction DATE () dans mysql, qui convertit un DateTime en just Date:
DB::table('page_views')
->select(DB::raw('DATE(created_at) as date'), DB::raw('count(*) as views'))
->groupBy('date')
->get();
Cependant, ce n’est pas vraiment une solution Laravel Eloquent, car il s’agit d’une requête brute. Voici ce que j’ai trouvé dans la syntaxe Eloquent. La première où la clause utilise des dates au carbone pour comparer.
$visitorTraffic = PageView::where('created_at', '>=', \Carbon\Carbon::now->subMonth())
->groupBy('date')
->orderBy('date', 'DESC')
->get(array(
DB::raw('Date(created_at) as date'),
DB::raw('COUNT(*) as "views"')
));
Vous pouvez utiliser Carbon (intégré à Laravel)
// Carbon
use Carbon\Carbon;
$visitorTraffic = PageView::select('id', 'title', 'created_at')
->get()
->groupBy(function($date) {
return Carbon::parse($date->created_at)->format('Y'); // grouping by years
//return Carbon::parse($date->created_at)->format('m'); // grouping by months
});
Voici comment je le fais. Un petit exemple, mais a rendu ma requête beaucoup plus facile à gérer
$visitorTraffic = PageView::where('created_at', '>=', \Carbon\Carbon::now->subMonth())
->groupBy(DB::raw('Date(created_at)'))
->orderBy('created_at', 'DESC')->get();
Comme la plupart des problèmes de base de données, ils doivent être résolus en utilisant la base de données.
En stockant les données que vous souhaitez regrouper et en utilisant des index, vous pouvez obtenir une méthode efficace et claire pour résoudre ce problème.
$table->tinyInteger('activity_year')->unsigned()->index();
$table->smallInteger('activity_day_of_year')->unsigned()->index();
<?php
namespace App\Models;
use DB;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
class PageView extends Model
{
public function scopePerDay($query){
$query->groupBy('activity_year');
$query->groupBy('activity_day_of_year');
return $query;
}
public function setUpdatedAt($value)
{
$date = Carbon::now();
$this->activity_year = (int)$date->format('y');
$this->activity_day_of_year = $date->dayOfYear;
return parent::setUpdatedAt($value);
}
$viewsPerDay = PageView::perDay()->get();
J'ai eu le même problème, j'utilise actuellement Laravel 5.3.
J'utilise DATE_FORMAT()
->groupBy(DB::raw("DATE_FORMAT(created_at, '%Y-%m-%d')"))
J'espère que cela vous aidera.
Vous pouvez filtrer les résultats en fonction de la date formatée en utilisant mysql ( Voir ici pour l'aide de Mysql/Mariadb ) et utiliser quelque chose comme ceci dans laravel-5.4:
Model::selectRaw("COUNT(*) views, DATE_FORMAT(created_at, '%Y %m %e') date")->groupBy('date')->get();
Pour regrouper des données selon DATE au lieu de DATETIME, vous pouvez utiliser la fonction CAST.
$visitorTraffic = PageView::select('id', 'title', 'created_at')
->get()
->groupBy(DB::raw('CAST(created_at AS DATE)'));
Attention: code non testé.
$dailyData = DB::table('page_views')
->select('created_at', DB::raw('count(*) as views'))
->groupBy('created_at')
->get();
Utiliser Laravel 4.2 sans carbone
Voici comment saisir les dix derniers jours et compter chaque ligne avec le même jour created_at timestamp.
$q = Spins::orderBy('created_at', 'desc')
->groupBy(DB::raw("DATE_FORMAT(created_at, '%Y-%m-%d')"))
->take(10)
->get(array(
DB::raw('Date(created_at) as date'),
DB::raw('COUNT(*) as "views"')
));
foreach ($q as $day) {
echo $day->date. " Views: " . $day->views.'<br>';
}
J'espère que cela t'aides
dans mysql vous pouvez ajouter le mot clé MONTH ayant le paramètre timestamp
Payement::groupBy(DB::raw('MONTH(created_at)'))->get();
J'ai construit un paquet laravel pour faire des statistiques: https://github.com/Ifnot/statistics
Il est basé sur éloquent, carbone et indicateurs, il est donc très facile à utiliser. Cela peut être utile pour extraire les indicateurs groupés par date.
$statistics = Statistics::of(MyModel::query());
$statistics->date('validated_at');
$statistics->interval(Interval::$DAILY, Carbon::createFromFormat('Y-m-d', '2016-01-01'), Carbon::now())
$statistics->indicator('total', function($row) {
return $row->counter;
});
$data = $statistics->make();
echo $data['2016-01-01']->total;
`` `
Je sais que c'est une vieille question et qu'il y a plusieurs réponses. Cependant, selon les docs et mon expérience sur laravel ci-dessous, c’est la bonne "méthode éloquente" de gestion
Dans votre modèle, ajoutez un mutateur/accélérateur comme celui-ci.
public function getCreatedAtTimeAttribute()
{
return $this->created_at->toDateString();
}
Une autre méthode consiste à convertir les colonnes. Dans votre modèle, remplissez le tableau $cast
.
$casts = [
'created_at' => 'string'
]
Le problème ici est que vous ne pourrez plus utiliser Carbon sur ce modèle car Eloquent transformera toujours la colonne en chaîne.
J'espère que ça aide :)
Je résous le problème de cette façon.
$totalView = View::select(DB::raw('Date(read_at) as date'), DB::raw('count(*) as Views'))
->groupBy(DB::raw('Date(read_at)'))
->orderBy(DB::raw('Date(read_at)'))
->get();