How to access third table data from eloquent relation between two tables in laravel? - laravel

i am sorry, if my question not make sense...
i have these two tables Area, and Address and are related via foreign key... here is the area and address models
class Area extends Model
{
protected $table='areas';
public function sections(){
$this->hasMany(Area::class,'area','id');
}
public function address(){
$this->belongsTo(Address::class,'id');
}
}
class Address extends Model
{
protected $table='address';
public function area(){
return $this->hasMany(Area::class,'id');
}
}
and i have a third table section which is connected to area table.
my question can i make eloquent relation that can access the data of address table from the section "section table connect with area not address"
class Section extends Model
{
protected $table ='sections';
protected $fillable =[
'sec_code',
'area',
'id',
];
public function beneficiaries(){
return $this->hasMany(Beneficiary::class,'ben_sec','id');
}
public function area_sec(){
return $this->belongsTo(Area::class,'area');
}
public function address(){
// need the eloquent relation if could
}
}
thank you

Call it as a property not a method:
$model->area_sec;

You can get the data with access it from your Area relation first, so the code will be like this:
class Section extends Model
{
protected $table ='sections';
protected $fillable =[
'sec_code',
'area',
'id',
];
public function area_sec(){
return $this->belongsTo(Area::class,'area');
}
public function address(){
return $this->area_sec->address;
}
}

Related

How to properly use Spatie\LaravelData for retrieveing data?

I was introduced to Spatie\LaravelData when I was searching for how to implement DTOs in Laravel.
Using Data classes for insert/update for a single model is pretty straightforward. I tend to keep my updates atomic in this way.
However I have a problem for using LaravelData to retrieve objects and send to front end, specially with nested models.
I have this example I have Post and Category models:
class Post extends Model
{
use HasFactory;
protected $fillable = [
'title',
'category_id'
];
public function category(): BelongsTo
{
return $this->belongsTo(Category::class);
}
}
class Category extends Model
{
use HasFactory;
protected $fillable = [
'category',
'description'
];
}
I have these Data classes:
class PostData extends Data
{
public function __construct(
public string $title,
public string $category_id,
) {
}
}
class CategoryData extends Data
{
public function __construct(
public string $category,
public string $description
) {
}
}
I want to be able to send a STO object with Post and its Category, also would love to be able to have a collection of Posts and their Categories for index page.
I tried using this approach as described in their documentation, but first it gives an error and second I'm not sure how to return that from index() or view() methods in controller:
class PostData extends Data
{
public function __construct(
public string $title,
public string $category_id,
#[DataCollectionOf(CategoryData::class)]
public DataCollection $category,
) {
}
}
Anyone ever used Spatie\LaravelData for returning DTOs to from end?
You are trying to use a DataCollection when you should be using nesting. This is because your post has a BelongsTo relationship with the category model.
class PostData extends Data
{
public function __construct(
public string $title,
public string $category_id,
public CategoryData $category,
) {
}
}

Laravel nested cross database relation

Why set connection does not work in nested relation?
Follower.php
class Follower extends Model {
$connection = 'followers';
public function details() {
return $this->belongsTo(User::class, 'user_id');
}
}
User.php
class User extends Model {
$connection = 'users';
protected $withCount = ['notifications'];
public function notifications() {
return $this->setConnection('followers')->hasMany('App\Models\Notifications');
}
}
and the query:
Follower::query()->where('user_id', 1)->with('details')->get();
and it throws :
SQLSTATE[42S02]: Base table or view not found: 1146 Table
'users.notifications' doesn't exist (SQL: select ` ....
But when I try this it works very well
User::with('notifications')->find(1);
Update
Notification.php
class Notification extends Model
{
protected $fillable = [
'user_id',
'builder',
'notification_type',
'comment_id',
'read_at'
];
}
This is a known issue with laravel since 2018, for more information see this thread , also there is a open pull request to fix this issue and will get fixed till next release
for now you can use hoyvoy/laravel-cross-database-subqueries package
install package using this
composer require hoyvoy/laravel-cross-database-subqueries
Follower.php
use Hoyvoy\CrossDatabase\Eloquent\Model;
class Follower extends Model {
$connection = 'followers';
public function details() {
return $this->belongsTo(User::class, 'user_id');
}
}
User.php
use Hoyvoy\CrossDatabase\Eloquent\Model;
class User extends Model {
$connection = 'users';
protected $withCount = ['notifications'];
public function notifications() {
return $this->setConnection('followers')->hasMany('App\Models\Notifications');
}
}
for every model you have add the default protected $connection

Bind Laravel table to other database connection

