I have two tables: user and student. The field username from user is a foreign key as login_id in student. I have created eloquent relationships in each model, but when I try to access Auth::user()->student->id it gives me:
Trying to get the property of a non-object.
Student Model:
public function user()
{
return $this->belongsTo('user','login_id');
}
User Model:
public function student(){
return $this->hasOne('student')
}
ProfileController.php
<?php
class ProfileController extends BaseController
{
public function showinfo()
{
if (Auth::check())
{
$user_id = Auth::user()->username;
$student_id = Auth::user()->student->id;
}
}
}
Above noted error occurs when I try to log in.
You should check first if the user who login has student, so i would suggest
$student = Auth::user()->student;
if($student) $student_id = $student->id;
$student_id = Auth::user()->student->id;
If it doesnt contain value, then you get that error. Try using isset, or empty, depends on what you like.
Only with many to many relations you use the ( ).
Example:
$user_companies = Auth::user()->companies();
foreach($user_companies as $company)
Related
I have a pivot table where I store Student and guardian relationships, I create student first before adding guardian Cause Student and guardian have two tables and I relate to them using ids. When I create a new Guardian everything works fine but the problem is when I try to merge an old guardian with a new student and I call my model "getStudent" i get the error "Call to a member function getStudent() on string"
//Guardians Model
public function getStudent()
{
return $this->belongsToMany(Student::class);
}
//Student Model
public function Guardians()
{
return $this->belongsToMany(Guardian::class);
}
//Controller
if (isset($_POST['merge'])) {
$student = Student::find($id);
$guardian = $req->input('parent_id');
dd($guardian->getStudent()->attach($student->id));
}
I am able to get the two Id but how do I save without errors to my pivot?
you are calling getStudent() function from a request Object you can call this function form a Guardian modal instance so
you code should look like
if (isset($_POST['merge'])) {
$student = Student::find($id);
$guardian = Guardian::find($req->input('parent_id'));
dd($guardian->getStudent()->attach($student->id));
}
You should do like this:
if (isset($_POST['merge'])) {
// $student = Student::find($id);
$guardian = Guardian::find($req->input('parent_id'));
$guardian->getStudent()->attach($id);
}
I have tables called users, places and user_place. users has a column called id that contains the id of the user and places has a column called place_id as well. The user_place table has 2 columns called user_id and place_id and I'm trying to automatically populate them with the corresponding ids. I read I have to use attach() function after setting up the relationships which I believe I have done but I might be wrong. Here they are:
class PlaceController extends Controller
{
public function likePlace(Request $request){
$placeId = $request['placeId'];
$userId = $request['userId'];
$user = User::where('id', $userId)->first();
$place = new Place();
$place->place_id = $placeId;
$place->save();
$user->places()->attach($place);
}
}
User model:
class User extends \Eloquent implements Authenticatable
{
use AuthenticableTrait;
public function places(){
return $this->hasMany('App\Place');
}
}
Place mode:
class Place extends Model
{
public function user(){
return $this->belongsToMany('App\User');
}
}
In a Many to Many relationship, you should define both relationships like the following:
User.php
class User extends \Eloquent implements Authenticatable
{
use AuthenticableTrait;
public function places()
{
return $this->belongsToMany('App\Place', 'user_place', 'user_id', 'place_id');
} // ^^^^^^^^^^^^
}
Note: Given that your intermetiate table name doesn't follow the naming convention we specified so Laravel knows where table to look up.
Place.php
Notice that you mentioned that the primmary key of your Place model is place_id, and this also scapes from the Laravel convention you should specify it:
protected $primaryKey = 'place_id'; // <----
class Place extends Model
{
public function user()
{
return $this->belongsToMany('App\User', 'user_place', 'place_id', 'user_id');
}
}
So now in your controller:
class PlaceController extends Controller
{
public function likePlace(Request $request)
{
$placeId = $request['placeId'];
$userId = $request['userId'];
$user = User::where('id', $userId)->first();
$place = new Place();
$place->place_id = $placeId;
$place->save();
$user->places()->attach($place);
}
}
Side note
As I side note, you could save a couple of line replacing some sentences with their equivalent:
$userId = $request['userId'];
$user = User::where('id', $userId)->first();
Using the find() method, this is equal to:
$user = User::find($request['userId']);
Then, you could create your related object using the static method create of an Eloquent model so this:
$placeId = $request['placeId'];
$place = new Place();
$place->place_id = $placeId;
$place->save();
Is equal to this:
$place = Place::create(['place_id' => $request['placeId']]);
Then your controller will be reduced to this:
class PlaceController extends Controller
{
public function likePlace(Request $request)
{
$user = User::find($request['userId']);
$place = Place::create(['place_id' => $request['placeId']]);
$user->places()->attach($place);
}
}
I have two database tables journeys and stops that are related in a many-to-many relationship. There is also the third table journey_stop (the pivot table) for the relationship.
Models
Here is my Journey.php model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Journey extends Model
{
public function stops() {
return $this->belongsToMany('App\Stop');
}
}
and the Stop.php model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Stop extends Model
{
public function journeys(){
return $this->belongsToMany('App\Journey');
}
}
Controller
Now in my controller, I have written a method changeStop(stop, journey_id) which takes a particular journey_id and either assigns a stop to it.(that is, creates a relationship between that particular stop and the journey) or removes the stop from the journey if it already exists.
Here is the method:
public function changeStop(Request $request, $id)
{
$stop = $request->all();
$journey = Journey::find($id);
if ($journey->stops()->contains($stop->id)) {
$journey->stops()->detach($stop->id);
}else{
$journey->stops()->attach($stop->id);
}
return $journey->stops();
}
But the line with the if statement throws the error:
Trying to get property of non-object
I have also tried using DB to query the pivot table directly but it throws the same error. Here's the code with DB:
public function changeStop(Request $request, $id)
{
$stop = $request->all();
$journey = Journey::find($id);
if (
DB::table('journey_stop')->where(
'journey_id',
$id
)->where(
'stop_id',
$stop->id
)->count() > 0
) {
$journey->stops->detach($stop->id);
} else {
$journey->stops->attach($stop->id);
}
return $journey->stops();
}
Everything seems right for me. But it doesn't work. What am I doing wrong?
Thanks for your time :)
You may also use the sync method to construct many-to-many associations. The sync method accepts an array of IDs to place on the intermediate table. Any IDs that are not in the given array will be removed from the intermediate table. So, after this operation is complete, only the IDs in the given array will exist in the intermediate table
$journey->stops()->sync([$stop_id])
And to work for your above code try this:
public function changeStop(Request $request, $id)
{
$stop = $request->all(); // returns an array
$journey = Journey::find($id);
if ($journey->stops->contains('id', $stop['id'])) {
$journey->stops()->detach($stop['id']);
} else {
$journey->stops()->attach($stop['id']);
}
return $journey->stops;
}
I have a User model and a Group model, connected by a pivot table. Users can be in many groups, groups contain multiple users.
I need to retrieve all of the users that are in a given group. Here are my models and my controller code so far. I'd appreciate any help - I'm sure I'm missing something obvious. My error messages vary depending on what I try, but with the current code it's:
"BadMethodCallException in Builder.php line 1992: Call to undefined method Illuminate\Database\Query\Builder::users()"
Many thanks!
User:
class User extends Model implements AuthenticatableContract, CanResetPasswordContract
{
//BLAH BLAH
public function groups()
{
return $this->belongsToMany('App\Group');
}
}
Group:
class Group extends Model
{
protected $table = 'groups';
protected $fillable = [
'name',
'detail'
];
public function scopeName($query, $group)
{
$query->where('name', '=', $group);
}
public function users()
{
return $this->belongsToMany('App\User');
}
}
Controller Code:
public function getGroup($query)
{
// $query = "name of group" FYI
// The task of this function is to return a Datatable object containing all users in the given ($query) group
$the_group = Group::with('users')->Name($query) -> get();
dd($the_group->users);
return Datatables::of($users)->make(true);
}
class User extends Model
{
public function scopeGender($query){
return $query->where('gender', 'f');
}
}
Utilizing A Query Scope
Once the scope has been defined, you may call the scope methods when querying the model. However, you do not need to include the scope prefix when calling the method. You can even chain calls to various scopes, for example:
$users = App\User::gender()->get() or -> first(); //<-- notice that you still need to
chain get or first to fetch results.
That's one error you have in query. your query should look like this.
$the_group = Group::with('users')->Name($query) -> get();
//returns all rows. use a foreach loop.
$the_group = Group::with('users')->Name($query) -> first();
// returns first
echo $the_group -> users;
Hope this help.
I am trying to grasp the concept of Eloquent ORM by creating a ticketing system at the moment. What I am trying to achieve is:
The tickets with the user who posted the ticket
The feedback belonging to the ticket and the user who entered the
feedback
This is what I have right now:
// TicketController.php
public function index()
{
$tickets = Ticket::with('feedback')->with('user')->orderBy("created_at", "desc")->get();
//dd($tickets);
return View::make('modules.helpdesk.index')->withTickets($tickets);
}
And the following models
// Ticket.php
class Ticket extends Eloquent {
protected $table = 'helpdesk_tickets';
public function feedback()
{
return $this->hasMany('Feedback');
}
public function user()
{
return $this->belongsTo('User');
}
}
// Feedback.php
class Feedback extends Eloquent {
protected $table = 'helpdesk_tickets_feedback';
public function ticket()
{
return $this->belongsTo('Ticket');
}
}
// User.php
class User extends Eloquent {
protected $table = 'users';
public function ticket()
{
return $this->belongsTo('Ticket');
}
}
What I have now is the tickets, their related feedback and user who created the ticket. What I am trying to achieve now is to also get the user who created the feedback.
You need to fix the relation:
// User model
public function tickets()
{
return $this->hasMany('Ticket'); // adjust namespace if needed
}
Next add the relation:
// Feedback model
public function user()
{
return $this->belongsTo('User'); // namespace like above
}
then use eager loading:
// it will execute 4 queries:
// 1st for tickets
// 2nd for feedback
// 3rd for feedbacks' user
// 4th for tickets' user
$tickets = Ticket::with('feedback.user', 'user')->latest()->get();
you can then access the relations in a loop, like below:
#foreach ($tickets as $ticket)
{{ $ticket->title }} by {{ $ticket->user->name }}
#foreach ($ticket->feedback as $feedback)
{{ $feedback->content }}
#endforeach
#endforeach
What you want to do is create nested relations, just like Ticket add a belgonsTo relation on feeback
When you want to use it you can chain relations using the dot notation feedback.user
The code
// Feedback.php
class Feedback extends Eloquent {
protected $table = 'helpdesk_tickets_feedback';
public function ticket()
{
return $this->belongsTo('Ticket');
}
public function user()
{
return $this->belgonsTo('User')
}
}
// TicketController.php
public function index()
{
$tickets = Ticket::with('feedback')->with('user')->with('feedback.user')->orderBy("created_at", "desc")->get();
//dd($tickets);
return View::make('modules.helpdesk.index')->withTickets($tickets);
}
EDIT:
Even though this would work, it will execute more queries than needed. See Jareks answer.
Original Answer:
First of all you need to get your relationships straightened, in User.php you should call the user relationship with HasMany.
public function ticket() {
return $this->hasMany('Ticket');
}
In modules.helpdesk.index you should now have a Ticket Collection since your attaching the $ticket variable to the view.
If you loop through this collection with a foreach loop then what you should get is a model each loop:
foreach($tickets as $ticket) {
// Prints the name property of the Ticket model
print $ticket->name;
// Since a ticket only belongs to ONE user then that means that you are trying to fetch a model
// What we're doing here is getting the User model via the relationship you made in the model Ticket.php and then getting the name.
print $ticket->user()->first()->username;
// Since a ticket can have MANY feedbacks that means were fetching a collection
// which needs to be broken down to models so we do that looping the collection.
// Here we are doing the same thing as with the User model except with a collection.
foreach($ticket->feedback()->get() as $feedback) {
$feedback->text;
}
}
You should definitely check out the Laravel API and see Collection and Model there. http://laravel.com/api/ You get alot of help from there when you get stuck, trust me :)
I hope this answered your question.