Laravel joining two models to User model - php

I have the following tables:
Users
Games
Characters
A user will have one active game at a time, and from that game, will have one active character.
I want to perform the following joi on my authentication table:
SELECT * FROM users
LEFT OUTER JOIN games ON games.ID = users.active_gameid
LEFT OUTER JOIN characters ON characters.ID = games.active_charid
Try to ignore the SELECT * part.
I'd like to perform these joins on my Auth table as soon as the page loads, so I have been using my User model to do the following:
class User extends Eloquent implements UserInterface, RemindableInterface {
public function game() {
return $this->hasOne('game', 'ID', 'active_gameid');
}
}
class game extends Eloquent {
protected $table = "games";
public function character() {
return $this->hasOne('character', 'ID', 'active_charid');
}
}
class character extends Eloquent {
protected $table = "characters";
}
The above doesn't work as outputting the following just returns a NULL value:
var_dump(Auth::user()->game->character);
I have tried to do the obvious checks such as making sure the data is in the table and such and that all seems fine.
Does anyone have any help on where I'm going wrong?
Thank you!

Your relations are wrong:
// User model
public function game()
{
return $this->belongsTo('Game', 'active_gameid', 'ID');
}
// Game model
public function character()
{
return $this->belongsTo('Character', 'active_charid', 'ID');
}
and obviously it won't call your query, but 2 separate queries:
Auth::user()
->game // SELECT * FROM games WHERE ID = ?
->character; // SELECT * FROM characters WHERE ID = ?

Related

Eloquent where clause in JOIN table - Laravel 5.5

I have two models which are connected each other.
class Company extends Model {
public function addresses() {
return $this->belongsToMany('\App\Address', 'address_mapping', 'uid_company', 'uid_address');
}
}
class Address extends Model {
}
In my JOIN table I have a column named active. How can I fetch all active addresses from the company? Or how can I implement a where-clause in the JOIN table?
Thank you!
The table that you call a "JOIN table", usually called a pivot table.
You can fetch all active records by using wherePivot method:
$company = Company::first();
$activeAdresses = $company->addresses()->wherePivot('active', 1);
Or you can directly define the relationship in your model:
class Company extends Model {
public function activeAddresses() {
return $this->belongsToMany('\App\Address', 'address_mapping', 'uid_company', 'uid_address')
->wherePivot('active', 1);
}
}
See section Filtering Relationships Via Intermediate Table Columns in Eloquent documentation

Laravel distinct result

