Laravel 8 relationship with two columns in each table - laravel-8

I have a multiple DB connection in Laravel 8 projects, I can't modify one of them which is mainly used in ROR project.
I need to fetch data from two tables only if id1, id2 columns have same value in both the tables. I went on google but did not find anything.
I tried some examples, either it is giving me N+1 query issue or second table o/p always null
function example()
{
return $this->belongsTo(Model::class, 'id1', 'id1')->where('id2', $this->id2);
}
function example()
{
return $this->belongsTo(Model::class, 'id1,id2', 'id1,id2');
}

I came up with a solution from https://laravel.io/forum/06-26-2014-one-to-one-relationship-with-two-fieldscolumns-connection-how
I used join with Laravel relation query:
HouseHold::where("printedcardno","=","17130103-0124")->with(array('members' => function($query)
{
$query->leftJoin('PatientCard', function($join)
{
$join->on('PatientCard.HouseHoldID', '=', 'shp_members.HouseHoldID')
->on('PatientCard.MemberID', '=', 'shp_members.MemberID');
});
}))->get()->take(10)->toArray();
I think this should be good approach as it fixed N+1 query issue and getting desired o/p.

Related

Relationship il Laravel 8 using three tables

Can some home help me to make this request using laravel Relationship?
SELECT * FROM `recoltes`, `plantations`, `users` WHERE recoltes.plantation_id = plantations.id AND plantations.user_id = users.id;
Yes i found a way
public function recoltes ()
{
return $this->hasManyThrough(Recolte::class, Plantation::class);
}
Note that when i start with ```Plantation::class``` it does not work.
For that to work, You should specify how fields are related between tables

Laravel query where field is less than sum of another field in related table (polymorphic relationship)

In Laravel trying to query a table for invoices (table name: invoices) where the invoice total (field name: net_total) is greater than the sum of payments made for that invoice. It is set as a polymorphic relationship.
Invoice Table:
public function transactions(){
return $this->morphMany(TransactionAllocation::class, 'doc');
}
Payment Table:
public function doc()
{
return $this->morphTo();
}
I tried the query which does not seem to work.
Invoice::with('transactions')
->where('net_total', '>' ,'transactions.amount')
->get();
I tried the following as per an answer below which gives me sum of relationship but the where condition fails
Invoice::withSum('transactions', 'amount')
->where('net_total','>','transactions_sum_amount')
->get();
Screenshot of result - https://prnt.sc/1favj7u
The second array shouldn't have comes as it fails where condition.
Any advice on what am I missing?
Since you will have many transactions as you said, that is the part missing in the query.
You can try something with withSum for example
InvoiceTest::withSum('transactions', 'amount')
->havingRaw('transactions_sum_amount < invoices.net_total')
->get();

Laravel query builder for Charts.js

I have logic querying a MSSQL Server database view and I've been searching for a solutions along with trying different techniques. Of course I don't expect a full solution where this is two parts (query builder & frontend javascript/chart) but any helpful direction would greatly appreciated. Here I'm getting the count of Leads on a particular day grouped by the date created and source of the leads. I'm trying build this the Laravel way so to speak, and display in charts.js. I'm thinking I might need to make two different database calls/queries. One count and one for the group by source text.
Thank you for your help for a solutions or an helpful direction I can take.
I have already done total leads for another chart but this project has some extra sugar to it.
SELECT count([LeadID]) as numleads,[LeadSource],cast(leadcreated as date) as
`enter code here`createddate
FROM [myDatabase].[dbo].[viewAllLeads]
where companyid=001
group by cast(leadcreated as date),[LeadSource]
order by createddate
Chart.js set up:
- Top links (horizontal) the groupby info by LeadSource
- Left, y-axis - the count of the leads
- Bottom x-axis - the date lead was created
It should actually be straight forward, but you need to be aware that using DB::raw() is necessary. To begin with, here your query a little bit nicer formatted:
SELECT
[LeadSource],
CAST([leadcreated] as date) as createddate,
COUNT([LeadID]) as numleads
FROM [dbo].[viewAllLeads]
WHERE [companyid] = '001'
GROUP BY [LeadSource], CAST([leadcreated] as date)
ORDER BY [createddate]
And converted to an Eloquent query:
DB::table('viewAllLeads') // the query builder doesn't care if it's a table or view
->select([
'LeadSource',
DB::raw('CAST(leadcreated as date) as createddate'),
DB::raw('COUNT(LeadID) as numleads')
])
->where('companyid', '001')
->groupBy('LeadSource', DB::raw('CAST(leadcreated as date)'))
->orderBy('createddate')
->get();
This will return a Illuminate\Support\Collection containing stdClass objects of the following form:
object(stdClass)#1 (3) {
["LeadSource"] => string(3) "ABC"
["createddate"] => string(10) "2019-08-05"
["numleads"] => int(15)
}
$leads = Lead::where('companyid', $companyid)->get()->groupBy(function ($item) {
return $item->created_at->format('Y-m-d');
})->sortBy(function ($item) {
return $item->created_at->format('x');
});
if you use dd($leads) you can see the data structure.

