One to many relationship in eloquent - laravel

I'm following the information here:
http://laravel.com/docs/eloquent#one-to-many
I have an assets and sizes table.
An asset has many sizes.
So in my asset model I have:
class Asset extends Eloquent {
public function sizes()
{
return $this->hasMany('sizes');
}
}
But when I do:
Asset::find(1)->sizes;
I get:
Class 'sizes' not found
Where am I going wrong?
Migrations are:
Schema::create('assets', function($table){
$table->increments('id');
$table->string('title');
});
Schema::create('sizes', function($table){
$table->increments('id');
$table->integer('asset_id')->unsigned();
$table->foreign('asset_id')->references('id')->on('assets');
$table->string('width');
});
My classes are also namespaced:
In my controller:
<?php namespace BarkCorp\BarkApp\Lib;
use BarkCorp\BarkApp\Asset;
then later:
Asset::find(1)->sizes;
My models:
Asset:
<?php namespace BarkCorp\BarkApp;
use \Illuminate\Database\Eloquent\Model as Eloquent;
class Asset extends Eloquent {
public function sizes()
{
return $this->hasMany('BarkCorp\BarkApp\Size');
}
}
Size:
<?php namespace BarkCorp\BarkApp;
use \Illuminate\Database\Eloquent\Model as Eloquent;
class Size extends Eloquent {
}

You need models for both and when you use a relationship function, it takes the class name as an argument, not the name of the table. The function name can be whatever you want so do whatever makes sense to you there.
class Size extends Eloquent {
// This is optional for what you need now but nice to have in case you need it later
public function asset()
{
return $this->belongsTo('Namespace\Asset');
}
}
class Asset extends Eloquent {
public function sizes()
{
return $this->hasMany('Namespace\Size');
}
}
Namespace = the namespace you have on your Asset model.
$assetSizes = Namespace\Asset::find(1)->sizes;
or you can use use so you don't need to add the namespace each time you want to use Asset.
use Namespace;
$assetSizes = Asset::find(1)->sizes;
Or you can use dependency injection.
public function __construct(Namespace\Asset $asset)
{
$this->asset = $asset;
}
$assetSize = $this->asset->find(1)->sizes;

Related

Laravel : How to Pass an attribute to Eloquent model constructor

I want to use strtolower() before saving data in database for 5 attributes,
I'm using this code in Model
public function setFirstNameAttribute($value)
{
$this->attributes['firstName'] = strtolower($value);
}
public function setLastNameAttribute($value)
{
$this->attributes['lastName'] = strtolower($value);
}
public function setUserNameAttribute($value)
{
$this->attributes['userName'] = strtolower($value);
}
... etc
Can I use the __construct method instead of the above code?
There are two ways first one, to use boot method directly (preferred for small changes in model like in your question)
Method 1 :
we can directly use the boot method,
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Mymodel extends Model
{
public static function boot()
{
parent::boot();
static::saving(function ($model) {
// Remember that $model here is an instance of MyModel
$model->firstName = strtolower($model->firstName);
$model->lastName = strtolower($model->lastName);
$model->userName = strtolower($model->userName);
// ...... other attributes
});
}
}
Method 2 :
So we can use here a simple trait with a simple method for generating a strtolower() for a string.This is preferred when you have to do bigger changes in your model while performing operations in model like saving, creating etc. Or even if you want to use the same property in multiple models.
Create a trait MyStrtolower
<?php
namespace App\Traits;
trait MyStrtolower
{
public function mystrtolower($string)
{
return strtolower($string);
}
}
We can now attach this trait to any class that we want to have the mystrtolower method.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\Traits\MyStrtolower;
class Mymodel extends Model
{
use MyStrtolower; // Attach the MyStrtolower trait to the model
public static function boot()
{
parent::boot();
static::saving(function ($model) {
// Remember that $model here is an instance of MyModel
$model->firstName = $model->mystrtolower($model->firstName);
$model->lastName = $model->mystrtolower($model->lastName);
$model->userName = $model->mystrtolower($model->userName);
// ...... other attributes
});
}
}
If you want to not repeat all these lines of code for every model you make, make the trait configurable using abstract methods so that you can dynamically pass the attribute names for which you want to lower case string, like employee_name is Employee Model and user_name in User Model.

Cannot establish relationship between two tables in Laravel

I want to create a relation between lising and attribute table in laravel for that i have used following code to establish relationship between them but the data in my view is not coming from both the tables. I'm getting following error:
Call to undefined relationship [adListAttributes] on model
[App\Models\AdListing].
Here listing can have as many attribute associated with and attributes
can be associated to many listings
ad_listings:
id
title
name
date
ad_list_attributes table :
id
listing_id
name
namespace App\Models;
use Eloquent;
use Illuminate\Database\Eloquent\Model;
class AdListAttribute extends Model
{
protected $table = "ad_list_attributes";
public function Listings()
{
return $this->belongsToMany('AdListing', 'id', 'listing_id');
}
}
namespace App\Models;
use Eloquent;
use Illuminate\Database\Eloquent\Model;
class AdListing extends Model
{
protected $table = "ad_listings";
public function Attributes()
{
return $this->belongsToMany('AdListAttribute', 'listing_id', 'id');
}
}
Problem is that you are using belongsToMany in both the models.This will cause a problem.
In AdListAttribute model,
public function listing_information()
{
return $this->belongsTo('App\AdListing', 'id', 'listing_id');
}
In AdListing model,
public function adlisting_attributes()
{
return $this->hasMany('App\AdListAttribute', 'listing_id', 'id');
}
You can get the results using,
$response = AdListing::get();
if($response->adlisting_attributes)
{
foreach($response->adlisting_attributes as $attribute)
{
echo $attribute->name;
}
}
Problem is that ur not calling the relationship with the right name i assume
$listings = AdListing::with('Attributes')->get();
Update :
Try this :
use App\Models\AdListAttribute;
//
return $this->belongsToMany(AdListAttribute::class, 'listing_id', 'id');
Same for other model, then try

