Fatal error: Call to a member function insertId() on null

Fatal error: Call to a member function insertId() on null

rf1234rf1234 Posts: 3,028Questions: 88Answers: 422
edited December 2016 in Free community support

Hi Allan,
would you kindly help me with this please. I get this fatal error using Editor to insert a row into a link table. I have a debug code as well, it is "ohufen".

( ! ) Fatal error: Call to a member function insertId() on null in 
E:\xampp\htdocs\lgf\DataTables\php\Editor\Editor.php on line 1596
Call Stack
#   Time    Memory  Function    Location
1   0.0012  154368  {main}( )   ...\actions.php:0
2   0.0752  543584  tblUserCreditor( )  ...\actions.php:106
3   0.0920  922648  DataTables\Editor->process( )   ...\functions.php:730
4   0.0920  922992  DataTables\Editor->_process( )  ...\Editor.php:661
5   0.0932  923944  DataTables\Editor->_insert( )   ...\Editor.php:900
6   0.0932  924232  DataTables\Editor->_insert_or_update( ) ...\Editor.php:1040

UPDATE: Completely changed my approach - I couldn't get Mjoin running for my link table editing - even when I put the focus on the parent table like in this example:
https://editor.datatables.net/examples/advanced/joinArray.html

I still got errors within Datatables and Editor. Is it possible that hese are caused by a bug in the new release? Anyway my issue has been resolved through editing the link table directly as a child table as described in the blog here:
https://datatables.net/blog/2016-03-25

This is my Editor code now. I also appended the link table with an extra column defining the user role for the respective creditor. In that sense it isn't a conventional link table any longer. Consequently I also had to add an id to the link table. Got rid of the Mjoin ...

function tblUserCreditor(&$db, &$lang) {
    if ( ! isset($_POST['user']) || ! is_numeric($_POST['user']) ) {
        echo json_encode( [ "data" => [] ] );
    } else {
        if ($lang === 'de') {     
            $msg[0] = 'Feld darf nicht leer sein.';
        } else {
            $msg[0] = 'Field may not be empty.';
        }
        Editor::inst( $db, 'creditor_has_user' )
        ->field(
            Field::inst( 'creditor_has_user.user_id' )->set(Field::SET_CREATE),
        // fourth parameter of options could be a where clause https://editor.datatables.net/manual/php/joins, null or limit
        //https://editor.datatables.net/docs/1.5.6/php/class-DataTables.Database.Query.html
            Field::inst( 'creditor_has_user.creditor_id' )->options('creditor', 'id', 'name'),
            Field::inst( 'creditor_has_user.role' )->validator( 'Validate::notEmpty', array('message' => $msg[0]) ),
            Field::inst( 'creditor.name' )
        )
        ->leftJoin( 'user', 'user.id', '=', 'creditor_has_user.user_id' )
        ->leftJoin( 'creditor', 'creditor.id', '=', 'creditor_has_user.creditor_id' )          
        ->where( 'creditor_has_user.user_id', $_POST['user'] )
        ->where( 'user.type', 'C' )        
        ->on('preCreate', function ( $editor, $values ) {
            // no acces to $id inside the function - need to access global array again
            $userUser = filter_var($_POST['user']);
            $editor            
                ->field('creditor_has_user.user_id')
                ->setValue($userUser);
        })
        ->process($_POST)
        ->json();
    }
}

This question has an accepted answers - jump to answer

