Laravel model: instance or relationship? - laravel-5

I'm not a professional programmer, so I don't know that I'm describing this very well.
Eloquent relationships are established in the model, using syntax and functions such as ... - >belongsTo.. etc.
Behind these models, are tables in my database.
In my (laravel) application, I have a logged in user who needs certain information about other users. At the end of the day, they're all just users, persisting in the user's table.
So when I use a relationship to another object, (e.g. car) all is good. When I try use a relationship to another user I get errors like Cannot redeclare class App\Models\User.
I think I'm misunderstanding something here.
I get the feeling maybe I should be 'instantiating' another version of my User (as 'manager') ... But do I really need to? It's more of a lookup than anything else. I'm not sure I would even know how to do that.
Some pointers please?

It sounds like you created two distinct "User" models:
// /app/User.php:
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
// ...
public function user() {
return $this->hasOne('App\Models\User');
}
}
// /app/models/User.php:
<?php namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
// ...
public function user() {
return $this->belongsTo('App\User');
}
}
Instead you want to have a single class which belongs to itself:
// /app/User.php:
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
// ...
public function parent() {
return $this->belongsTo('App\User');
}
public function children() {
return $this->hasMany('App\User');
}
}
Then in your database make sure that the users table has a user_id property (edit database/migrations/2014_10_12_000000_create_users_table.php):
$table->integer('user_id')->unsigned()->nullable();
$table->foreign('user_id')->references('id')->on('users');
Now you can attach users to one another:
<?php
$manager = new User();
$employeeOne = new User();
$employeeTwo = new User();
$manager->children()->saveMany([
$employeeOne,
$employeeTwo
]);
dd( $employeeTwo->parent->name ); // Manager's name

Related

Laravel Polymorphic Relationships - Return child with parent

I have a model Team with has a polymorphic relationship with Marketcenters Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Team extends Model
{
public function teamable()
{
return $this->morphTo();
}
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Marketcenter extends Model
{
public function teams()
{
return $this->morphMany('App\Team', 'teamable');
}
}
I need to retrieve all teams for one or any Marketcenter so I can list all Teams and to which Marketcenter they belong.
So I execute the following code and I get a collection od Teams for the Market Center in query:
$marketcenters = Marketcenter::where('id', $request->user()->marketcenter->id)->with('teams')->get();
foreach($marketcenters as $marketcenter) {
dd($marketcenter->teams);
}
But my problem appears when I want to retrieve each Team with their corresponding Market Center:
$marketcenters = Marketcenter::where('id', $request->user()->marketcenter->id)->with('teams')->get();
foreach($marketcenters as $marketcenter) {
dd($marketcenter->teams->marketcenter->mc_name);
}
Property [marketcenter] does not exist on this collection instance.
How can I retrieve parent data to child record in a Polymoprphic relationship?
Regards
Try querying for teams instead of the market center:
$teams = Team::whereHas('teamable', function ($q) {
$q->whereKey(request()->user()->marketcenter->id);
})->get();
Also, from the Laravel docs:
You may also retrieve the owner of a polymorphic relation from the polymorphic model by accessing the name of the method that performs the call to morphTo.
// This gets the marketcenter
$team->teamable
my question is why you want to access "marketcenter" via team model like $marketcenter->teams->marketcenter->mc_name instead you can directly use $marketcenter->mc_name in the for loop as both would return you the same object.
If you still need it than you have to have another foreach loop for martketcenter->team as you have morphMany so it would return you collection object from team model if you want marketplace than you have to call teamable function that would return the object of morphed model which may be Marketcenter or may not be depending on the morphed model attached to that record

How to get all records(related and non related) of Laravel belongsTo relationship?

How can I get all the records from the relationship? I mean not only the related records, but also the rest.
Let's say I have a post which belongs to some category. If I want to change the category of this post I need a list of all available categories. Can I get this list from the relationship?
The Post model:
class Post extends Model
{
public function category()
{
return $this->belongsTo('App\Category');
}
}
The Category model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
public function posts()
{
return $this->hasMany('App\Post');
}
}
In the PostsController I tried:
$postModel->category->find('all'); // Returns null
$postModel->category->all(); // Returns only the related categories
I know I can simply use the Category model in the PostsController, but I prefer to do it using the relationship.
If you feel you must use the relationship to get to the other model you could try:
$categories = $post->category()->getRelated()->get();

Hasmany with child of child in laravel 5.5

