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.
Related
I want to join 2 tables, t_admin and t_article using eloquent laravel. So this is table t_admin:
id_adm| name | email
-------------------------
4 | Arya | arya#mail.com
7 | Andrea | andrea#mail.com
12 | Adibah | adibah#mail.com
table t_article:
id_article | id_admin | title
--------------------------------
1 | 4 | AAA
2 | 12 | BBB
3 | 7 | CCC
based on that tables, t_admin.id_adm = t_article.id_admin.
This is my model
Admin.php
class Admin extends Model
{
protected $fillable = [
'id_adm','name','email',
];
protected $table = 't_admin';
}
Article.php
class Article extends Model
{
protected $fillable = [
'id_article','id_admin','title',
];
protected $table = 't_article';
}
Create a relationship in your Admin Model:
Note: I am assuming that an Admin can have many article.
public function articles(){
return $this->hasMany('App\Article', 'id_admin');
}
Then, whenever you want to get all articles that belong to an Admin, do this:
$adminArticles = Admin::find($adminId)->articles
In a scenario where an Admin can only have one article, do this instead:
public function article(){
return $this->hasOne('App\Article', 'id_admin');
}
Then, whenever you want to get the article that belongs to an Admin, do this:
$adminArticle = Admin::find($adminId)->article
Read here for more information.
You could also use Laravel's Query Builder to write join queries yourself.
In your case, you would do this:
$adminArticles = DB::table('t_admin')
->join('t_article', 't_admin.id_adm', '=', 't_article.id_admin')
->select('t_admin.*', 't_article.title')
->get();
Add the relationship to the models assuming its one to many
class Admin extends Model
{
protected $fillable = [
'id_adm','name','email',
];
protected $table = 't_admin';
/**
* Get the articles for admin.
*/
public function articles()
{
return $this->hasMany('App\Article');
}
}
class Article extends Model
{
protected $fillable = [
'id_article','id_admin','title',
];
protected $table = 't_article';
/**
* Get the user for the article post.
*/
public function user()
{
return $this->belongsTo('App\Admin');
}
}
You can retrieve them by
$articles = App\Admin::find(1)->articles;
foreach ($articles as $article) {
//
}
I have a table without 'primary ID', ex.
+---------+----------+------------+------------+
| user_id | point_id | created_at | updated_at |
+---------+----------+------------+------------+
And I have records:
1 ..| 200 | (date) | (date)
14 | 300 | (date) | (date)
1 ..| 200 | (date) | (date)
Now I want delete only one record to get:
1 ..| 200 | (date) | (date)
14 | 300 | (date) | (date)
I tryied:
UserPoint::where( 'point_id', $reqId )->where( 'user_id', $userId )->first()->delete();
But it always remove all record with this params ... Anyone can help?
EDIT: My UserPoint model
use Illuminate\Database\Eloquent\Model;
class UserPoint extends Model {
protected $table = 'point_user';
public function scopeUsed($query){
return $query->where('amount', '<', 0);
}
public function scopeEarned($query){
return $query->where('amount', '>', 0);
}
public function about(){
return $this->hasOne('\App\Point', 'id', 'point_id');
}
}
The way you are trying to achieve this deletion is somewhat wrong as it does not follow the rules of data integrity . Deleting a child table in your case would impose what we call an orphaned table.
However the correct way of deleting that record would be to first associate this table to its parent related table in this case as below:
Class User extends Model {
public function points() {
return $this->hasMany(UserPoint::class)
}
}
then in your UserPoint Class or Model you then need to map your relation.
class UserPoint extends Model {
protected $table = 'point_user';
// I have added this part
public function users() {
return $this->belongsTo(User::class)
}
public function scopeUsed($query){
return $query->where('amount', '<', 0);
}
public function scopeEarned($query){
return $query->where('amount', '>', 0);
}
public function about(){
return $this->hasOne('\App\Point', 'id', 'point_id');
}
}
This way you when deleting the Model or Item you can simply do the below:
// Inject your User in the constructor or function - lets say you names it User $user
$user->points->delete();
I suggest you also look at Eloquent's association and sync methods when working with relations this way you always know that the related Models are on sync and there re no orphaned children in the database which in Enterprise Design is a huge problem as accuracy and Data intergrity is everything .
I have just started using Laravel Eloquent and stuck at retrieving some data. It would be great if someone can guide me.
I have two tables (not mentioning user table)
Institutes:
id |name | user_id
1 |abc |22
2 |xyz |32
Now institute2 (xyz) has following programs
Programs:
id |institute_id| name | admission_open|
1 | 2 |exp1 | 1 |
2 | 2 |exp2 | 0 |
Institute.php
class Institute extends Eloquent
{
protected $table = 'institutes';
public function programs(){
return $this->hasMany('Program');
}
}
Program.php
class Program extends Eloquent
{
protected $table = 'programs';
public function institute()
{
return $this->belongsTo('Institute');
}
}
What I want:
I want to get name of institutes for which admissions (admission_open =1) are open in programs table.
How should I write query for that.do I have to join tables?
$tests = Programs::where('admission','1')->get();
Now after you get object you can loop
foreach($tests as $test) {
$test->institute->name;
}
There are a lot of ways to do this. Like user #ujwal dhakal said or with joins, but I prefer this:
Institute:::whereHas('program', function($query) {
$query->where('admission', '=',1);
})->get();
$institutions = Institute:::whereHas('programs', function($query) {
$query->where('admission_open', '=',1);
})->get();
Hope this helps
You can try
$programs = Program::where('admission_open','1')->with('institute')->get();
OR
$programs = Program::where('admission_open','=','1')->with('institute')->get();
$programs will have Program objects with admission_open = 1 and institute data
foreach($programs as $program){
echo $program->institute->name;
}
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;
}
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;