Laravel 8 Using Belongs To Failing When Using Where - eloquent

I know this is me being dumb and not understanding the documentation but I am trying to use the belongsTo feature to access the parent of a class
In the model I have the function defined
class Child extends Model {
use HasFactory;
protected $fillable = ['childField'];
public function parent() {
return $this->belongsTo(Parent::class, 'parent_id');
}
}
But I am getting an error when trying to retrieve it in a controller
$child = Child::where('childField', 'ChildTest01')->get();
$parent = $child->parent->parentField;
The where is working because it's returning the right child but I'm getting an error saying that Property [parent] does not exist when trying to get the parent, what am I missing?

In your code, $child is a Collection, not a Model. It should be:
$child = Child::where('childField', 'ChildTest01')->first();
$parent = $child->parent->parentField;

Related

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 one to many relationship save method empty attributes

I am trying to save a relationship with the Laravel save method:
public function storeContact(Request $request)
{
$user = User::firstOrNew(['email' => $request->input('email')]);
$user->save();
$message = new App\Message([
'message' => $request->input('remarks')
]);
$user->message()->save($message);
}
var_dump($request->all) confirms both fields are available in the request.
All relations work. hasOne, belongsTo are configured in the models. The relation is saved like expected (but message field is empty)
When I var_dump($message), there are no attributes in the collection.
I already tried fillable and guarded on the models without any effect. These should not be necessary for the save method though because this uses a full Eloquent model instance.
What am I missing here??
I think I found the culprit.
When I use a __construct on a model it fails. When I instantiate a model with a __construct no variables are passes as attributes. Even if the __construct is empty.
Test with __construct method
class Message extends Model
{
protected $connection = 'system';
public function __construct()
{
}
// ...
}
$message = new App\Message(['remarks' => 'Test remarks']);
var_dump(message) // does NOT contain attributes!
Test2 without __construct method
class Message extends Model
{
protected $connection = 'system';
// ...
}
$message = new App\Message(['remarks' => 'Test remarks']);
var_dump(message) // does contain attributes!
This looks like a bug in Laravel to me.

Access other entities while creating a Doctrine entity

Say I have tables A, B in MySQL and Doctrine entity classes with the same names. Those entities are managed by Doctrine and are basically created according to Symfony/Doctrine docs.
Now I want to create entity C with columns: x, y. Whenever this entity is created or updated, I want to set the column values:
x: select count(*) from A where (some condition)
y: select sum(y) from B where (other condition)
pull some other data from A or B and store it as column value for C.
I want to do this in PHP and not use mysql triggers. I can't achieve from inside the Entity classes, because they don't have access to entity manager. I don't want to do this in the controller, as I want insert/update operations to be standardized, and I will need to do it from multiple controllers, and I generally don't think the controller is a good place for logic like this.
So I need some kind of class which manages entity C.
My question is: How do I call this manager class and where do I place it in Symfony? I am pretty sure this is a common need in Symfony (to access multiple entities while creating another entity), but I don't know how it is called and if there is a standard practice with them.
you can define service in app/config/services.yml and pass Entity manager as argument
services:
app.service.some_service:
class: AppBundle\Service\SomeService
arguments: ["#doctrine.orm.default_entity_manager"]
place your logic inside service
use Doctrine\ORM\EntityManagerInterface;
use AppBundle\Entity\SomeEntity;
class SomeService
{
/**
* #var EntityManagerInterface
*/
protected $entityManager;
public function __construct(EntityManagerInterface $entityManager) {
$this->entityManager = $entityManager;
}
public function getSomeEntity($id) {
$entity = $this->entityManager->getRepository(SomeEntity::class);
// do some work, return result..
}
}
call it from controller
$someService = $this->get('app.service.some_service');
$someService->getSomeEntity($id);
:)
I think you should create a Doctrine Event Subscriber as described in the documentation
I'll try to explain the basics.
1) Declare the service
services:
c_entity_counter_subscriber:
class: AppBundle\EventListener\CounterSubscriber
tags:
- { name: doctrine.event_subscriber, connection: default }
2) In the Subscriber count A and B properties
namespace AppBundle\EventListener;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
use AppBundle\Entity\A;
use AppBundle\Entity\B;
use AppBundle\Entity\C;
class CounterSubscriber implements EventSubscriber
{
public function getSubscribedEvents()
{
return array(
'postPersist',
'postUpdate',
);
}
public function postUpdate(LifecycleEventArgs $args)
{
$this->count($args);
}
public function postPersist(LifecycleEventArgs $args)
{
$this->count($args);
}
public function count(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if (!$entity instanceof C) {
return;
}
$entityManager = $args->getEntityManager();
// ... count/sum entities from A/B classes using $entityManager and update $entity
}
}

Laravel 5.1 - Eloquent Relationships

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)

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.