datamapper orm advanced relationship - codeigniter

I use datamapper orm with codeigniter
my table is:
person
id, name, related_person1_id, related_person2_id
person can have 1 related_person1, 1 related_person2
how can i set the relationship in my model file ?
it is described in the docu:
class Person extends DataMapper {
$has_many = array(
'related_person' => array(
'class' => 'person',
'other_field' => 'person',
'reciprocal' => TRUE
),
'person' => array(
'other_field' => 'related_person',
'reciprocal' => TRUE
)
);
}
how can I set in for more than 1 related person ? and how shold i set up my table ? i wanna stay with 1 "person" table.
THX

Best bet is to create a separate table for relationships.
So you have a person table:
id:int
name:text
then a relationship table
id:int
person_id:int
related_to_person_id:int
relationship
This way you can have as many relationships per person as you want.
Persons:
id | name
1 | Jimmy Doublechin
2 | Opie Hardabs
3 | Anthony Predator
Relationships:
id | person_id | related_to_person_id | relationship
1 | 1 | 2 | lover
2 | 1 | 3 | best buddy evar
3 | 3 | 2 | Mother
Then
class Person extends Datamapper {
public $has_many = array('relationships');
...
class Relationships extends Datamapper {
public $has_one = array('person');
....

Related

Laravel Has Many Relationship with a OR condition

I need an help understanding Eloquent has many relation in this particular scenario.
This is the scenario:
Airport Table
| id | code | name |
---------------------
| 1 | XXX | XXX |
---------------------
Route Table
| id | from | to |
-------------------
| 1 | 1 | 2 |
--------------------
As above, ONE airport table 'id' can be a foreign key in 'from' OR 'to' Route Table column.
What I'd like to do is to retrieve all records from Airports table with its routes (Where the airport can appear as a departure or as a destination).
For example:
[
{
'id': 1,
'code': 'JFK',
'name': 'John F. Kennedy International Airport'
'routes' : [
{
'id': 1,
'from': 1 //JFK airports table id
'to': 22 //somewhere
},
{
'id': 1,
'from': 334 //somewhere
'to': 1 //JFK airports table id
}
]
}
]
Obviously I know how to do it with a SQL query or using Eloquen but what I want to understand is if it can be done natively in the Model by expressing a relationship.
Maybe adding to the relationship
->orWhereColumn('Route.to','AirportTable.id')
The "Eloquent has many relation" you are imagining does not exist, and also does not make sense as a relation. Pivot table columns have semantic meaning, just like in your case of from and to.
Firstly, this is not a HasMany, it is a BelongsToMany (Many to Many) in Eloquent speak. If you want to do this purely with relations, then you will need to define both of them. Airports are destinations when they are in the to column, and Airports are origins when they are in the from column.
To get all routes an Airport is a part of, we can simply merge the results of the two relations.
The $appends attribute is used to automatically append the data when serializing.
The $with attribute is used to always eagerload these relations when retrieving Airports from the database.
Airport.php
protected $appends = ['routes'];
protected $with = ['destinations', 'origins'];
public function destinations()
{
return $this->belongsToMany(Airport::class, 'routes', 'from', 'to')
->withPivot(['id', 'from', 'to']);;
}
public function origins()
{
return $this->belongsToMany(Airport::class, 'routes', 'to', 'from')
->withPivot(['id', 'from', 'to']);
}
public function getRoutesAttribute()
{
return $this->destinations->pluck('pivot')
->merge($this->origins->pluck('pivot'));
}
Now if you were to do:
Airport::query()->take(5)->toArray();
You would see all of the routes associated on each of the Airport results.

How to query a table based on criteria of another table in Laravel?

In my laravel project I have an inventory and a medicine table which the formats are as the following:
Inventory Table
id | medicine_id | expiry_date
-------|-----------------|-------------
1 | 1 | 13-11-2021
2 | 2 | 01-01-2020
3 | 2 | 23-05-2024
Medicine Table
id | name | category
-------|-----------------|-------------
1 | Hemophine | Syringe
2 | andrenalin | Tablet
3 | aspirin | Capsule
The models are set as below:
Inventory Model
class Inventory extends Model
{
public $incrementing = false;
public function medicine(){
return $this->belongsTo('App\Medicine', 'medicine_id');
}
}
Medicine Model
class Medicine extends Model
{
public $incrementing = false;
public function inventory(){
return $this->hasMany('App\Inventory', 'medicine_id');
}
}
For retrieving all the inventories with a specific category such as Syringe, I tried eager loading, but couldn't figure out the flaws. Here is what I did to get all the inventories with a Syringe category, but it didn't work.
public function index()
{
$medicines = Inventory::where('medicine_id'->category, "Syringe")->get();
foreach($medicines as $medicine){
echo $medicine->medicine->name ." ".$medicine->expiry_date;
echo "<br>";
}
}
Now, Is there anyway to get all the inventory items based on their categories they are in? in this case in "Syringe" category?
Your syntax is a bit wrong, in order to load the medicine for each inventory you need to use with and the where function is where('column', value)
So change it to this:
$medicines = Inventory::with([
'medicine' => function($query) {
$query->where('category', "Syringe");
}
])->get();
or even better the other way around:
$medicines = Medicine::with('inventory')->where('category', 'Syringe')->get();

How to combine models and order by model two data in Laravel 5.4

I would like to be able to output leaders in a section by their position in a group. I'm thinking of combining these tables through a pivot table ordered by position from the groups table.
These are the three class I have relationships established
class Leader extends Model
{
public function groups()
{
return $this->belongsToMany('App\Group');
}
}
class Group extends Model
{
public function leaders()
{
return $this->belongsToMany('App\Leader');
}
}
class GroupLeader extends Model
{
// Maybe some function here?
}
I would like to be able to get the groups in the controller and pass them individually kinda like this.
$group1 = Leader::where('group', '=', 'group1_name')->orderBy('position', 'asc');
$group2 = Leader::where('group', '=', 'group2_name')->orderBy('position', 'asc');
return view('page.leadership')->with([
'group1' => $group1,
'group2' => $group2,
]);
Then I would pass the variables to include files which would loop through them in order.
Here is my table structure
leaders
--------
| id
| first_name
| last_name
| deceased
----------
groups
----------
| id
| group
| title
| position
-----------
group_leader
-------------
| id
| group_id
| leader_id
------------
Try it
$groups = Leader::whereIn('group', ['group1_name', 'group2_name'])
->orderBy('position', 'asc')
->groupBy('group', 'id')
->get(['group', 'id']);

Relation between 2 tables with a link table

I have this tables :
topics
-------
id | title
------+----------
1 | Sport
2 | Social
posts_topics
------------
id | post_id | topic_id
------+--------------+------------
1 | 1 | 1
2 | 1 | 2
posts
------
id | title
-----+----------
1 | A Test Post
I store topics in topics table and use posts_topics to link between my posts table and topics
now I want select title of topics when selecting posts,
After some searching in StackOverflow and Google, I've written this models:
Posts.php
public function post_topics()
{
return $this->hasMany('App\PostTopics');
}
PostTopics.php
public function topics()
{
return $this->hasManyThrough('App\Posts', 'App\Topics', 'id', 'topic_id');
}
Topics.php
protected $table = 'topics';
and in my controller I trying to fetch:
$post = Posts::with('post_topics')->find($post_id);
dd($post);
Now this code will work but cannot return title of topics.
Change the code to a Many to Many relationship in Posts.php:
public function post_topics()
{
return $this->belongsToMany('App\Topics', 'posts_topics', 'post_id', 'topic_id');
}
And then call it:
$post = Posts::with('post_topics')->find($post_id);
Try this and check if it works for you.

Joining pivot table to access data

I am trying to access data from a database query which I think will need a join. I have users that can be apart of many groups. I am using a belongsToMany
relationship. My Models are like so
class User extends Model
{
protected $table = 'users';
protected $guarded = [];
public function group()
{
return $this->belongsToMany('App\Group', 'users_user_groups')->withPivot('user_id', 'group_id');
}
}
class Group extends Model
{
protected $table = 'user_groups';
protected $guarded = [];
use SoftDeletes;
public function user()
{
return $this->belongsToMany('App\User', 'users_user_groups')->withPivot('user_id', 'group_id');
}
}
When I run everything I need too, I might get data like the following.
users
+----+---------------+
| id | name |
+----+---------------+
| 1 | John Doe |
+----+---------------+
user_groups
+----+---------------+-----------------+
| id | name | description |
+----+---------------+-----------------+
| 1 | Group AA | Something |
+----+---------------+-----------------+
| 2 | Group BB | Something |
+----+---------------+-----------------+
users_user_groups
+----+---------------+-----------------+
| id | user_id | group_id |
+----+---------------+-----------------+
| 1 | 1 | 1 |
+----+---------------+-----------------+
| 2 | 1 | 2 |
+----+---------------+-----------------+
So I know user with the id 1 belongs to the user_groups with ids of 1 and 2. What I am trying to do is grab all the users within my database who
belong to a user_group with the name admin. So I am trying something like this
DB::table('users')->select('userName')
->join('user_groups', 'users_user_groups')
->where('name', '=', 'admin')->get();
This I know is all wrong, how can I get all users within a group when using belongsToMany and a pivot table?
Thanks
Eloquent uses relations, not the query builder.
You can achieve what you're aiming for by doing something like this:
$group = Group::where('name', 'admin')->first();
$users = $group->users; // Where users is the name of your relationship (At the moment you have user)
Under the hood that will do two SQL statements and map them together in eloquent objects, rather than a join. The statements will look something like this:
select * from user_groups where name = ? and deleted_at is not null limit 1
select * from users where id in (?, ?)
When you have an instance Group you execute the relationship by calling it as if it was a property. So after that $users will contain a collection of User instances, so you can just loop through them:
foreach ($users as $user) {
// Do something with $user
}

Resources