How to change Doctrine "findBy/findOneBy" functions's behaviors to reduce the number of queries?

I'm working on a Symfony2 using Doctrine.
I would like to know how to change the behavior of "findBy" functions when retrieving my entities.
For example, if you call "findAll()", it returns all products.
$entities = $em->getRepository('ShopBundle:Product')->findAll();
However, how to reduce the number of queries, because, by default, it will create a new query each time I want to get a member linked to a join column. So if I get 100 entities, it will process 101 queries (1 to get all entities and 1 by entity to get join column).
So today, I use createQuery() function by specifying the joins. Is there a way to configure something about findBy functions to skip createQuery method ?
Thanks in advance !
K4
You can fetch out this in below way
public function findUser() {
$query = $this->getEntityManager()
->createQuery('SELECT us.id as id, us.name as user_name FROM Bundle:User us');
try {
return $query->getResult();
} catch (\Doctrine\ORM\NoResultException $e) {
return null;
}
}

Joining multiple tables together with eloquent and eager loading in laravel [implementing filter]

What I have already and what I'm trying to do:
I have a website that lets users make posts advertising themselves to other users. Now, I'm trying to implement a filter for these posts but filter by values in the users table, posts table and three others. This is where I'm running into some trouble.
Code that works, as is, no filter:
$posts = Post::with('user','lookingfors','playstyles', 'postcomments')->orderBy('id', 'DESC')->paginate(10);
return View::make('posts/index', compact('posts'));
This is what I've tried:
$posts = User::leftjoin('posts', function($join)use($region){
$join->on('users.id', '=', 'posts.user_id');
$join->on('playstyle_post.post_id', '=', 'posts.id'); // join pivot, then join pivot to playstyles
$join->on('playstyle_post.playstyle_id', '=', 'playstyles.id');
//$join->on;
})->where('users.region_id', 'like', $region)->get();
This one keeps bringing up this error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column
'playstyle_post.post_id' in 'on clause' (SQL: select * from users
left join posts on users.id = posts.user_id and
playstyle_post.post_id = posts.id and
playstyle_post.playstyle_id = playstyles.id where
users.region_id like ?) (Bindings: array ( 0 => 6, ))
Also:
$posts = Post::with('lookingfors', 'playstyles', 'postcomments')
->leftjoin('users', 'posts.user_id', '=', 'users.id')
//->join('playstyle_post', 'posts.id', '=', 'playstyle_post.post_id')
->paginate(10);
This one is odd ( well for me ), when 'leftjoin' is commented out obviously it works just as before, but when I have it as it is now it displays the view as it should and even pulls all the right values from the users table but does not display any of the information thats being requested through the 'with'.
I've tried a couple other things in the last two weeks, but I've already thrown them out when they didn't work. This has been kicking my ass for the better half of a month and I can't wrap my head around why I can't get it to work.
So really, my trouble right now is just trying to join the tables and returning it to the view in an eloquent fashion so I can keep treating it the same. The filter itself will be a problem of its own, but getting the joins to work has proved to be the hard part.
Instead of passing a bunch of relationship names to the with() function, try passing an array, setting keys as the names of the relationships and the values as callback functions and pass in the query for actual editing. Also will have to use use ($region) where needed. Hopefully you get the idea.
I put in some examples for adding filters on each relationship. Because you are working locally with each one, you shouldn't have to worry about prefixing them with table names or aliases.
$posts = Post::with(array(
'user' => function($query) use ($region)
{
// User constraints here
$query->where('status', 'A');
$query->where('deleted', '0');
},
'lookingfors' => function($query)
{
// lookingfors constraints here
$query->where('name', 'somelookingforname');
},
'playstyles' => function($query)
{
// playstles constraints here
$query->where('name', 'someplaystylesname');
},
'postcomments' => function($query)
{
// Some postcomments constraints here
$query->where('name', 'somepostcommentsname');
}))
->orderBy('id', 'DESC')
->paginate(10);
Looking at your attempt at left joins though, I don't know if these relationships are correct. My example assumes all the relationships can relate directly back to the user table. Otherwise, you will need to change the keys on the array to match how the relationships should be.
For example, if trying to relate to the playstyles table, but the relationship between playstyles and posts doesn't exist because you need to go through the users table first, you would just change 'playstyles' to 'users.playstyles'.
If you post your migrations, I could help you further.