I am finding some difficulties to bind one relationship table to my second database.
In "db_main" I have tables, with the basic details about each object and than I have other tables: "db_site1", "db_site2" etc, in which tables I save detailed information about the same objects.
Everything is working find with that schema, except one situation in that I have relationship table (bookmaker_games), which must be only on "db_main". The table save the relations between bookmakers and games.
On my website1 I want to list the games of a bookmaker with the following models:
class Bookmaker extends Model {
public function games() {
// here the database is "db_site1"
return $this->belongsToMany('App\Models\Game', 'bookmaker_games', 'bookmaker_id', 'game_id');
}
}
class Game extends Model {
public function bookmakers() {
// here the database is "db_site1"
return $this->belongsToMany('App\Models\Bookmaker', 'bookmaker_games', 'game_id', 'bookmaker_id');
}
}
class BookmakerGame extends Model {
protected $connection = 'db_main';
}
When I try to return all games, it is thinking that "bookmaker_games"-table is on database "db_site1", which is wrong.
What is the best way to tell that relationship to look at the correct database ?
Declare BookmakerGame as a subclass of Illuminate\Database\Eloquent\Relations\Pivot
Then define the relationships to use it.
Prefixing the connection name
//...
use Illuminate\Database\Eloquent\Relations\Pivot;
class Bookmaker extends Model {
public function games() {
// here the database is "db_site1"
return $this->belongsToMany(
'App\Models\Game', 'db_main.bookmaker_games', 'bookmaker_id', 'game_id')
->using('App\Models\BookmakerGame');
}
}
class Game extends Model {
public function bookmakers() {
// here the database is "db_site1"
return $this->belongsToMany(
'App\Models\Bookmaker', 'db_main.bookmaker_games', 'game_id', 'bookmaker_id')
->using('App\Models\BookmakerGame');
}
}
class BookmakerGame extends Pivot {
protected $connection = 'db_main';
}
Using the class path to the pivot
use Illuminate\Database\Eloquent\Relations\Pivot;
class Bookmaker extends Model {
public function games() {
// here the database is "db_site1"
return $this->belongsToMany(
'App\Models\Game', 'App\Models\BookmakerGame', 'bookmaker_id', 'game_id');
}
}
class Game extends Model {
public function bookmakers() {
// here the database is "db_site1"
return $this->belongsToMany(
'App\Models\Bookmaker', 'App\Models\BookmakerGame', 'game_id', 'bookmaker_id');
}
}
class BookmakerGame extends Pivot {
protected $connection = 'db_main';
protected $table = 'bookmaker_games';
}

Not able to create eloquent relationship with table which have custom primary key

When i'm trying to get user details from company Model i'm getting NULL value.
class User extends Model
{
protected $primaryKey = 'uid';
}
class Company extends Model
{
$table = 'company';
public function users(){
return $this->hasMany('App\User','user_id','uid');
}
}
class RepoController{
public function index(){
$user = Company::where('id',1)->with('user')->get();
/// Returning value but without Users
}
}`
users table should contain company_id and you should define id as company ID because company table doesn't use custom ID:
public function users()
{
return $this->hasMany('App\User', 'company_id', 'id');
}
Or just this:
public function users()
{
return $this->hasMany('App\User');
}
Also, you're trying to load user relationship, but it should be users(), so do this instead:
Company::where('id', 1)->with('users')->get();
I think your ids are in wrong position
try swapping them like
return $this->hasMany('App\User','uid','user_id');

Laravel belongsTo and hasMany relationship on same model

How do you apply belongsTo and hasMany relationship on same model?
For example, I have one User and one Project model. Now Project model has method user() and User model has projects() method.
Now I want a user to share projects with other users. So that I can have methods like users() in Project model and shared_projects() in User model.
How I can achieve that?
Here is my current Project model
class Project extends \Eloquent {
protected $fillable = [];
public function user() {
return $this->belongsTo('User');
}
}
And this my User model
class Project extends \Eloquent {
protected $fillable = [];
public function projects() {
return $this->hasMany('Project');
}
}
In this case, User and Project have Many-to-Many relationship because one user has many projects and one project belongs to many user. Therefore, you should create a third table (project_user) which connect User table and Project table in the database.
And you set Many-to-Many relation to User Model and Project Model.
class User extends Eloquent {
public function projects()
{
return $this->belongsToMany('Project');
}
}
In Project model
class Project extends Eloquent {
public function users()
{
return $this->belongsToMany('User');
}
}
Then you can do something like this
//users in the same project
$users = Project::find($id)->users;
Okay, so here it is how I solved it. I used pivot table as you suggested but I even added hasMany relationship like this way. I am still not sure what I am doing is perfectly correct but it worked. :)
class Project extends \Eloquent {
protected $fillable = [];
public function users() {
return $this->belongsToMany('User');
}
public function user() {
return $this->belongsTo('User');
}
}
And here is the key ingredient in User model
class User extends \Eloquent {
protected $fillable = [];
public function projects_owned() {
return $this->hasMany('Project', 'user_id');
}
public function projects() {
return $this->belongsToMany('Project');
}
}

Resources