Answers

  • allanallan Posts: 63,852Questions: 1Answers: 10,519 Site admin
    Answer ✓

    Could you show me the Javascript code you are using as well please? That error suggests that the insert might have failed.

    Thanks,
    Allan

  • rf1234rf1234 Posts: 3,028Questions: 88Answers: 422
    edited December 2016

    Yes, the insert definitely failed. I had also gotten it wrong initially. Later I thought I had it right but it didn't work either. Then I threw it all away and changed the approach - which was required anyway because I added the additional attribute on the link table - which isn't really just a link table any longer.
    The code is gone ... But when I'll do another Mjoin and run into the same issues I will definitely let you know. My impression was however that I had precisely implemented your example mentioned above. But maybe I was wrong?!

  • rf1234rf1234 Posts: 3,028Questions: 88Answers: 422

    Hi Allan,
    it happened again ... I tried to implement the logic of this example: https://editor.datatables.net/examples/advanced/joinLinkTable.html

    I hope I understood now what you are doing there. Upon insert into the users table you take the id of the new users row and the selected id of the dept table and insert them into the user_dept table - in that sequence.There is no way to insert the user_dept table row separately from the insert into the users table based on that example and the mjoin example.

    I have a different requirement: I want to insert the user_dept table row separately through a child table like you described in your blog: https://datatables.net/blog/2016-03-25.

    I tried to do this using your example but I always got the "Fatal error"; the debug option didn't work unfortunately, I could not see the SQL generated from this, but I could see that the id of the users table wasn't sent to the server. I couldn't send it myself by defining it as SET_CREATE either. Obviously the fatal error was caused by a null insert into the users table because I didn't submit any values for the users table.

    I have a workaround now: I edit the link table directly as a child table (as in your blog; not your other definition of child table which seems to be the drop down for fields that don't fit into a table row when using the responsive option - that is a bit confusing for me - I read a lot about child tables here but I obviously had no idea what was really meant :blush: : ...), but it needs a separate id field even though this is normally redundant. I can live with that; I've just put a unique index on the two foreign keys. This way I also have the freedom to add additional attributes to the link table ...

    This took me very, very long to find out ... Maybe you can add a warning to your example - or to your blog entry!

    This is how I resolved it now. My users table is called "rfp" and my user_dept table is called "rfp_has_creditor".

    function tblRfpCredGov(&$db, &$lang) {
        if ( ! isset($_POST['rfp_id']) || ! is_numeric($_POST['rfp_id']) ) {
            echo json_encode( [ "data" => [] ] );
        } else {
            if ($lang === 'de') {     
                $msg[0] = 'Feld darf nicht leer sein.';
            } else {
                $msg[0] = 'Field may not be empty.';
            }
            Editor::inst( $db, 'rfp_has_creditor' )
            ->field(
                Field::inst( 'rfp_has_creditor.rfp_id' )->set(Field::SET_CREATE)
                                                        ->setValue( $_POST['rfp_id'] ),
                Field::inst( 'rfp_has_creditor.creditor_id' )
                    ->options( Options::inst()
                        ->table('creditor')
                        ->value('creditor.id')
                        ->label( array('creditor.name', 'creditor.BIC', 'creditor.city') )
                        ->render( function ( $row ) {
                            if ($row['creditor.BIC'] > '') {
                                return $row['creditor.name'].' (BIC: '.$row['creditor.BIC'].'), '
                                    .$row['creditor.city'];
                            } else {
                                return $row['creditor.name'].', '.$row['creditor.city'];
                            }
                        } )
                        ->order( 'creditor.name asc' )
                        //where clause MUST be a closure function in Options!!!
                        ->where( function($q) {
                            //only creditors that are already clients and
                            //that haven't been selected yet for the RfP will show up
                            $q ->where('creditor.is_client', 1 );
                            $q ->where('creditor.id',
                                '( SELECT DISTINCT rfp_has_creditor.creditor_id  
                                   FROM rfp_has_creditor  
                                  WHERE rfp_has_creditor.rfp_id = :rfp_id
                                )', 'NOT IN', false);        
                            $q ->bind( ':rfp_id', $_POST['rfp_id'] );
                        } )
                    ),
                Field::inst( 'rfp_has_creditor.gov_id' )->set(Field::SET_CREATE)
                                                        ->setValue( $_SESSION['rfp_gov_id'] ),
                Field::inst( 'creditor.name' )->set( false ),
                Field::inst( 'creditor.BIC' )->set( false ),            
                Field::inst( 'creditor.type' )->set( false ),
                Field::inst( 'creditor.city' )->set( false ),
                Field::inst( 'creditor.country' )->set( false )
            )
            ->leftJoin( 'rfp', 'rfp.id', '=', 'rfp_has_creditor.rfp_id')
            ->leftJoin( 'creditor', 'creditor.id', '=', 'rfp_has_creditor.creditor_id')             
            ->where( 'rfp.id', $_POST['rfp_id'] )
            ->process($_POST)
            ->json();
        }
    }
    

    As always your comments are appreciated.
    Roland

This discussion has been closed.