I'm building a PM system, and I have a problem.
This is my PM table:
id, user_id, to, content
Now, in my inbox page I'm fetching all the users that sent me a message.
$pms = DB::table('pm')->select('user_id')->distinct()->where('to', Auth::id())->get();
The problem is if I add more columns to the select method, it won`t be distinct anymore..
You can easily do that using Eloquent and its whereHas() method.
First, define models and the relation in your model:
class Message extends Model {
protected $table = 'pm';
}
class User extends Model {
public function sent_messages() {
return $this->hasMany(Message::class);
}
}
Now, fetch all users that have a related Message models where to column matches your ID:
$usersThatSentMeMessages = User::whereHas('sent_messages', function($query) {
$query->where('to', Auth::id());
});

Relations Laravel 4 with 3 tables using Eloquent

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

Has many through

A Venue has many Subscriptions.
A Subscription has many Subscribers (User).
Theres a pivot table, containing the relation between user_id and subscription_id.
How can I get all Subscribers from a Venue?
I have tried with:
class Venue {
/**
* Members
*/
public function members() {
return $this->hasManyThrough('App\User', 'App\Subscription');
}
}
But it fails with MySQL error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'users.subscription_id' in 'on clause' (SQL: select `users`.*, `sub
scriptions`.`venue_id` from `users` inner join `subscriptions` on `subscriptions`.`id` = `users`.`subscription_id` where `
users`.`deleted_at` is null and `subscriptions`.`venue_id` = 1)
How my Subscription model look:
`Subscription`
class Subscription extends Model {
protected $table = 'subscriptions';
/**
* Subscripers
*/
public function subscribers() {
return $this->belongsToMany('App\User');
}
/**
* Venue
*/
public function venue() {
return $this->belongsTo('Venue');
}
}
Simple question: Why are you using a third model for Subscriptions? It sounds like a normal n:m relation between User and Venue, as already written in the comments above.
class User {
public function venues() {
return $this->belongsToMany('App\Venue');
}
}
class Venue {
public function users() {
return $this->belongsToMany('App\User');
}
}
This constellation actually needs three tables, which are (i gave each model a column name):
users
- id
- name
venues
- id
- name
user_venue
- user_id
- venue_id
But to access the relations, you can simply use the Eloquent magic:
// List of all venues (as Venue models) that are in relation with User with id $id
$venues = User::find($id)->venues()->get();
// Returns the alphabetically first user that has a relation with Venue with id $id
$user = Venue::find($id)->users()->orderBy('name', 'asc')->first();
If you need to store additional information in the pivot table (e.g. when the relation has been established), you can use additional pivot fields:
user_venue
- user_id
- venue_id
- created_at
class User {
public function venues() {
return $this->belongsToMany('App\Venue')->withPivot('created_at');
}
}
class Venue {
public function users() {
return $this->belongsToMany('App\User')->withPivot('created_at');
}
}
// Returns the date of the relations establishment for the alphabetically
// first Venue the User with id $id has a relation to
$created_at = User::find($id)->venues()->orderBy('name', 'asc')->first()->pivot->created_at;
I've never tried to do whatever you are trying to do there, because it seems (with the current information) conceptually wrong. I also don't know if it is possible to set up an own model for a pivot table, but I think it should work if the pivot table has an own primary id column. It could probably be helpful if you've a third model that needs to be connected with a connection of two others, but normally that doesn't happen. So try it with pivot tables, like shown above, first.
Alright, I still don't see a good use case for this, but I can provide you a query that works. Unfortunately I wasn't able to get an Eloquent query working, but the solution should be still fine though.
class Venue {
public function members($distinct = true) {
$query = User::select('users.*')
->join('subscription_user', 'subscription_user.user_id', '=', 'users.id')
->join('subscriptions', 'subscriptions.id', '=', 'subscription_user.subscription_id')
->where('subscriptions.venue_id', '=', $this->id);
if($distinct === true) {
$query->distinct();
}
return $query;
}
}
The relation can be queried just as normal:
Venue::find($id)->members()->get()
// or with duplicate members
Venue::find($id)->members(false)->get()

Where is the proper place to put a user-related function in Laravel 5.0

The relevant portion of my application is set up as follows:
A Users table, with unique user IDs
A Teams table, with unique team IDs
A Team_Membership table, with
a unique ID and a column for a User ID and a Team ID, to denote
that a user belongs to a team.
A user can be on an unlimited number of teams.
I have a function to retrieve an array of the teams a given user belongs to. It would generally be called in the scope of the current logged in user to get their active teams, but will also be used in administrative functions to return the teams of a given user ID.
My first thought was to make the function callable from the user model, so for a given user object, I could do as follows
$teams = $user->get_teams();
or
$teams = User::get_teams($user_id);
But I'm not sure if this is generally considered best practice in Laravel for this type of functionality. Where should this function be located?
Actually, you are talking about something that laravel already does for you if you are using Eloquent.
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $table = 'users';
public function teams()
{
return $this->belongsToMany(Team::class);
}
}
class Team extends Model
{
protected $table = 'teams';
public function users()
{
return $this->belongsToMany(User::class);
}
}
In addition to the users and teams table you would make a pivot table:
team_user
id - integer
team_id - integer
user_id - integer
and laravel does the rest.
$userId = 1;
$user = User::with('teams')->find($userId);
$teams = $user->teams;

Categories