addCondition() statement. This is a fragment of m" /> addCondition() statement. This is a fragment of m" /> addCondition() statement. This is a fragment of m"/>

Adding addCondition() in a Form with fields from other tables

153 views Asked by At

I don't know the syntax to access "CurrentTable.ForeignKey" nor "OtherTable.PrimaryKey" in a $model->addCondition() statement.

This is a fragment of my code which works: $mm = new SYSPC_MODEL($this->app->db,['title_field'=>'MODEL_NAME']); $mm->addCondition('MODEL_NAME', 'LIKE', 'DESK%');

In place of simply searching for MODEL_NAME like 'DESK%', I would like to display only the FK_MODEL_id values which exist in the SYSPC_MODEL table for the same FK_OS_ID than the current record FK_OS_ID value. So in SQL, we should have something like: SELECT SYSPC_MODEL.MODEL_NAME WHERE ( DHCP_PC.FK_OS_ID = SYSPC_MODEL.id )

To understand easier the context, I reduced my code as much as possible:

<?php
include_once ('../include/config.php');
require '../vendor/autoload.php';

class SYSPC_OS  extends \atk4\data\Model {
    public $table = 'SYSPC_OS';
    function init() {
        parent::init();
        $this->addFields([ ['OS_NAME',         'required'=>true, 'caption'=>'Identifiant d\'OS'],
                            ['OS_DESCRIPTION', 'required'=>true, 'caption'=>'Description d\'OS']
                        ]);
    }
}     // End of class SYSPC_OS

class SYSPC_MODEL  extends \atk4\data\Model {
    public $table = 'SYSPC_MODEL';
    function init() {
        parent::init();
        $this->addFields([ ['MODEL_NAME',     'caption'=>'Nom du modele'],
                            ['MODEL_BASE_RPM', 'caption'=>'Rpm de base']
                        ]);
        $this->hasOne('FK_OS_id',[new SYSPC_OS(),'ui'=>['visible'=>false]])->addField('OS_NAME','OS_NAME');
    }
}     // End of class SYSPC_MODEL

class DHCP_PC  extends \atk4\data\Model {
    public $table = 'DHCP_PC';
    function init() {
        parent::init();
        $this->addFields([  ['PCNAME',      'required'=>true, 'caption'=>'Nom du pc']
                        ]);
        $this->hasOne('FK_OS_ID',['required'=>true,new SYSPC_OS(),'ui'=>['visible'=>false]])->addField('OS_NAME','OS_NAME');
        $this->setOrder('PCNAME','asc');
        $this->hasOne('FK_MODEL_id',['required'=>true,new SYSPC_MODEL(),'ui'=>['visible'=>false]])->addField('MODEL_NAME','MODEL_NAME');
    }
}      // End of class DHCP_PC

class PcForm extends \atk4\ui\Form {
    function setModel($m, $fields = null) {
        $PcWidth = 'three';
        parent::setModel($m, false);
        $gr = $this->addGroup('PC name');
        $gr->addField('PCNAME',['required'=>true,'caption'=>'Nom du pc']);
        $gr = $this->addGroup('OS');
        $mm2 = new SYSPC_OS($this->app->db,['title_field'=>'OS_NAME']);
        $gr->addField('FK_OS_ID',['width'=>$PcWidth],['DropDown'])->setModel($mm2);

        $gr = $this->addGroup('Modèle');
        $mm = new SYSPC_MODEL($this->app->db,['title_field'=>'MODEL_NAME']);
        $mm->addCondition('MODEL_NAME', 'LIKE', 'DESK%');  // Works fine but I would like to display only the FK_MODEL_id values 
                                                            // which exist in the SYSPC_MODEL table for the same FK_OS_ID 
                                                            // than the current record FK_OS_ID value :
                                                            // SELECT SYSPC_MODEL.MODEL_NAME WHERE ( DHCP_PC.FK_OS_ID = SYSPC_MODEL.id )
        $gr->addField('FK_MODEL_id', ['width'=>$PcWidth], ['DropDown'])->setModel($mm);
        return $this->model;
    }
}     // End of class PcForm

$app = new \atk4\ui\App();
$app->title = 'Gestion des PC';
$app->initLayout($app->stickyGET('layout') ?: 'Admin');
$app->db = new \atk4\data\Persistence_SQL(
    "pgsql:host=".$GLOBALS['dbhost'].";dbname=".$GLOBALS['dbname'],
    $GLOBALS['dbuser'],
    $GLOBALS['dbpass']
);
$g = $app->add(['CRUD', 'formDefault'=>new PcForm()]);
$g->setIpp([10, 25, 50, 100]);
$g->setModel(new DHCP_PC($app->db),['PCNAME', 'OS_NAME', 'MODEL_NAME']);
?>
3

There are 3 answers

0
romaninsh On

Please look at https://github.com/atk4/ui/pull/551 - it might be what you're looking for.

Example here: https://ui.agiletoolkit.org/demos/autocomplete.php

Docs: https://agile-ui.readthedocs.io/en/latest/autocomplete.html?highlight=lookup#lookup-field

$form = $app->add(new \atk4\ui\Form(['segment']));
$form->add(['Label', 'Add city', 'top attached'], 'AboveFields');

$l = $form->addField('city',['Lookup']);

// will restraint possible city value in droddown base on country and/or language.
$l->addFilter('country', 'Country');
$l->addFilter('language', 'Lang');

//make sure country and language belong to your model.
$l->setModel(new City($db));
0
romaninsh On

Alternatively you can use something other than drop-down, here is UI example:

https://ui.agiletoolkit.org/demos/multitable.php

Selecting value in the first column narrows down options in the next. You can have a hidden field inside your form where you can put the final value.

1
Anciaux Frank On


Thanks for your support but I still have some questions.
Question 1: I found "addRelatedEntity" and "relEntity" but I didn't found a description of those commands. Does it exist ? Is this a possible solution for my issue ?
Question 2: Is it possible to 'Lookup' in another table and if yes, how ?
Question 3: If 'Lookup' is not the solution, how to make a join (with filtering in the where clause) inside a model ?
Question 4: If the join is not the solution, is it possible to use DSQL inside a model ?
Question 5: Or do you have a DSQL example (with a self made join between several tables) associated with a CRUD ?