Join database tables using foreign key laravel - php

I have two tables that I need to join in order to access more data. My first table thought_journal_entries contains many id values from the second table emotions. The primary key in emotions is id and the foreign key in thought_journal_entries is em_id.
This is in the Emotions model
public function thoughtJournalEntry() {
return $this->belongsTo(ThoughtJournalEntry::class, 'id');
}
This is in the ThoughtJournalEntry model
public function emotions() {
return $this->hasMany(Emotions::class, 'id');
}
This is how far I've got, not sure if this is correct and how I would join these in the controller?

If you set em_id in thought_journal_entries table, that means that thoughtJournalEntry belongs to Emotions, and Emotions hasMany thoughtJournalEntry, so in this case relations must be declared this way
// Emotions class
public function thoughtJournalEntries() {
return $this->hasMany(ThoughtJournalEntry::class, 'em_id');
}
// ThoughtJournalEntry class
public function emotion() {
return $this->belongsTo(Emotions::class, 'em_id');
}
// access from controller
$emotion->thoughtJournalEntries;
$thoughtJournalEntry->emotion;
If this type of relations is not what you wanted, then probably you have to change your db tables

Related

How to create relationship between 3 models in laravel?

SQL scheme:
bulletins
id increment
deals
id increment
seller_id
buyer_id
deals_items - items = bulletins
id increment
title
desc
bulletin_id
deal_id
How can I get deal row by bulletin id? In raw SQL it looks like:
select `deals`.* from `deals` inner join `deals_items` on `deals_items`.`deal_id` = `deals`.`id` where `deals_items`.`bulletin_id` = 10572
I tried:
public function deals()
{
return $this->hasManyThrough(DealItem::class,Deal::class, 'bulletin_id','dealid','id');
}
But it seems a wrong way. Can't find right way in laravel doc about relation.
#HCK shows right way.
but when I doing $bulletin->deals() in blade template I got empty collection of deals.
When just $bulletin->deal - all is fine, we have collection of deals.
I using protected $with = ['deals'] in my bulletin model, but what is different call method or property? Why with method empty result?
#Amarnasan was close, but the order of the foreign keys was wrong. Try this:
Deal.php
public function bulletins()
{
return $this
->belongsToMany(Bulletin::class, 'deals_items', 'deal_id', 'bulletin_id')
->withPivot('title','desc');
}
Bulletin.php
public function deals()
{
return $this
->belongsToMany(Deal::class, 'deals_items', 'bulletin_id', 'deal_id')
->withPivot('title','desc');
}
From the docs:
As mentioned previously, to determine the table name of the
relationship's joining table, Eloquent will join the two related model
names in alphabetical order. However, you are free to override this
convention. You may do so by passing a second argument to the
belongsToMany method:
return $this->belongsToMany('App\Role', 'role_user');
In addition to customizing the name of the joining table, you may also
customize the column names of the keys on the table by passing
additional arguments to the belongsToMany method. The third argument
is the foreign key name of the model on which you are defining the
relationship, while the fourth argument is the foreign key name of the
model that you are joining to:
return $this->belongsToMany('App\Role', 'role_user', 'user_id', 'role_id');
Update
When you access the relationship as a method: $bulletin->deals() you are accessing the relationship itself. This will return an instance of \Illuminate\Database\Eloquent\Relations\BelongsToMany (in your case). Here the query is not executed yet, so you could keep adding constrains to your query, for example:
$bulletin
->deals()
->where('seller_id', 45) // <---
->skip(5) // <---
-> ... (And so on)
When you access it as a dynamic property, you are already executing the query, so this will return a Collection instance. Is the same as calling the relationship as a method and then attach the ->get() at the end, so this two are equivalent:
$bulletin->deals()->get()
// equals to:
$bulletin->deals
Check this other answer, it answers your question.
DealClass:
public function bulletins()
return $this->belongsToMany('App\Bulletin', 'deals_items ', 'bulletin_id', 'deal_id')->withPivot('title','desc');
}
BulletinClass:
public function deals()
return $this->belongsToMany('App\Deal', 'deals_items ', 'deal_id', 'bulletin_id')->withPivot('title','desc');
}
deals model -
public function bulletins()
return $this->belongsToMany(Bulletin::class, 'deals_items ', 'bulletin_id', 'deal_id');
}
bulletin model:-
public function deals()
{
return $this
->belongsToMany(Deal::class, 'deals_items', 'deal_id', 'bulletin_id',);
}

