I'm trying to figure out how I can do a query within a query. (if that even makes sense) I want to grab all the activities. For each activity I want to get the count of users that did the activity. Then I want to order all the activities in DESC order based on the amount of users that did each activity. I'm basically making a "Popular Activities Page" where I show the all activities starting with the activity done by the most users.
I have 3 main tables for this
users
| id | name | password | email | created_at |
activities
| id | title | description | created_at |
resource This is a table I'm using for posts which shows which user did which activity. (Users can show what activities they did, and attach media and locations to the post)
| id | user_id | activity_id | media_id | location_id | created_at |
Here are my models for each table
User Model
class User extends Eloquent {
protected $table = 'users';
/**
* get the activities associated with the given user
* #return mixed
*/
public function activities()
{
return $this->belongsToMany('Acme\Activities\Activity', 'resource', 'activity_id');
}
public function posts(){
return $this->hasMany('Acme\Resource\Resource');
}
public function media()
{
return $this->hasMany('Acme\Media\Media');
}
public function locations()
{
return $this->hasMany('Acme\Locations\Location');
}
}
Activity Model
class Activity extends Eloquent {
protected $table = 'activities';
public function posts(){
return $this->hasMany('Acme\Resource\Resource', 'resource_id');
}
/**
* get the users associated with the given activity card
* #return mixed
*/
public function users()
{
return $this->belongsToMany('Acme\Users\User', 'resource', 'user_id');
}
}
Resource Model
class Resource extends Eloquent {
protected $table = 'resource';
public function user()
{
return $this->belongsTo('Acme\Users\User', 'user_id');
}
public function activities()
{
return $this->belongsTo('Acme\Activities\Activity', 'activity_id');
}
public function media()
{
return $this->hasMany('Acme\Media\Media', 'media_id');
}
public function locations()
{
return $this->belongsTo('Acme\Locations\Location', 'location_id');
}
}
I know I can get all activities using
Activity::get()
I can get a user count for a specific activity using
User::whereHas('resource', function($q) use ($activity_id){
$q->where('activity_id', $activity_id);
})->get()->count();
but I don't know how I can put all of this together in order to get all Activities sorted by user count, starting with the activity with the highest user count.
How would I make this query using eloquent?
Thanks in advance!
try
Resource::select(DB::raw('*, COUNT(distinct(user_id)) as user_count'))->group_by('activity_id')->order_by('user_count', 'desc')->get();
You could then do this
$results = Resource::select(DB::raw('*, COUNT(distinct(user_id)) as user_count'))->group_by('activity_id')->order_by('user_count', 'desc')->get();
foreach ($results as $result) {
$activity = Activity::where('id','=',$result->activity_id)->first();
// do stuff to display data for this activity like
// $activity->title or $activity->description
$count = $result->user_count;
}
Related
Hello i am new here and not a native English speaker so please forgive me for any mistakes on my grammar and on my question formatting.
I am building an app with php using laravel framework 5.4 version.
The web app is very simple its for reviewing articles and users that posts articles.
I would like to learn how i can union the results of the functions within my model.
I want the allReviews function from user model to return the reviews the user has mixed with the reviews his articles have orderby createdtime.
let me explain better.
here is my 3 main tables:
Users | Articles | Reviews
--------- | --------- | ---------
id | id | id
name | user_id | reviewable_id
email | title | reviewable_type
password | body | reviewtext
etc.. | etc.. | created_time
and here is my models code :
class User extends Model{
protected $table = 'users';
public function articles()
{
return $this->hasMany(Article::class,'user_id');
}
public function reviews(){
return $this->morphMany(Review::class,'reviewable');
}
public function allReviews(){
/*
i want union something like this:
$result = $this->reviews() union
foreach ($this->Articles() as $Article) {
union $Article->reviews();
}
orderby created_time ASC or DESC doesn't matter
return $result
*/
}
}
class Article extends Model{
protected $table = 'articles';
public function user()
{
return $this->belongsTo(User::class,'user_id');
}
public function reviews(){
return $this->morphMany(Review::class,'reviewable');
}
}
class Review extends Model{
protected $table = 'reviews';
public function reviewable(){
return $this->morphTo('reviewable');
}
}
So my question is how i can do the function allReviews from user to work ?
Any help is appreciated :)
Thank You
Calling the $user->reviews property will return all reviewable models. You don't have to UNION anything, Eloquent will take care of that for you.
Try this:
public function allReviews(){
$reviews = new \Illuminate\Database\Eloquent\Collection;
foreach($this->articles as $article)
{
$reviews = $reviews->merge($article->reviews);
}
$reviews = $reviews->merge($this->reviews);
return $reviews;
}
I'm really tired now and I have a feeling you might get the N+1 query problem situation here but it should work for you.
I want to make a relation with 3 table using ORM but cant. My tables
User table
id | userame | name |
1 Ellie Elen
2 Pol Paul
record table
id | user_id| item_id| hour|
1 2 1 3
2 2 2 5
Item table table
id | title
1 item 1
2 item 2
I am using this logic but not work properly
class User Extends Eloquent {
public function record()
{
return $this->hasMany('VolunteerRecord');
}
}
class VolunteerRecord Extends Eloquent {
function item() {
return $this->hasMany('VolunteerItem');
}
}
I cant understand how to do it?
It seems like you want a Many-To-Many relationship between Users and Items but you also want to track hours on the pivot table. So first, you'll define the many-to-many relationships using belongsToMany(), and you'll tell Laravel that you have extra data on your pivot table with the withPivot() function. Your classes will look like this:
class User extends Eloquent {
protected $table = 'users';
public function items() {
return $this->belongsToMany('Item', 'records')->withPivot('hour');
}
}
class Item extends Eloquent {
protected $table = 'items';
public function users() {
return $this->belongsToMany('User', 'records')->withPivot('hour');
}
}
Then, to access the hour field you would do this:
$user = User::first(); // First User
$item = $user->items()->first(); // User's first Item
$hour = $item->pivot->hour; // The 'hour' on the User-Item relationship
Also, your current column naming scheme is correct for Laravel so don't feel like you need to change it. If you change your column names, then you'll need to define them in the belongsToMany() method like this:
$this->belongsToMany('ModelName', 'pivot_table', 'foreign_key', 'other_key');
// For example, in Items::users() you would have this:
$this->belongsToMany('User', 'records', 'users_id', 'items_id');
Finally, I'm assuming that your tables are named users, items, and records. If they are not, then just replace all instances of users, items, and records with your actual table names.
Based on your table names, I'd suggest the following, first of all, change your record table as follows:
id | users_id| items_id| hour|
1 2 1 3
2 2 2 5
And these are the classes for your models:
class Users extends Eloquent
{
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
public function records()
{
return $this->hasMany('Records');
}
}
class Records extends Eloquent
{
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'records';
public function record()
{
return $this->hasOne('Users');
}
public function item()
{
return $this->hasOne('Items');
}
}
class Items extends Eloquent
{
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'items';
public function records()
{
return $this->hasMany('Records');
}
}
These contain the relations for your models.
If you were to select a few records, for each record you can get the user and the item. If you were to select an item, and all records for that item. You can also get the user for each record.
In User Model
public function images()
{
return $this->belongsToMany('Item')->withPivot('hour');
}
In user controller
public function view($username)
{
$user = User::where('name',$username)->firstOrFail();
return View::make('view')->with('user',$user);
}
In view
#foreach ($users->items as $item)
name: {{$image->title}}<br>
hour: {{$image->pivot->hour}}<br>
#endforeach
I have a StandardOverall table with the following columns:
sto_id | sto_transaction_id | sto_standard_id | sto_count | sto_total
and a Standard table with the following columns:
std_standards_id | std_code | std_description | std_notes
sto_standard_id in StandardOverall table is the foreign key to std_standards_id in the Standard table.
I return all the rows from the StandardOverall table that belong to a sto_transaction_id. How can I return the data from the foreign table as well, all in one collection? This code is in the controller:
$transactionID = Session::get('transactionID');
$standardStats = StandardOverall::whereID($transactionID)->get();
The StandardOverall Model:
class StandardOverall extends Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'sto_stat_overall';
protected $primaryKey = 'sto_id';
public function Standards() {
return $this->belongsTo('Standards');
}
public function getStandards() {
return $this->hasOne('Standards', 'std_standards_id', 'sto_standard_id')->with('std_description');
}
public function scopewhereID($query, $transactionID) {
return $query->where('sto_transaction_id', $transactionID);
}
}
So I want the count and total columns from standards overall table and the linked code and description from the standard table. Is this possible?
You may try this:
$transactionID = Session::get('transactionID');
$standardStats = StandardOverall::with(['standards' => function($query) {
$query->select(
'std_standards_id', 'std_code', 'std_description', DB::raw('count(*) as count')
)->groupBy('std_standards_id');
}])->whereID($transactionID)->get();
I have a User table and need to allow for users to have a parent user.
the table would have the fields:
id
parent_id
email
password
How would I define this self referencing relationship in Eloquent ORM?
I had some success like this, using your exact DB table.
User Model:
class User extends Eloquent {
protected $table = 'users';
public $timestamps = false;
public function parent()
{
return $this->belongsTo('User', 'parent_id');
}
public function children()
{
return $this->hasMany('User', 'parent_id');
}
}
and then I could use it in my code like this:
$user = User::find($id);
$parent = $user->parent()->first();
$children = $user->children()->get();
Give that a try and let me know how you get on!
I had a chain of self referencing contracts (a contract can be continued by another contract) and also needed self referencing. Each contract has zero or one previous and also zero or one next contract.
My data table looked like the following:
+------------------+
| contracts |
+------------------+
| id |
| next_contract_id |
+------------------+
To define the inverse of a relationship (previous contract) you have to inverse the related columns, that means setting
* foreign key column on the model table
* associated column on the parent table (which is the same table)
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Contract extends Model {
// The contract this contract followed
function previousContract()
{
// switching id and next_contract_id
return $this->belongsTo('App\Contract', 'id', 'next_contract_id');
}
// The contract that followed this contract
function nextContract()
{
return $this->belongsTo('App\Contract');
// this is the same as
// return $this->belongsTo('App\Contract', 'next_contract_id', 'id');
}
}
See http://laravel.com/docs/5.0/eloquent#one-to-one for further details.
Im really new to laravel, and im sure im doing something wrong
I have 2 tables. Cities And users_metadata
My cities table look like this
id | City |
1 | New York |
1 | Los Angeles |
users metadata
user_id | firt name | last name | cities_id |
1 | Jonh | Doe | 2 |
So my problem is when i create a relation i get New York, becaus the city id is matched with the user id
City model
class City extends Eloquent
{
public static $table = "cities";
public function profile()
{
return static::has_many('Profile');
}
}
profile model
class Profile extends Eloquent
{
public static $timestamps = false;
public static $table = "users_metadata";
public static $key = "user_id";
public function city()
{
return static::has_one('City');
}
}
error
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'profile_id' in 'where clause'
SQL: SELECT * FROM `cities` WHERE `profile_id` = ? LIMIT 1
Bindings: array (
0 => 1,
)
If i dont pass the id to has one i get the following error
Okay i understand this.
So my questions is am i able to pass the foreign key cities_id somehow in my relation to match? Or im doing it all wrong? Can someone give me a basic example?
thank you folks
Try this:
City model
class City extends Eloquent
{
public static $table = "cities";
public function profile()
}
Profile model
class Profile extends Eloquent
{
public static $timestamps = false;
public static $table = "users_metadata";
public static $key = "user_id";
public function city()
{
return static::belongs_to('City');
}
}
I ran into the same problem thinking I should use has_one, but I needed to use belongs_to. user1808639's probably didn't work because you still had a 'has_many' in the city model.
Try this:
class Profile extends Eloquent
{
public function city()
{
return $this->belongs_to('City'); // city_id in the table
}
}
Laravel has a way of detecting foreign keys automatically. So for your database schema... this models should work fine
Try the following
user_id | firt name | last name | city_id | //city not cities
1 | Jonh | Doe | 2 |
-
class Profile extends Eloquent
{
public static $timestamps = false;
public static $table = "users_metadata";
public function city()
{
return $this->has_one('City');
}
}
/
class City extends Eloquent
{
public static $timestamps = false;
public function profiles()
{
return $this->has_many('Profile');
}
}
The table rows shouldn't contain whitespaces. So rename "firt name" | "last name" in "firstname" | "lastname". The SQL-error shows me that you're calling the model in the reverse way like City::find(1) in this case Laravel expects inside the "Cities" table the foreign key for the profiles that would be usually "profile_id".
I guess you're looking for something like this:
$user_id = 1;
$user = Profile::find($user_id);
echo $user->firstname." ".$user->lastname." lives in ".$user->city->city;