How to create call column from grand grand child :( laravel backpack - relationship

I have 4 table Projects -> Systems -> Requirements -> Subfunctions
All is 1-n
Can i call add Subfunction column into Project :( Tks u guys .
Here is my Project Model :
public function systems(){
return $this->hasMany(System::class,'project_id','id');
}
public function requirements(){
return $this->hasManyThrough(Requirement::class,System::class,null,'id');
}

Related

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.

Grails Relation m:n:n

We work with an existing mysql database under grails which contains a m:n relation. No problem here. But now we are in the situation that i have to add a second n relation entry, which links to the same table and has to be associated to the first n entry.
If it were for the database, I would simply create a table which looks like:
field m_id -> links to m table
field n_id1 -> links to n table
field n_id2 -> links to n table
But how can this be represented in a grails domain class?
Possibly the answer can already be found somewhere, but the searches I did were not successful, maybe due to lack of search term creativity.
EDIT:
Trying to clarify the question: we have a many-to-many relation, but with two items on one side, which have to maintain association to each other (and it also must be clear which is for example the original and which is the replacement item), so they can not be seperated into two separate entries into the relation.
Hmm... try to think of racing car drivers nominating for a series of races, and every nomination has to contain the driver and his substitute. Races would be m (left hand), driver would be n1 and substitute would be n2. (It was really hard work to find an example...)
EDIT:
By coincidence I found this question which addresses the same problem but also left off rather unsolved.
Take a look at the documentation, is pretty clear:
http://grails.github.io/grails-doc/2.5.0/guide/GORM.html#gormAssociation
Anyway I'm not sure I understand what you're trying to do, but let's try.
If it's a one-to-one relation, you could simply do something like this:
class DomainA {
DomainB domainB
DomainC firstDomainC
DomainC secondDomainC
}
class DomainB {
}
class DomainC {
}
That would create the following fields in the "domain_a" table:
"domain_b_id"
"first_domain_c_id"
"second_domain_c_id"
If it's a one-to-many relationship from DomainA to both DomainB and DomainC with two differentiated collections of DomainC in DomainA, you must have two different DomainA properties in DomainC to be able to map it.
The example with Airport and Flight in the documentation:
class Airport {
static hasMany = [outboundFlights: Flight, inboundFlights: Flight]
static mappedBy = [outboundFlights: "departureAirport",
inboundFlights: "destinationAirport"]
}
class Flight {
Airport departureAirport
Airport destinationAirport
}
The flight needs to Airport properties in order to be able to distinguish which one is mapping the right hasMany collection in Airport.
EDIT: for the race-driver example
Grails supports many-to-many relations but one of the ends must be the principal one and the other must additionally have a belongsTo to it. Though this is not the case, since neither race belongs to driver nor driver belongs to race.
I would use relation with a property: "drives" with a property "mainDriver".
That cannot be mapped directly, you need to use a domain for the relation:
class Race {
static hasMany = [ participants: DriverRace ]
def mainDrivers() {
getDrivers( false )
}
def substitutes() {
getDrivers( false )
}
private getDrivers( mainDriver ) {
DriverRace.withCriteria {
eq( "race", this )
eq( "mainDriver", mainDriver )
}.collect { it.driver }
}
}
class Driver {
static hasMany = [ races: DriverRace ]
}
class DriverRace {
static belongsTo = [ race: Race, driver: Driver ]
boolean mainDriver
}
We thought we were able to solve the problem by inserting a second reference to domain/table n in the mapping property of (left hand side) domain m. grails then seems to put a second reference to n on the right hand side of the relation. But that turned out to be a hopeful weekend dream.

Traversing relationships (simple)

Bear with me please, I'm still learning.
I have 4 Models as so:
class Model_Users extends Model_Table {
public $table="users";
function init(){
parent::init();
$this->addField('name')->mandatory('Enter Name');
$this->addField('email')->mandatory('Enter E-Mail');
$this->addField('phone')->mandatory('Enter Phone');
$this->addField('password')->type('password')->mandatory('Enter Password');
$this->addField('is_superadmin')->type('boolean');
$this->addField('is_employee')->type('boolean');
$this->addField('is_manager')->type('boolean');
$this->hasMany('companies');
}
}
class Model_areas extends Model_Table {
public $entity_code='areas';
function init(){
parent::init();
$this->addField('name');
$this->addField('description')->type('text');
//$this->addField('companies_id')->refModel('Model_companies');
$this->hasOne('companies','companies_id','name')->mandatory(true);
$this->hasMany('sites');
}
}
class Model_areas extends Model_Table {
public $entity_code='areas';
function init(){
parent::init();
$this->addField('name');
$this->addField('description')->type('text');
//$this->addField('companies_id')->refModel('Model_companies');
$this->hasOne('companies','companies_id','name')->mandatory(true);
$this->hasMany('sites');
}
}
class Model_sites extends Model_Table {
public $entity_code='sites';
function init(){
parent::init();
$this->addField('name');
$this->addField('description')->type('text');
$this->addField('qrcode');
//$this->addField('Company Name','areas_id')->refModel('Model_companies','name');
$this->hasOne('areas','areas_id','name');
}
}
I have the "sites" model in a simple crud. It is successfully pulling the relevant hasOne record from "areas". I have two questions:
1) How do I change the column names for the joined areas column? It just says "Areas", whereas I want it to be "Area Name"
2) And the more complex one: How can I perform something like a grid->addColumn to the resulting CRUD (or would it have to be a grid?) that would pull the company name linked to the area in areas_id? Its all 1 to many relationships down the line. Company has multiple areas. Areas has multiple sites. I want to add the company name to the CRUD view of Sites.
You can see in the commented lines some of my minor attempts at accomplishing this. Then I realized I'm missing something big. I should be able to keep this model simple and simply traverse the relationships..
Thank you for your help.
Back to these tutorial videos.
Edit: OK the column name I figured out. ->caption('Blah'). Still can't figure out the traversal :(
1) Try:
$this->hasOne('areas','areas_id','name')->caption('Area Name');
2) Slightly simplified your models and here it is. I admit - I didn't test this, but it should work:
<?php
class Model_Company extends Model_Table {
public $table = 'company';
function init(){
parent::init();
$this->addField('name');
$this->addField('description');
$this->hasMany('Area');
}
}
class Model_Area extends Model_Table {
public $table = 'area';
function init(){
parent::init();
$this->addField('name');
$this->addField('description');
$this->hasOne('Company', 'company_id', 'name');
$this->hasMany('Site');
}
}
class Model_Site extends Model_Table {
public $table = 'site';
function init(){
parent::init();
$this->addField('name');
$this->addField('description');
$this->hasOne('Area', 'area_id', 'name');
// join area and company tables
$j_area = $this->leftJoin('area', 'area_id');
$j_company = $j_area->leftJoin('company', 'company_id');
// add fields from joined tables to this model
$j_area->addField('area_name', 'name');
$j_company->addField('company_name', 'name');
}
}
Basic idea - use joins. ->leftJoin will not create joined records, but ->join will create them. Just for reporting (grid, crud etc.) you're fine with leftJoin.
P.S.
Define some kind of coding rules for yourself. For example, when you use uppercase, lowercase, camel-case etc for class names, filenames. Otherwise you'll sooner or later run into problems when moving on *NIX systems.
Good example is to name all classnames with first letter in upper case. Don't forget that your respective file names should exactly match your classname - also letter case.
Page classnames I like to name all in lowercase, because their name is used in URLs and then it looks better lowercased. But that's just me :)
One more. If you're working on new project or are just learning ATK, then stick to newest development version (available on github). There are quite many things which have changed since recording of tutorials. For example $entity_code is deprecated - use $table instead. refModel is obsolete too I guess etc.
If you want to be successful with ATK, then you have to look regularly into ATK source code to understand it better. Also there are some useful comments :)
Good luck!

