Laravel 5.1 - Eloquent Relationships - eloquent

I am new to Laravel. I was looking at the Eloquent relationships. I followed the documentation and defined my one to many relationship as:
// in the test model
public function questions()
{
return $this->hasMany('App\Question', 'test_name_id', 'test_id');
}
// in the question model
public function test()
{
return $this->belongsTo('App\Test', 'test_name_id', 'test_id');
}
Note that i have not followed the convention for naming the id's. So if I do this in the Tinker:
$test = App\Test::first();
$question = $test->questions;
It works fine. But if want the record any other than first like doing:
$test = App\Test::where(['test_id'=>'2'])->get();
$question = $test->questions;
It gives me this error:
PHP error: Trying to get property of non-object on line 1
Can any one please explain me what I am doing wrong here and how does this work properly?

Try ->first() instead of get(). get() returns array. Or use protected $primaryKey = 'test_id'; in test model and then ->find($id)

Related

Yii2 override on condition in relation for postgres array data type

I'm trying to create a relation to a postgres array column in Yii2 and it's giving me an error (not surprisingly)
SQLSTATE[42883]: Undefined function: 7 ERROR: operator does not exist: integer[] = integer
Just setting the standard onCondition() doesn't seem to work.
Anyone have experience working with postgres array types and Yii2 relations? It would be nice if I could do something like this to override the default operator and on condition to support array column type.
/**
* #return \yii\db\ActiveQuery
*/
public function getMyRelation()
{
return $this->hasMany(ModelName::className(), ['#>', 'id', '{'.intval($this->rel_id).'}'])->alias('myRelation');
}
You cannot create hasMany relation in this way - ActiveRecord does not support such syntax and you cannot use model attributes for defining relations, since this method may be executed before real model initialization (for example if you're building joins).
You may create getter which will use ActiveQuery to obtain related models - it will not be real relation and you will not be able to use it for eager loading or joins, but should work fine with lazy loading for single model:
public function getMyRelation() {
$query = ModelName::find()
->andWhere(['#>', 'id', '{'. (int) $this->rel_id .'}'])
->alias('myRelation');
$query->primaryModel = $this;
$query->multiple = true;
return $query;
}

Eloquent attaching a many to many results in Trying to get property of non-object

In my Lumen project I use a many to many relationship like this:
class Item{
protected $appends = ['order'];
public getOrderAttribute(){
return $this->pivot->order;
}
public function collections(){
return $this->belongsToMany(Collection)->withTimestamps()->withPivot('order');
}
}
and then in the collection
class Collection{
public function items(){
return $this->belongsToMany(Item)->withTimestamps()->withPivot('order')';
}
}
then I try to insert a new item in a collection like this:
addItem(Request $req, $id){ <- is for collection
$item = new Item();
$item->save();
$collection = Collection::findOrFail($id);
$collection->items()->attach($item, ['order' => $req->input('order')]);
return $item;
this result in Trying to get property of non-object
The data gets stored in the database succesfully and correctly.
I have tried switching up the attach on collections() and on items() but that doenst change anything.
I have tried to renew the item value like this: Item::findOrFail($item->id)
still results in the same error.
Abd when I refresh the page I get the correct data.

Laravel 5.4 order by related table after using `with` statement

This is my simple structure:
public class Post{
public function user(){
return $this->belongsTo(User::class);
}
}
This is how I query (the query has pagination):
$query = Post::query();
$query->with('user');
I want to sort by user.name.
Now, I know that I can go $query->with('user',function(){...order by here});
But I need a detached method that I can run later in the stack.
$query->user->orderBy('name');
$query->user()->orderBy('name');
This https://stackoverflow.com/a/38741988/936651 says that it is possible, but I get the error: Undefined property/method: Illuminate\Database\Eloquent\Builder::$user
Is there any way to sort by related table after using with statement?
Thanks
Your code doesn't work because when you do $query = Post::query(); it will return an instance of the Query Builder, so when you after do $query->user() it gives you an error because the Query Builder does not have the method user(), that method exists in your Post model.
I won't provide any code since you've mentioned you already know how to do the with() way..

laravel mongodb how to change _id to id on output?

I want to have _id in the database but want to output id when doing a query.
How can I achieve it?
You can try this (using an Accessor) :
Model
public function getIdAttribute() {
return $this->attributes['_id'];
}
Controller test
$user = User::find(1);
// this will call getIdAttribute which will return the `_id`
dd($user->id);
You can also override toArray() method if you want to show it :
Model
// ..
// getIdAttribute()
// ..
public function toArray()
{
$array = parent::toArray();
$array['id'] = $this->id;
unset($array['_id']);
return $array;
}
Controller Test
$user = User::find(1);
dd($user->toArray());
Another way to do this is using Transformers (http://fractal.thephpleague.com/transformers/). There is a service provider for Laravel here (https://github.com/gathercontent/laravel-fractal).
It will do that in a elegant way :)
Of course, if you need to do only with "id" field, I'll do like zorx told:
public function getIdAttribute() {
return $this->attributes['_id'];
}
But you'll probably put that in some BaseModel or abstractModel class, a parent for you models who need this.

Laravel 4 Auth with Facebook (no password authentication)

I'm trying to set up an authentication system with Laravel 4 with a Facebook login. I am using the madewithlove/laravel-oauth2 package for Laravel 4.
Of course, there is no password to add to my database upon a user loggin in with Facebook. I am, however, trying to check to see if a user id is in the database already to determine if I should create a new entity, or just log in the current one. I would like to use the Auth commands to do this. I have a table called "fans".
This is what I'm working with:
$fan = Fan::where('fbid', '=', $user['uid']);
if(is_null($fan)) {
$fan = new Fan;
$fan->fbid = $user['uid'];
$fan->email = $user['email'];
$fan->first_name = $user['first_name'];
$fan->last_name = $user['last_name'];
$fan->gender = $user['gender'];
$fan->birthday = $user['birthday'];
$fan->age = $age;
$fan->city = $city;
$fan->state = $state;
$fan->image = $user['image'];
$fan->save();
return Redirect::to('fans/home');
}
else {
Auth::login($fan);
return Redirect::to('fans/home');
}
Fan Model:
<?php
class Fan extends Eloquent {
protected $guarded = array();
public static $rules = array();
}
When I run this, I get the error:
Argument 1 passed to Illuminate\Auth\Guard::login() must be an instance of Illuminate\Auth\UserInterface, instance of Illuminate\Database\Eloquent\Builder given
EDIT: When I use: $fan = Fan::where('fbid', '=', $user['uid'])->first();
I get the error:
Argument 1 passed to Illuminate\Auth\Guard::login() must be an instance of Illuminate\Auth\UserInterface, null given, called in /Applications/MAMP/htdocs/crowdsets/laravel-master/vendor/laravel/framework/src/Illuminate/Auth/Guard.php on line 368 and defined
I do not know why it is giving me this error. Do you have suggestions on how I can make this work? Thank you for your help.
You have to implement UserInterface to your model for Auth to work properly
use Illuminate\Auth\UserInterface;
class Fan extends Eloquent implements UserInterface{
...
public function getAuthIdentifier()
{
return $this->getKey();
}
/**
* Get the password for the user.
*
* #return string
*/
public function getAuthPassword()
{
return $this->password;
}
}
getAuthIdentifier and getAuthPassword are abstract method and must be implemented in you class implementing UserInterface
To login any user into the system, you need to use the User model, and I bet inherited classes will do the trick as well but I'm not sure.
Anyway, your Fan model does not associate with the User model/table in any way and that's a problem. If your model had a belong_to or has_one relationship and a user_id field then you could replace Auth::login($user) with Auth::loginUsingId(<some id>).
Original answer:
You are missing an extra method call: ->get() or ->first() to actually retrieve the results:
$fan = Fan::where('fbid', '=', $user['uid'])->first();
Alternatively, you can throw an exception to see what's going on:
$fan = Fan::where('fbid', '=', $user['uid'])->firstOrFail();
If you see different errors, update your question with those errors.