How to Use Recursive Relation in Laravel? - database

I'm using one User table to store the information of three different users. I created the parent first with one parent_id, and now I want to create the student, and I want to give reference of parent id.
My Table has an id, parent_id, name, job, etc. When the parent gets registered, it will set a new id, parent_id, name, job. When the student gets registered, it will set the new id, name, and parent_id stored earlier.
I'm new to Laravel 5.7 and I m having issues with syntaxes to store parent record with student record.

If I understand you correctly, you want to make a user parent of other users. For example a student will have a parent which is also a user. If that is the case you will need your user model to be implemented like below:
class User extends Model
{
public function parent(){
return $this->belongsTo('App\User','parent_id');
}
public function children(){
return $this->hasMany('App\User','parent_id');
}
}
This way you can access children and parent of your users.

I agree with Ali Mrj Use Ali Mrj style to make relation..
class User extends Model
{
public function parent(){
return $this->belongsTo('App\User','parent_id');
}
public function children(){
return $this->hasMany('App\User','parent_id');
}
}
then you use umefarooq style to insert data.
create parent record get its id as parent_id for sudent, then create student record
how can you get the last id? it depends on your style.
i thinking about 2 solution right now..
get all of id_parent then use it in
get the last id parent from database.
how to get last id_parent?
$last_user = User::where('job','teacher')->orderBy('id','desc')->get()

Related

Laravel multiple user id tables

I'm pretty new to laravel and have a really basic question related to relationships.
Here is an example of my question:
I have a migration called money_transfers.
The migration contains the following things:
user_id (transfer sent by)
sentTo_id (transfer sent to)
amount
sent_at
BOTH user_id and sentTo_id refer to a User ID.
Now, what I want to do is the following:
Fetch the user the money was sent TO the same way as the user the money was sent BY. Just like in the example below:
$transfer->sentTo->name
or
$transfer->sentTo->id
You get what I mean. Thanks in advance :)
If you defined your foreign keys correctly in your migration table, Then it's just a matter of defining the right relationship:
class MoneyTransfer extends Model
{
public function sentBy()
{
return $this->belongsTo(User::class,'user_id');
}
public function sentTo()
{
return $this->belongsTo(User::class,'sentTo_id');
}
}
This way you can access the receiver attribute like this:
$transfer->sentTo->name;
And the sender attribute like this:
$transfer->sentBy->name;

How do I get info from lookup in salesforce query

