postEdit Mjoin

postEdit Mjoin

jacob.steinbergerjacob.steinberger Posts: 86Questions: 18Answers: 1
edited April 2023 in Editor

I'm seeing some odd behavior on the events in Editor, and wanted to fish for confirmation on either my sanity or order of operation.

When performing a postEdit function, it seems to be postEdit based on the initial table, and not any Mjoined tables. For example, I have:

        ->join(
          Mjoin::inst( 'lob' )
            ->link( 'intake.id', 'intake_lob.intake_id' )
            ->link( 'lob.id', 'intake_lob.lob_id')
            ->order( 'id asc' )
            ->fields(
              Field::inst( 'id' )
                ->validator( Validate::required() )
                ->options( Options::inst()
                  ->table( 'lob' )
                  ->value( 'id' )
                  ->label( 'name' )
                ),
              Field::inst( 'name' )
            )
        )

Which works, but in a postEdit function call, it occurs before the Mjoin appears to be processed and that related table is updated/changed/inserted.

Are there any events that are called that are truly postEdit, and not (effectively) half-way through an edit? Does the field used in postEdit matter - should I be performing multiple postEdit functions per Mjoin field?

This question has an accepted answers - jump to answer

Answers

  • allanallan Posts: 61,635Questions: 1Answers: 10,092 Site admin
    edited April 2023

    Hi,

    The postEdit will happen after the Mjoin code has been executed, as you can see in the code here (the mJoin happens at line 1308).

    Can you show me your postEdit code perhaps?

    There is one important point - if you are reading information from the database in your postEdit event handler, you must use the same database transaction as Editor. A quick way to test if that is the problem you are running into would be to add ->transaction(false) and see if it then behaves like you expect.

    If that is the issue, you could get a database handler for the transaction using the Editor->transaction() method.

    Thanks,
    Allan

  • jacob.steinbergerjacob.steinberger Posts: 86Questions: 18Answers: 1
            ->on( 'postEdit', function ( $editor, $id, $values ) {
              $editor
                    ->field( 'intake.edited_date' )
                    ->setValue( date("Y-m-d h:i:s") );
              } )
    

    My use-case is I need to perform calculations on data that will change, based on submitted data. If I edit any of the "primary" columns directly, without Mjoin fields, there are no issues. If I alter an "Mjoin" field, the calculations appear to occur post-primary, pre-Mjoin - the data is quite literally backwards. For example, I'm performing a simple fielda+fieldb, if fieldb is changed from 0->5, the calculations show as if the field is 0. If I change it from 5->0, the calculations show as if the field is 5.

    Database trigger (insert and update):

    create trigger score_intake
    AFTER INSERT ON intake FOR EACH ROW
    BEGIN
        
        DECLARE q1 int;
        DECLARE q2 int;
        SELECT COALESCE(sum(lob.value),0) INTO q1 FROM intake_lob left join lob ON intake_lob.lob_id = lob.id where intake_id = new.id;
        SELECT COALESCE(sum(related_reason.value),0) INTO q2 FROM intake_related_reason left join related_reason ON intake_related_reason.related_reason_id = related_reason.id where intake_id = new.id;
    
       SET t_total_score = q1 + q2;
    
      INSERT INTO total_score (intake_id, score) VALUES ( new.id, t_total_score ) ON DUPLICATE KEY UPDATE score=t_total_score;
    

    The only alternative I can think of is to convert to a procedure, called by an insert/update/delete trigger on every Mjoin table, which seems heavy handed.

  • jacob.steinbergerjacob.steinberger Posts: 86Questions: 18Answers: 1

    Attempted using ->transaction(false), didn't change the results.

    I'm uncertain if where the problem is - it could be in my understanding of events, or something else I havent thought of.

  • jacob.steinbergerjacob.steinberger Posts: 86Questions: 18Answers: 1

    I think it is my understanding of Mjoin and events. I believe even the ID I think it's returning isn't the proper one for the table being edited. I'm going to go back to some debugging to figure out what is being passed around.

  • jacob.steinbergerjacob.steinberger Posts: 86Questions: 18Answers: 1

    Was able to confirm that the ID is the proper ID for the row I'm editing in the main (not joined) table. But now I've realized it might be something entirely different - the update on the postEdit never occurs, intake.edited_date is never updated.

    Might be a more basic issue I'm missing - I'll keep digging.

  • jacob.steinbergerjacob.steinberger Posts: 86Questions: 18Answers: 1

    I think this thread clears up a bit. "Post" events don't update the table, so they're not actually occuring.

    In my case, I need to trigger something to occur after all the joined tables are updated, and not during the initial Editor run :(

  • allanallan Posts: 61,635Questions: 1Answers: 10,092 Site admin

    "Post" events don't update the table, so they're not actually occuring.

    The events fire, but as you say, they will not update the database table. That are post having written to the table.

    Perhaps preEdit is the event handler you want (docs for it here?

    e.g.:

    ->on( 'preEdit', function ( $editor, $id, $values ) {
      $editor
            ->field( 'intake.edited_date' )
            ->setValue( date("Y-m-d h:i:s") );
      } )
    

    Are you allowing multi-row editing?

    Allan

  • jacob.steinbergerjacob.steinberger Posts: 86Questions: 18Answers: 1

    preEdit is definitely not the desire. Calculations have to occur after all tables are updated - after the primary table and all join tables are updated.

    I went the brute force method of adding triggers to every Mjoin table until I have time to really dig into a better solution. Off hand, adding a procedure call inside the core Editor.php, that occurs right before postEdit, would be simple enough, and likely a lot cleaner than an insert/update/delete trigger on every table.

    Additional alternatives would/could be
    1. Updating the php backend to support three fields per key/value
    2. Setting up two datasets using DT, and referencing between them to have the calculations performed within the client-side versus server-side.

    I don't have an absence of possibilities ;)

  • allanallan Posts: 61,635Questions: 1Answers: 10,092 Site admin
    Answer ✓

    I don't really understand what you are trying to do to be honest. The example you gave doesn't need a database operation, it just sets the time stamp and doesn't do any calculations, which is a perfect use for preEdit.

    If you want Editor two write values to the database, then preEdit is the event to use. If you want to read values after Editor has written all of its information to the database, postEdit is the one to use.

    I suspect I'm not getting the full picture, which is why I'm not really able to give a proper answer.

    Allan

Sign In or Register to comment.