Database One-to-Many with two foreign key fields in Laravel

I have been trying to define some Database schema to use the laravel framework. I want to model a Football match. The first step I wanted to do is to define the Entity Relationship diagram, but I found this (which I thought would be quite trivial) to be confusing in some aspects.
First, the obvious approach is to say that a Match is related with two Teams, and a Team is related to any number of Matches. So, we would have a "Many to Many" relationship.
But the implementation of a many to many relation is to have two tables and an intermediate table to relate both entities. I think this would be too much, when I know that a Match will always have two Teams and simply having two columns (local_id and visitant_id) with foreign keys to the Teams table would be enough. Plus, I want to be able to do:
Match::find(1)->local() or Match::find(1)->visitant();
So, thinking on this I am implementing a "One to Many" relation, but with this I have another issue. To retrieve all the matches a Team has played I would like to do:
Team::find(1)->matches();
But I cannot do this because I can only specify one key column when defining the matches() method in eloquent (by default it would be team_id, but it should be visitant_id and local_id).
After some more digging into the source code I found there is a way to actually keep my database schema as it is and achieve what I want (at least in Laravel 4). I posted my problem in github and Taylor Otwell (creator of the framework) gave me the correct answer: https://github.com/laravel/framework/issues/1272
Quoting him, it should be as easy as this:
class Team extends Eloquent {
public function allMatches()
{
return $this->hasMany('Match', 'visitant_id')->orWhere('local_id', $this->id);
}
}
And then...
$team = Team::find(2);
$matches = $team->allMatches;
This is one of those famous database design problems. Friendship relationships, for instance, suffer from that same difficulty. Since you are using Eloquent, I would suggest you to stick with many to many approach and have an extra boolean column local on your intermediate table
class Match extends Eloquent {
public $includes = array('team'); // Always eager load teams
public function teams() {
return $this->has_many_and_belongs_to('team')->with('local');
}
public function get_local() {
foreach ($this->teams as $team) {
if ($team->pivot->local) return $team;
}
}
public function get_visitant() {
foreach ($this->teams as $team) {
if (!$team->pivot->local) return $team;
}
}
}
class Team extends Eloquent {
public function matches() {
return $this->has_many_and_belongs_to('match')->with('local');
}
// I'm doing separate queries here because a team may have
// hundreds of matches and it's not worth looping through
// all of them to retrieve the local ones
public function matches_as_local() {
return $this->has_many_and_belongs_to('match')->with('local')
->where('pivot_local', '=', 1);
}
public function matches_as_visitant() {
return $this->has_many_and_belongs_to('match')->with('local')
->where('pivot_local', '=', 0);
}
}
Obs:
The method has_many_and_belongs_to(...)->with('field') has nothing to do with eager loading. It tells Eloquent to load the intermediate table column field and put that in the pivot.
Usage:
$match = Match::find(1);
$match->local; // returns local team
$match->visitant; // returns visitant team
$team = Team::find(1);
$team->matches; // returns all matches
$team->matches_as_local; // ...
$team->matches_as_visitant; // ...
foreach ($team->matches as $match) {
if ($match->pivot->local) {
// put nice local icon here
} else {
// put nice visitant icon here
}
}

Two tables one view ASP MVC

I need some help. What I am trying to do is show the locations of a device belonging to a specific project.
On the projects page I have a button which goes to the google map. For projects I have a Projects model and controller.
I've got 2 tables, a table containing the location of a device and a project table. I want to display all device locations belonging to a project on a google map. The google maps part is working and I managed to show all device locations on 1 map, only problem is I can't seem to link the devices to the project. I need some help on how to achieve this.
In the Location table ive got a foreign key to the projects table. this is a many-to-onerelation. A project can have multiple devices, but a device can only be linked to 1 project. I have defined the relation as follows in the location model:
[BelongsTo("ProjectID")]
public Project project
{
get { return _project; }
set { _project = value; }
}
In the Location controller I use the following code(theres more but for the moment its not relevant):
public ActionResult Index()
{
return View(DeviceLocation.FindAll());
}
This simply lists all locations in the location table. What I need is to list all locations where the ProjectID = the ID of the projects table. I'm coming from PHP/MYSQL and there you would simply join the 2 tables. How do I achieve this with asp mvc?
You should read up on LINQ and how to use it to query your data.
Something like this should help:
public ActionResult Index()
{
return View(DeviceLocation.Where(d=> d.ProjectId == myProjectId));
}

Resources