I have a custom salesforce object Installation__c and it has a custom field Product__c which is a lookup to a custom object Product__c I am trying to get the fields from the child object using these query:
public with sharing class InstallationController {
#AuraEnabled
public static List<Installation__c> getItems() {
// Perform isAccessible() checking first, then
return [SELECT Id, Name, Installation_Display_Name__c, Product__c, Status__c, (SELECT Product__c.Name FROM Product__c) FROM Installation__c];
}
}
I get the error:
Didn't understand relationship 'Product__c' in FROM part of query call. If you are attempting to use a custom relationship, be sure to append the '__r' after the custom relationship name. Please reference your WSDL or the describe call for the appropriate names.
I have tried changing the Query to
FROM Product__rand FROM Product__c__r but neither seems to work, how do I fix my query?
If you're traversing up or down a relationship hierarchy, the __c suffix becomes __r (r for 'relationship') until you finally get to the field that you're looking for (which still ends in __c if it's a custom field). So in your case, it will be
public with sharing class InstallationController {
#AuraEnabled
public static List<Installation__c> getItems() {
// Perform isAccessible() checking first, then
return [SELECT Id, Name, Installation_Display_Name__c, Product__r.Name, Status__c FROM Installation__c];
}
}
So, the change here is, for the relationship you have to use Product__r.Name
Click into the relationship on the object that has the look up. Copy the relationship name adding __r to it
This example would be Test_Drives__r

Salesforce Lookup field showing ID value instead of record name

Hi I have a custom object which has a custom field of type lookup to Account. The child custom record gets created when Account record is created. I am creating child record in after insert trigger on Account and keeping the name of child record same as of the name of Account.
But In the name I am getting 15 digit Id instead of real name of account. What can be the issue?
Code## for Trigger
if(Trigger.isAfter && (Trigger.isInsert)){
AccountTriggerHelper.createReferrer(Trigger.new);
}
In Apex Class:
public static void createReferrer(List<Account> accountList){
List<Referral__c> newReferral = new List<Referral__c>();
for(Account acc : accountList) {
if(acc.Talos_RecordType__c=='Referrer'){
system.debug('==acc=1='+acc);
Referral__c ref = new Referral__c();
System.debug('-----acc.Name----'+acc.Name);
ref.Name = acc.Name;
ref.Account__c = acc.Id;
ref.Email__c = acc.PersonEmail;
ref.Talos_IQOS_Expert_ID__c = acc.Talos_IQOS_Expert_ID__c;
ref.Talos_Referrer_Type__c = acc.Referrer_Type__c;
ref.User_Id__c = acc.UserID__c;
ref.Email_Validation__c = true;
ref.Store_Code__c = acc.Store_Code__c;
newReferral.add(ref);
system.debug('==referral=1='+newReferral);
}
}
Thanks,
Marc
This code can't lead to population of Id in the Name field. There might be another trigger on Account or child Object, or any workflow, process builder on your org creating that change again. Can you check the created date and modified date of the child record.
If they are different, then most probably I am right.

Writing a Custom Controller extension to get related records and iterate over list/index and use with apex:repeat

I have 3 custom objects with a Master-Detail Relationship and Lookup Relationship.
CustomA__c (related CustomB__c) <-> CustomB__c <-> CustomC_c (related CustomB_cc)
I´ve built a Visualforce page with HTML table to replicate a PDF document and a Custom Controller Extension, so far so good.
But I´m just a beginner with apex coding.
The problem is that I need to replicate the document as it is, when there are no related records for CustomA__c or less then 5, it should still show the full table (the empty rows). Max. rows/related records on the document is 5, no second page needed.
Currently I´m trying to accomplisch that by using apex:variable and apex:repeat as I´ve seen some examples, but perhaps there is also another solution. For the Visualforce page I already wrote the code for the rows with data and another apeax:repeat for the empty rows.
But I´m really strugling with the controller, i know i need to iterate over the list, the code that i already wrote is also put together out of examples as i just don´t understand it yet good enough.
Any help would be appreciated! Thanks, Josip
public with sharing class CustomAController {
public CustomA__c customa{get; set;}
public CustomA__c ca{get; set;}
public CustomAController (ApexPages.StandardController controller) {
ca = (CustomA__c )controller.getRecord();
customa= [SELECT Id, Name FROM CustomA__c WHERE Id = :ApexPages.currentPage().getParameters().get('Id')];
}
public List<CustomB__c > getrelatedCustomB() {
List <CustomB__c > cbList = New List<CustomB__c >(5);
for(CustomA__c acc:[SELECT Id, Name, (SELECT Id, Name, ... , CustomCfield__r.Name FROM CustomBs__r ORDER BY Name LIMIT 5) FROM CustomA__c WHERE Id = :customa.Id]){
for(CustomB__c cb:acc.CustomBs__r)
cbList.add(cb);
}
return cbList;
}
}
You can dramatically simplify your code by writing a direct query on the child object instead of a parent-child SOQL query.
public List<CustomB__c > getrelatedCustomB() {
return [SELECT Id, Name, ... , CustomCfield__r.Name
FROM CustomB__c
WHERE CustomA__c = :customA.Id
ORDER BY Name
LIMIT 5];
}
There's no need to iterate in Apex here.

Apex Trigger Context Variable

Here my code for apex trigger.
trigger LeadTrigger on Lead (after insert)
{
if(Trigger.isInsert){
for(Lead newLead: Trigger.new)
{
//newLead.RecrodTypeId //'Give value of record type id.
//newLead.RecordType.Name //'Null'
}
}
}
Why "newLead.RecordType.Name" returns null?
The lists of objects available in triggers only have values for the fields on the object the trigger is running on. No relationships are traversed, only the IDs of the lookup records are included.
Therefore, to pull in any extra information you need to from related objects needs to be queried for.
You'll want to do something like this:
trigger LeadTrigger on Lead (after insert) {
map<id, RecordType> mapRecordTypes = new map<id, RecordType>();
if(Trigger.isInsert) {
for(Lead newLead: Trigger.new) {
mapRecordTypes.put(newLead.RecordTypeId, null);
}
}
for(RecordType rt : [select Id, Name from RecordType
where Id in : mapRecordTypes.ketSet()]) {
mapRecordTypes.put(rt.Id, rt);
}
for(Lead newLead : Trigger.new) {
string recordTypeName = mapRecordTypes.get(sLead.RecordTypeId).Name;
}
}
This is probably because some of your leads that just got inserted don't have record types associated with them. This is normal. You can enforce that record type selection is mandatory through configuration, if that's what you're looking for.
[EDIT]
Now I think I understand the issue (from your comment). The reason is that since you're in a trigger, the associated RecordType referenced object is not available. The RecordTypeId will always be available since it is literally part of the trigger object as an Id. However, child objects (referenced objects) will not be available to simply reference from within a trigger. To do this you need to create a map of the referenced object in question by doing an additional SOQL call WHERE Id IN: theIdList.
From Apex, not in a trigger, you need to specifically call this field out from your SOQL like this:
List<Lead> leads = [SELECT Id, RecordType.Name FROM Lead];
What just happened there is that the child object, the RecordType in this case, was included in the query and therefore available to you. By default a trigger will not have all of your child objects pre-selected and therefore need to be selected afterwards from within the trigger or class called by the trigger:
List<Id> recIds = new List<Id>();
for(Lead l : leads)
{
recIds.add(l.RecordTypeId);
}
List<RecordType> rt = [SELECT Id, Name FROM RecordType WHERE Id IN :recIds];
Map <Id, String> idRecNameMap = new Map<Id, String>();
for(RecordType r : rt)
{
idRecNameMap.put(r.Id, r.Name);
}
// And finally...
for(Lead l : Trigger.new)
{
String tmpRecordTypeName = idRecNameMap.get(l.RecordTypeId);
}
I did not test this code but I think it look ok. Hope this makes sense.
you can't get extra information on the related objects from this trigger. if you want to get more information you need to make query for other objects.
List<RecordType> records = [SELECT Id, Name FROM RecordType WHERE Id = newLead.RecrodTypeId];
string myname = records[0].name;
but remember that you shouldn't make a query in for loop. so if you wanted to do it in the right way go for Adam's solution.
Put some system debug inside the loop and check your system debug logs for more information
system.debug('lead:' + newLead);
inside the for loop and see what is being passed in. You may find that it is null.
We cant really give you a good answer without knowint the rest of your set up.

Resources