I have 3 tables.
shops
shop_foods
foods
I need to fetch foods table data when I create hasmany relation with shops_food and store.
$this->hasMany('App\Diet\ShopFood', 'shop_id', 'id');
Please, show your code so we can know what are you trying to do.
But what I can see here is that you have a wrong relationship.
Why are you assigning hasMany in a Many to Many relationship?
In your Shop Model you can make a foods relationship with:
$this->belongsToMany('App\Diet\Food);
Then you can retreive you food when calling
$shop->foods
And the shop_foods with the Pivot property
If i understand correctly you want to get foods when you call shops->shop_foods. if is that
//first you call your shops as you want.
Shop::with(['shops_food' => function($query){
//the 'shops_food' relationship should be called within an array
//this way you could query the relationship as the eloquent model.
//that way you could call the 'foods' relationship inside the shops_food relationship.
$query->with('foods')
}])
...
Note that you must have the relationship declared in shop and shop_foods models
lets your models are like these
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Shop extends Model
{
//
public function shops_food()
{
//shop_id is the foreing key inside your shop_foods table
return $this->hasMany('App\ShopFood','shop_id');
}
....
}
then ShopFood Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class ShopFood extends Model
{
//
public function foods()
{
//shop_food_id is the foreing key inside your foods table
return $this->hasMany('App\Food','shop_food_id');
}
....
}
This reads as if you want
public function foods() {
$this->hasMany('App\Diet\Food');
}
in your ShopFood model and in your Shop model
public function shopfoods() {
$this->hasMany('App\Diet\ShopFood')->with('foods');
}
You can also make 2 separate relations in the Shop model:
public function shopfoods() {
$this->hasMany('App\Diet\ShopFood');
}
public function shopfoodsWithFoods() {
$this->hasMany('App\Diet\ShopFood')->with('foods');
}
So that way you can use whatever you need at that moment.
But the whole thing is really not clear...
I am not even sure how the 3 table are connected, so the hasMany are just guesses.
Nevertheless you can just go with the "with" function.
PS
There is also the possibility to just declare
protected $with = ['foods'];
in your ShopFood model, if you ALWAYS want those 2 connected. It's all in the documentation.

Unable to maintain one to many relationship in Eloquent using laravel 5.3

I am using laravel eloquent model so there are three tables tempsocials, tempusers and tempdevices. so one user can have multiple devices and multiple social acounts.
I created a models for three of above table and trying to maintain relationship in between like following
This is my Tempuser model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Tempuser extends Model
{
public function tempsocials(){
return $this->hasMany('App\Tempsocial');
}
public function tempdevices(){
return $this->hasMany('App\Tempdevice');
}
}
This is my Tempdevice model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Tempdevice extends Model
{
public function tempusers(){
return $this->belongsTo('App\Tempuser');
}
}
And this one is last Tempsocial model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Tempsocial extends Model
{
public function tempusers(){
return $this->belongsTo('App\Tempuser');
}
}
Now this is my controller where i want to retrive all the devices and social accounts of particular user
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Database\Eloquent\Collection;
use App\Http\Requests;
use App\tempLogin;
use App\Tempdevice;
use App\Tempuser;
use App\Tempsocial;
class loginController extends Controller
{
public function check_credentials(Request $request){
$count=0;
if($request->header('content-type')=='application/json'){
$temp=new Tempuser;
$devices = $temp->tempdevices();
return $devices;
}
}
}
But i got following error:
Object of class Illuminate\Database\Eloquent\Relations\HasMany could
not be converted to string
You're making a new Tempuser(), it has no id, so your relation returns nothing as expected, you will need to pass an id to the method and with that id you could do something like:
Tempuser::find($id);
This will then return an actual model instead of creating a new one.
Also because when you call ->tempdevices() as a function it will return a query builder, instead when you do ->tempdevices it will return a collection, change it like this:
$devices = $temp->tempdevices;
Also, if you expect a json response (if thats not the case you can ignore this part), it might be better to also state it in your return by doing:
return response()->json($devices);

Polymorphic relations in upgraded Laravel app from 4.2 to 5

Short: some related models are returning instances correctly, but some aren't (the polymorphic ones).
I have those three models:
app/Models/User.php
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function company()
{
return $this->hasOne('App\Company');
}
}
app/Models/Company.php
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Company extends Model {
public function user()
{
return $this->belongsTo('App\User');
}
public function address()
{
// Also tested with morphMany, without success
return $this->morphOne('App\Address', 'addressable');
}
}
app/Models/Address.php
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Address extends Model {
public function addressable()
{
return $this->morphTo();
}
}
And the controller:
app/Http/Controllers/MyController.php
<?php namespace App\Http\Controllers;
// ... many "use" clauses not relevant to the question
use Auth;
// ...
use App\Address;
use App\Company;
use App\User;
class MyController extends Controller {
// Ok here
$user = Auth::user();
// Ok here, too
$company = $user->company()->first();
// Here is the problem; $address is null
$address = $company->address()->first();
}
The line $company->address()->first(); is always returning null to $address in Laravel 5, but it worked well in Laravel 4.2
In L4 models were not namespaced by default, so they were saved as ModelName in your table, while now in L5 they are rather Namespace\ModelName and are retrieved the same way.
That said, your data saved in L4 needs to be adjusted so it matches your current models, or you can use protected $morphClass on the models.
However take this into consideration for the latter solution.
If you open your database - you'll see the relationship in your old L4 data stored as: User or Company
You need to run a script that updates the columns to the new namespace names - such as App\User or App\Company
This is because you are now namespacing your models - so Laravel needs to know which namespace to call.
Along with #The Shift Exchange's answer and following my question's example, you can follow this approach:
Instead of adding the namespace in addressable_type column values from address table (and this is a valid solution), you can use $morphClass:
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Company extends Model {
protected $morphClass = 'Company';
public function user()
{
return $this->belongsTo('App\User');
}
public function address()
{
// Also tested with morphMany, without success
return $this->morphOne('App\Address', 'addressable');
}

Resources