Eloquent one to many relationship not working

I'm stuck for hours with one of those issues where a fresh set of eyes might help. I just can't understand what's missing.
I'm connecting a model called User_ativo and defining two one-to-many relations to models Instituicao and Tipo_Ativo.
My database is simple.
Table user_ativo has columns "tipo_ativo_id" and "instituicao_id". I have a test row where both are set to 1. Both my tables instituicoes and tipo_ativos have only "id" and a string field "nome" (name). Both have a record with id == 1.
User_ativo.php:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User_ativo extends Model
{
public function tipo(){
return $this->belongsTo('App\Tipo_ativo');
}
public function instituicao(){
return $this->belongsTo('App\Instituicao');
}
}
Instituicao.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Instituicao extends Model
{
protected $table = 'instituicoes';
public function user_ativos(){
return $this->hasMany('App\User_ativo');
}
}
Tipo_ativo.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Tipo_ativo extends Model
{
protected $table = 'tipo_ativos';
public function user_ativos(){
return $this->hasMany('App\User_ativo');
}
}
My controller method that fetches the date goes as follow:
public function index()
{
$ativos = User_ativo::with('tipo', 'instituicao')->get();
return view('ativos.index', compact('ativos'));
}
Now here's where it gets interesting, for some reason I can't figure out, when I echo the $ativos variable in my view I get this:
[{"id":1,"user_id":1,"instituicao_id":1,"tipo_ativo_id":1,"tipo":null,"instituicao":{"id":1,"nome":"Banco do Brasil"}}]
So, weirdly my relationship with the Instituicao model works, but the one with Tipo_ativo returns null.
I'm pretty confident someone will point out some dumb and obvious mistake in all of this, but I can't for the life of me understand why one works and the other doesn't since they're pretty much the same thing.
Your relationships names are not according to laravel convention.
Read below function and provide foreign_key and local_key/owner_key to your relationships then it will work
public function belongsTo($related, $foreignKey = null, $ownerKey = null, $relation = null){}
If we do not follow laravel convention while creating relationships then we have to tell it that these are the foreign and local keys that should be used.
Read more here
class User_ativo extends Model{
public function tipo(){
return $this->belongsTo('App\Tipo_ativo','user_ativo_id'); //second parameter is foreign_key_of_User_avito_table_here
}
public function instituicao(){
return $this->belongsTo('App\Instituicao','user_ativo_id'); //second parameter is foreign_key_of_User_avito_table_here
}
}
class Instituicao extends Model
{
protected $table = 'instituicoes';
public function user_ativos(){
return $this->hasMany('App\User_ativo','instituicao_id'); //second parameter is foreign key of Instituicao model
}
}
class Tipo_ativo extends Model
{
protected $table = 'tipo_ativos';
public function user_ativos(){
return $this->hasMany('App\User_ativo','tipo_ativo_id'); //second parameter is foreign key of Tipo_ativo model.
}
}

In laravel how to get the join table data in same array without where condition

I have created both employes and employes_detail tabel with the data
i have created model for both of the table that is given below:
emloye model:
<?php
namespace App\Http\Model;
use Illuminate\Database\Eloquent\Model;
use App\Http\Model\EmployeDetail;
class Employe extends Model
{
public function employes_detail()
{
return $this->hasOne(EmployeDetail::class);
}
}
and eployedetail model:
<?php
namespace App\Http\Model;
use Illuminate\Database\Eloquent\Model;
class EmployeDetail extends Model
{
public function employe()
{
public function employe()
{
return $this->belongsTo(Employe::class);
}
}
}
and in controller i used like :
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use DB;
use App\Http\Model\Employe;
use App\Http\Model\EmployeDetail;
class EmployeController extends Controller
{
public function index(Request $request)
{
$Employe=Employe::all();
$convert=$Employe->toArray();
echo "<pre>";print_r($convert);exit;
//return view('employe.employe');
}
}
it showing only employe table data how can i show the data for the
employes_detail as well as .still i am not able to understand it on
laravel documentation can anyone please help me related this.
how can i get the all data from employes and employes_details table for all the records
but when i used this code in controller:
public function index(Request $request)
{
$Employe=Employe::where('id',1)->first();
//$convert=$Employe->toArray();
echo "<pre>";print_r($Employe->employes_detail);exit;
//return view('employe.employe');
}
its shows me the employe_detail table data
but i want both of the table data in a same array and i dont want to use where condition here.
the function employes_detail and employe in your models only declares the relationships between the models but if you want to load the relationship, you can try this :
Employe::with('employes_detail')->get();
or
$employees = Employe::all(); $employees->load('employes_detail');
Then you can access for each employees the relation attribute like that :
foreach($employees as $employe) {
$employe->employes_detail->id;
}
Hopes it helps you.

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