In my Model class;
Currently I have defined like;
return $this->belongsTo(related: Site::class,
foreignKey:'SiteId', ownerKey:'SiteId');; ----->This works.
But I want to define a combination as Foreign key,
eg: CompanyCode+SiteId
My Current and Target model has both columns(ie:CompanyCode+SiteId). That combination will return a single entry.I want to retrieve that in my current model.
How can I do that?
My Site Model is like;
class Site extends Model
{
protected $table = 'vwSitesPortal';
protected $primaryKey = 'SiteId';
...
My Current model is like;
class Alarm extends Model
{
protected $table = 'vwAlarm';
protected $primaryKey = 'AlarmId';
...
public function Site()
{
return $this->belongsTo(**related**: Site::class,
**foreignKey**:'SiteId', **ownerKey:**'SiteId'
}
Schema::create('favorites', function (Blueprint $table) {
$table->integer('lecture_id')->unsigned();
$table->integer('user_id')->unsigned();
$table->timestamps();
$table->primary(['lecture_id', 'user_id']);
$table->foreign('lecture_id')
->references('id')->on('lectures')
->onDelete('cascade');
$table->foreign('user_id')
->references('id')->on('users')
->onDelete('cascade');
});
see this example
Related
I have a customer model that has many contacts. I defined a relationship to get the most recent contact of the customer using the "Has One Of Many" relationship in Laravel 8:
Models
class Customer extends Model
{
use HasFactory;
public function contacts()
{
return $this->hasMany(Contact::class);
}
public function latestContact()
{
return $this->hasOne(Contact::class)->ofMany('contacted_at', 'max')->withDefault();
}
}
class Contact extends Model
{
use HasFactory;
protected $casts = [
'contacted_at' => 'datetime',
];
public function customer()
{
return $this->belongsTo(Customer::class);
}
}
Migration (contact model)
class CreateContactsTable extends Migration
{
public function up()
{
Schema::create('contacts', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->softDeletes();
$table->foreignID('customer_id');
$table->string('type');
$table->dateTime('contacted_at');
});
}
}
In my view, I want to show all customers and order them by their latest contact. However, I can't figure out how to do that.
I tried to achieve it via the join method but then I obviously get various entries per customer.
$query = Customer::select('customers.*', 'contacts.contacted_at as contacted_at')
->join('contacts', 'customers.id', '=', 'contacts.customer_id')
->orderby('contacts.contacted_at')
->with('latestContact')
Knowing Laravel there must be a nice way or helper to achieve this. Any ideas?
I think the cleanest way to do this is by using a subquery join:
$latestContacts = Contact::select('customer_id',DB::raw('max(contacted_at) as latest_contact'))->groupBy('customer_id');
$query = Customer::select('customers.*', 'latest_contacts.latest_contact')
->joinSub($latestContacts, 'latest_contacts', function ($join){
$join->on([['customer.id', 'latest_contacts.customer_id']]);
})
->orderBy('latest_contacts.latest_contact')
->get();
More info: https://laravel.com/docs/8.x/queries#subquery-joins
I suspect there is an issue with your migration, the foreign key constraint is defined like this:
Check the documentation:
https://laravel.com/docs/8.x/migrations#foreign-key-constraints
Method 1: define foreign key constraint
public function up()
{
Schema::create('contacts', function (Blueprint $table) {
$table->id();
$table->foreignId('consumer_id')->constrained();
$table->string('type');
$table->dateTime('contacted_at');
$table->timestamps();
$table->softDeletes();
});
}
Method 2: define foreign key constraint
public function up()
{
Schema::create('contacts', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('customer_id');
$table->foreign('customer_id')->references('id')->on('customers');
$table->string('type');
$table->dateTime('contacted_at');
$table->timestamps();
$table->softDeletes();
});
}
Below are all of the models, migrations and controller.
Donation Model
class Donation extends Model
{
protected $guarded =[];
public function users(){
return $this->hasMany(User::class);
}
public function items(){
return $this->belongsTo(DonationItems::class);
}
}
Donation Items Model:
class DonationItems extends Model
{
protected $guarded=[];
public function donation(){
return $this->hasMany(Donaition::class);
}
}
Donation Items Migration:
public function up()
{
Schema::create('donation_items', function (Blueprint $table) {
$table->id();
$table->string('category');
$table->timestamps();
});
}
Donation Migration:
public function up()
{
Schema::create('donations', function (Blueprint $table) {
$table->id();
$table->string('item');
$table->unsignedInteger('user_id');
$table->unsignedInteger('donation_item_id');
$table->timestamps();
});
}
In my controller I want to access the items as follows:
$don = Donation::all();
$don->items;
But I'm unable to achieve this.
Its not working because laravel follows one rule for relationships:
Remember, Eloquent will automatically determine the proper foreign key column on the Comment model. By convention, Eloquent will take the "snake case" name of the owning model and suffix it with _id. So, for this example, Eloquent will assume the foreign key on the Comment model is post_id.
So you can try by supplying local and foreign id
So it would look something like this
Donation Model
class Donation extends Model
{
protected $guarded =[];
public function users(){
return $this->hasMany(User::class);
}
public function items(){
return $this->belongsTo(DonationItems::class, 'donation_item_id', 'id');
}
}
Donation Items Model:
class DonationItems extends Model
{
protected $guarded=[];
public function donation(){
return $this->hasMany(DonationItems::class, 'id', 'donation_item_id');
}
}
I am writing from my head you might need to swap local and foreign ID's
I seem to be having a problem understanding this hierarchical relationship.
Farm > Fields > Shepherds > Sheep
It seems a pretty straightforward hierarchy - Farm hasMany fields, field hasMany shepherds, shepherd hasMany sheep.
Sheep belong to a shepherd, shepherds belongs to fields, fields belong to farms.
I have defined this model relationships thus:
class Sheep extends Model {
protected $fillable ['name'];
public function shepherd() {
return $this->belongsTo('App\Shepherd');
}
}
class Shepherd extends Model {
protected $fillable ['name'];
public function field() {
return $this->belongsTo('App\Field');
}
public function sheep() {
return $this->hasMany('App\Sheep');
}
}
class Field extends Model {
protected $fillable ['name'];
public function farm() {
return $this->belongsTo('App\Farm');
}
public function shepherd() {
return $this->hasMany('App\Shepperd');
}
}
class Farm extends Model {
protected $fillable ['name'];
public function field() {
return $this->hasMany('App\Field');
}
}
public function up()
{
Schema::create('farms', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
});
}
public function up()
{
Schema::create('fields', function (Blueprint $table) {
$table->increments('id');
$table->integer('farm_id');
$table->string('name');
});
}
public function up()
Schema::create('shepherds', function (Blueprint $table) {
$table->increments('id');
$table->integer('field_id');
$table->string('name');
});
}
public function up()
Schema::create('sheep', function (Blueprint $table) {
$table->increments('id');
$table->integer('shepherd_id');
$table->string('name');
});
}
I would expect to be able to save each model in the following manner.
$farm = new App\Farm;
$farm->name = 'West Farm';
$field = new App\Field;
$field->name = 'The orchard';
$shepherd = new App\Shepherd;
$shepherd->name = 'Jason';
$sheep = new App\Sheep;
$sheep->name = 'Sean';
$farm->save();
$farm->field()->save($farm);
$farm->field->shepherd()->save($shepherd);
$farm->field->shepherd->sheep()->save($sheep);
But it does not work. Once I get to $farm->field->shepherd()->save($shepherd); the process breaks down. I would appreciate some assistance in the correct manner of saving using the relationships between all the tables.
I'm pulling my hair out trying to understand this, so any help would be greatly appreciated.
thanks
Your code breaks here:
$farm->field->shepherd()->save($shepherd);
Farms have many fields, so when you reference $farm->field, you're getting a collection of Field object, not just a single Field object.
To make it work, you need to either reference $farm->field[0]
$farm->field[0]->shepherd()->save($shepherd);
or just use the $field object you created before:
$field->shepherd()->save($shepherd);
I'd also suggest to use plural names for your hasMany relations (fields, sheeps, etc.) - this way you'll always remember that the referenced fields refer to a collection, not a single object
I have the follow migration code (simplified):
Ads Table
class CreateAdsTable extends Migration {
public function up()
{
Schema::create('ads', function(Blueprint $table) {
$table->increments('id');
$table->integer('authors_id')->unsigned()->index();
$table->foreign('authors_id')->references('id')->on('authors');
$table->timestamps();
});
}
}
Authors Table
class CreateAuthorsTable extends Migration {
public function up()
{
Schema::create('authors', function(Blueprint $table) {
$table->increments('id');
$table->string('name', 200);
$table->timestamps();
});
}
}
And my models are:
Ad Model
class Ad extends \Eloquent {
protected $table = 'ads';
// Ad __hasOne__ Author
public function author() {
$this->belongsTo('Author');
}
}
Author Model
class Author extends \Eloquent {
// The database table used by the model
protected $table = 'authors';
// Author __hasMany__ Ads
public function ads() {
$this->hasMany('Ad');
}
}
But when I try to get the author using Ad::find(1)->author i receive Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation.
Someone can help me and find the error?
You have to return it:
return $this->belongsTo('Author');
I have two models User.php and Blog.php and the content,
Model User.php
<?php
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Eloquent implements UserInterface, RemindableInterface {
protected $softDelete = true;
protected $table = 'users';
protected $hidden = array('password');
//-----
public function blogs()
{
return $this->has_many('Blog');
}
//----
Model Blog.php
<?php
class Blog extends Eloquent {
protected $guarded = array();
public static $rules = array();
public function author()
{
return $this->belongs_to('User', 'author_id');
}
}
The Controller, BlogsController.php
<?php
class BlogsController extends BaseController {
public function index()
{
$posts = Blog::with('author')->get();
return Response::json(array(
'status' => 'success',
'message' => 'Posts successfully loaded!',
'posts' => $posts->toArray()),
200
);
}
//-----
The blogs schema,
Schema::create('blogs', function(Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->text('body');
$table->integer('author_id');
$table->timestamps();
$table->softDeletes();
});
And the users schema,
Schema::create('users', function(Blueprint $table) {
$table->integer('id', true);
$table->string('name');
$table->string('username')->unique();
$table->string('email')->unique();
$table->string('password');
$table->timestamps();
$table->softDeletes();
});
When I call Blog::with('author')->get(); from BlogsController, I am getting this error:-
"type":"BadMethodCallException","message":"Call to undefined method Illuminate\\Database\\Query\\Builder::belongs_to()"
And when I change Blog::with('author')->get(); to Blog::with('author')->all();, the error become:-
"type":"BadMethodCallException","message":"Call to undefined method Illuminate\\Database\\Query\\Builder::all()"
I am using latest update for Laravel 4. What is the wrong with my code?
Your going to love and hate this answer, change belongs_to to belongsTo. Same goes for has_many to hasMany and has_one to hasOne.
Laravel 4 moved to using camel case for methods. Your method not being found on the eloquent model, it falls back to calling it on the query builder, laravel does this to allow short cutting to methods like select() and where().
The second error you were getting, when using all(), is because all() is a static method defined on eloquent and does not work with eager loading. get() is effectively the same thing as all().