foreign keys equivalents of laravel relationships

so i have those models
// Curso.php
public function trienio()
{
return $this->hasMany('App\Trienio');
}
// Trienio.php
public function curso()
{
return $this->belongsTo('App\Curso');
}
public function oe()
{
return $this->belongsTo('App\OE');
}
public function aluno()
{
return $this->hasMany('App\Aluno');
}
// Oe.php
public function trienio()
{
return $this->hasMany('App\Trienio');
}
// Aluno.php
public function trienio()
{
return $this->belongsTo('App\Trienio');
}
public function pap()
{
return $this->hasOne('App\PAP');
}
// Pap.php
public function aluno()
{
return $this->belongsTo('App\Aluno');
}
public function video()
{
return $this->hasOne('App\Video');
}
// Video.php
public function pap()
{
return $this->belongsTo('App\Pap');
}
and i'm having trouble "converting" those to sql foreign keys. can anybody give me insight on what the foreign keys equivalents will be considering those eloquent relationships? ty in advance
p.s - i can provide more details if needed.
p.s2 - what i REALLY want to know is how i should structure the fields, the sql foreign keys and the constraints based on those eloquent relationships. and how do i that ?
When ever you have hasMany relation, please specify the foreign key used. as follows
// Curso.php
public function trienio()
{
return $this->hasMany('App\Trienio', 'curso_id');
}
this means you have one to many relation ship between Curso and Trienio, but the table trienio must have a field as curso_id (If you want default implementation, no need to establish hard relationship using SQL foreign key constraints) By default this relation will work.
And in belongsTo you dont need to specify the key (Optional).
To fetch the data from Curso
$curso = Curso::find(1);
$trienio = $curso->trienio;
At the trienio side, its okay
// Trienio.php
public function curso()
{
return $this->belongsTo('App\Curso');
}
Similarly for all other.
Note: If you do like this for Curso and Trienio (one to many), the table of Trienio model must have curso_id field and by default relationship will work without doing anything at SQL side.
Update:Using SQL, modify table of Trienio model.
ALTER TABLE trienios MODIFY COLUMN curso_id INT NOT NULL,
ADD CONSTRAINT trienios_curso_id_fk
FOREIGN KEY(curso_id)
REFERENCES Curso(id);
Using Schema builder (Migration Files) Link
$table->foreign('curso_id')
->references('id')->on('curso')
->onDelete('cascade');
You can specify the cascade rule.

laravel one to one relationship

I have xml_document table with these columns:
id
general_information_id
I have general_information table with these columns:
id
domain
log_file
The relationship between them is one to one.
Have I build the relationship correctly? Or I need to add xml_document_id column to the general_information table.
Secondly:
I have added a row to the xml_doucment and now I want to add a row to the general_information and link this new row to the xml_document
I tried this:
$xmlDocument = XmlDocument::find(Input::get(4));
$generalInformation = new GeneralInformation($dataGeneralInformation);
$generalInformation->xmlDocument()->associate($xmlDocument);
//$xmlDocument->generalInformation()->attach($generalInformation);
$generalInformation->save();
$xmlDocument->save();
but I got error that xml_document_id column doesn't exist in the general_information table.
I tried to replace associate with attach but I got that attach is not an existed function.
please help me I am tried of this one to one relationship, I couldn't know what is the correct way to do id. I don't know where to add columns in the database and what to do in the models. I have tried a lot of things but still so confused.
Update 1
class GeneralInformation extends Eloquent{
.....
public function xmlDocument(){
return $this->belongsTo('XmlDocument');
}
}
class XmlDocument extends Eloquent {
....
public function generalInformation(){
return $this->hasOne('GeneralInformation','general_information_id');
}
}
To make a one-to-one relationship, you need to store the primary key of parent table in the child table as a foreign key. So if xml_document is parent and if it contains many general_information then the id field of the xml_document should be present in in the general_information table as xml_document_id.
So, you may build the one-to-one relation like this:
// xml_document model
public function generalInfo()
{
return $this->hasOne('GeneralInformation');
}
Then the declare the GeneralInformation model.
This is what you want:
class GeneralInformation extends Eloquent
{
public function xmlDocument()
{
return $this->hasOne('XmlDocument');
}
}
class XmlDocument extends Eloquent
{
public function generalInformation()
{
return $this->belongsTo('GeneralInformation','general_information_id');
}
}

Laravel Eloquent Joins

I have below query in core php:
SELECT DISTINCT device_tocken FROM push_details JOIN users ON users.id=push_details.user_id
I have to integrate it in laravel 4
Application already have User extends Eloquent class
I created Push_details class as below
class Push_details extends Eloquent {
public $table = 'push_details';
public function User() {
return $this->hasMany('\User','id');
}
}
Table : users
Primary key : id
Table: push_details
Primary key: id
Foreign key: user_id belongsTo('users.id');
But i m not able to get expected result.
One more thing i didn't write anything in User's model yet.
Only way to join table is.. to join it, as Eloquent relations don't work using joins but separate queries with WHERE IN clauses. So this will do:
DB::table('push_details')
->select('device_tocken')
->distinct()
->join('users','users.id','=','push_details.user_id')
->get();
Above will return array of stdObject's so or if you need Eloquent Collection with Eloquent models as a result replace DB::table('push_details')->select... with PushDetails::select...
Now, correct your relations, as they are wrong:
// PushDetails model (as previously stated, I suggest renaming it to StudlyCase)
public function user() {
return $this->belongsTo('\User','user_id'); // user_id is may be omitted here
}
// User model
public function pushDetails() {
return $this->hasMany('\PushDetails','user_id'); // user_id is may be omitted here as well
}
In your User model, you need to link back to the PushDetails model, like so
class User extends Eloquent {
public function push_details() {
return $this->belongsTo('PushDetails');
}
}
Use CamelCase for Class names, because laravel has several functions, in which CamelCase are changed to snake_case
Change
public function User() {
return $this->hasMany('\User','id');
}
to
public function users() {
return $this->hasMany('User');
}
See the docs 'Eloquent ORM' for more...

Laravel eager relationships empty query

I have 3 tables : hotels, hotels_data, hotels_types
Table hotels have id, type, stars, etc... type field is set as foreign key referencing type_id in hotels_types. I'm managing to get the correct data from hotels_data but have an empty result on getting hotels_types title and I don't understand why.
The code is the following :
class Hotel extends Eloquent {
public function getList() {
$data = Hotel::select('id','stars')->with('HotelData', 'HotelType')->paginate(10);
return View::make('hotels.index')->with('hotels', $data);
}
public function HotelData()
{
return $this->hasOne('HotelsData')->select('id','hotel_id','title');
}
public function HotelType()
{
return $this->hasOne('HotelType','type_id', 'type')->select('id','type_id','title');
}
}
You're using the wrong relationship for HotelType()
Your Hotel model should use the inverse of hasOne, which is belongsTo, because it contains the foreign key to HotelType (when a table contains a foreign key, it always belongs to the table being pointed to).
The following should work:
public function hotelType() {
return $this->belongsTo('HotelType','type', 'type_id')->select('id','type_id','title');
}
I've obtained the desired result with the following:
Hotel::select('hotels.*','hotels_types.title as type')
->join('hotels_types', 'hotels.type', '=', 'hotels_types.type_id')
->with('HotelData');

Categories