XF 2.0 _postSave() / entity_post_save

S Thomas

Well-known member
Can someone shed some light why the entity _postSave() method nor the event entity_post_save contain the correct entity?
For example, in ConversationMaster, this is the dump for the entity:
PHP:
PHP: object(XF\Entity\ConversationMaster)#259 (15) {
  ["_uniqueEntityId":"XF\Mvc\Entity\Entity":private]=>
  int(5)
  ["rootClass":protected]=>
  string(28) "XF\Entity\ConversationMaster"
  ["_useReplaceInto":protected]=>
  bool(false)
  ["_newValues":protected]=>
  array(15) {
    ["user_id"]=>
    int(1)
    ["username"]=>
    string(4) "admin"
    ["open_invite"]=>
    bool(false)
    ["conversation_open"]=>
    bool(true)
    ["title"]=>
    string(1) "9"
    ["start_date"]=>
    int(1533001394)
    ["last_message_date"]=>
    int(1533001394)
    ["last_message_user_id"]=>
    int(1)
    ["last_message_username"]=>
    string(4) "admin"
    ["conversation_id"]=>
    int(28)
    ["reply_count"]=>
    int(0)
    ["recipient_count"]=>
    int(0) // how?
    ["first_message_id"]=>
    int(0) // why?
    ["last_message_id"]=>
    int(0) // what's this?
    ["recipients"]=>
    array(0) {
    } // yah?
  }
  ["_values":protected]=>
  array(0) {
  }
  ["_relations":protected]=>
  array(0) {
  }
// etc
No relations and many missing params. Same happens to every entity.
Even manually fetching the entity with
PHP:
\XF::app()->em()->findOne("XF:ConversationMaster", ["conversation_id" => $entity->conversation_id]
results in that entity - but it's fully there in the DB. And it's not only this particular entity, this happens with every entity.
Am I misunderstanding something or what is the right approach to use an entity right after it has been created? And why is the freshly picked entity from the database still cheesy?
 
Reading through Mvc\Entity\Entity:

PHP:
public final function save(..)

$this->_postSave();
..
\XF::fire('entity_post_save', [$this], $this->rootClass);
..
$db->commit();

That explains a lot. So post_save is not post_commit. Is there anything like post_commit?
 
Works fine for me. Maybe some kind of caching problem?

HTML:
PHP: object(XF\Entity\ConversationMaster)#345 (15) {
  ["_uniqueEntityId":"XF\Mvc\Entity\Entity":private] => int(5)
  ["rootClass":protected] => string(28) "XF\Entity\ConversationMaster"
  ["_useReplaceInto":protected] => bool(false)
  ["_newValues":protected] => array(15) {
    ["user_id"] => int(1)
    ["username"] => string(9) "TickTackk"
    ["open_invite"] => bool(false)
    ["conversation_open"] => bool(true)
    ["title"] => string(4) "test"
    ["start_date"] => int(1533003486)
    ["last_message_date"] => int(1533003486)
    ["last_message_user_id"] => int(1)
    ["last_message_username"] => string(9) "TickTackk"
    ["conversation_id"] => int(3)
    ["reply_count"] => int(0)
    ["recipient_count"] => int(0)
    ["first_message_id"] => int(0)
    ["last_message_id"] => int(0)
    ["recipients"] => array(0) {
    }
  }
  ["_values":protected] => array(0) {
  }
  ["_relations":protected] => array(0) {
  }
  ["_previousValues":protected] => array(0) {
  }
  ["_options":protected] => array(0) {
  }
  ["_deleted":protected] => bool(false)
  ["_readOnly":protected] => bool(false)
  ["_writePending":protected] => string(4) "save"
  ["_writeRunning":protected] => bool(true)
  ["_errors":protected] => array(0) {
  }
  ["_cascadeSave":protected] => array(1) {
    [6] => object(XF\Entity\ConversationMessage)#347 (15) {
      ["_uniqueEntityId":"XF\Mvc\Entity\Entity":private] => int(6)
      ["rootClass":protected] => string(29) "XF\Entity\ConversationMessage"
      ["_useReplaceInto":protected] => bool(false)
      ["_newValues":protected] => array(0) {
      }
      ["_values":protected] => array(11) {
        ["conversation_id"] => int(3)
        ["user_id"] => int(1)
        ["username"] => string(9) "TickTackk"
        ["message"] => string(7) "boo moo"
        ["embed_metadata"] => string(2) "[]"
        ["message_date"] => int(1533003486)
        ["message_id"] => int(3)
        ["attach_count"] => int(0)
        ["ip_id"] => int(0)
        ["likes"] => int(0)
        ["like_users"] => string(6) "a:0:{}"
      }
      ["_relations":protected] => array(2) {
        ["User"] => object(XFMG\XF\Entity\User)#301 (16) {
          ["threadmarkCount":protected] => int(0)
          ["_uniqueEntityId":"XF\Mvc\Entity\Entity":private] => int(4)
          ["rootClass":protected] => string(14) "XF\Entity\User"
          ["_useReplaceInto":protected] => bool(false)
          ["_newValues":protected] => array(0) {
          }
          ["_values":protected] => array(38) {
            ["user_id"] => int(1)
            ["username"] => string(9) "TickTackk"
            ["email"] => string(20) "no-spam@ticktackk.io"
            ["custom_title"] => string(0) ""
            ["language_id"] => int(1)
            ["style_id"] => int(0)
            ["timezone"] => string(13) "Europe/London"
            ["visible"] => int(1)
            ["activity_visible"] => int(1)
            ["user_group_id"] => int(2)
            ["secondary_group_ids"] => string(3) "3,4"
            ["display_style_group_id"] => int(3)
            ["permission_combination_id"] => int(6)
            ["message_count"] => int(148)
            ["conversations_unread"] => int(0)
            ["register_date"] => int(1531102240)
            ["last_activity"] => int(1533003275)
            ["trophy_points"] => int(18)
            ["alerts_unread"] => int(0)
            ["avatar_date"] => int(1532394714)
            ["avatar_width"] => int(398)
            ["avatar_height"] => int(384)
            ["avatar_highdpi"] => int(1)
            ["gravatar"] => string(0) ""
            ["user_state"] => string(5) "valid"
            ["is_moderator"] => int(1)
            ["is_admin"] => int(1)
            ["is_banned"] => int(0)
            ["like_count"] => int(2)
            ["warning_points"] => int(0)
            ["is_staff"] => int(1)
            ["secret_key"] => string(32) "dddddddddddddddddddddddddddddddddddddddddd"
            ["privacy_policy_accepted"] => int(0)
            ["terms_accepted"] => int(0)
            ["xfrm_resource_count"] => int(2)
            ["xfmg_album_count"] => int(1)
            ["xfmg_media_count"] => int(2)
            ["xfmg_media_quota"] => int(493)
          }
          ["_relations":protected] => array(4) {
            ["PermissionCombination"] => NULL
            ["Privacy"] => object(XF\Entity\UserPrivacy)#298 (15) {
              ["_uniqueEntityId":"XF\Mvc\Entity\Entity":private] => int(1)
              ["rootClass":protected] => string(21) "XF\Entity\UserPrivacy"
              ["_useReplaceInto":protected] => bool(false)
              ["_newValues":protected] => array(0) {
              }
              ["_values":protected] => array(6) {
                ["user_id"] => int(1)
                ["allow_view_profile"] => string(8) "everyone"
                ["allow_post_profile"] => string(7) "members"
                ["allow_send_personal_conversation"] => string(7) "members"
                ["allow_view_identities"] => string(8) "everyone"
                ["allow_receive_news_feed"] => string(8) "everyone"
              }
              ["_relations":protected] => array(0) {
              }
              ["_previousValues":protected] => array(0) {
              }
              ["_options":protected] => array(0) {
              }
              ["_deleted":protected] => bool(false)
              ["_readOnly":protected] => bool(false)
              ["_writePending":protected] => bool(false)
              ["_writeRunning":protected] => bool(false)
              ["_errors":protected] => array(0) {
              }
              ["_cascadeSave":protected] => array(0) {
              }
              ["_behaviors":protected] => NULL
            }
            ["Profile"] => object(XF\Entity\UserProfile)#299 (15) {
              ["_uniqueEntityId":"XF\Mvc\Entity\Entity":private] => int(2)
              ["rootClass":protected] => string(21) "XF\Entity\UserProfile"
              ["_useReplaceInto":protected] => bool(false)
              ["_newValues":protected] => array(0) {
              }
              ["_values":protected] => array(15) {
                ["user_id"] => int(1)
                ["dob_day"] => int(0)
                ["dob_month"] => int(0)
                ["dob_year"] => int(0)
                ["signature"] => string(0) ""
                ["website"] => string(0) ""
                ["location"] => string(0) ""
                ["following"] => string(0) ""
                ["ignored"] => string(6) "a:0:{}"
                ["avatar_crop_x"] => int(1)
                ["avatar_crop_y"] => int(0)
                ["about"] => string(0) ""
                ["custom_fields"] => string(6) "a:0:{}"
                ["connected_accounts"] => string(6) "a:0:{}"
                ["password_date"] => int(1)
              }
              ["_relations":protected] => array(0) {
              }
              ["_previousValues":protected] => array(0) {
              }
              ["_options":protected] => array(0) {
              }
              ["_deleted":protected] => bool(false)
              ["_readOnly":protected] => bool(false)
              ["_writePending":protected] => bool(false)
              ["_writeRunning":protected] => bool(false)
              ["_errors":protected] => array(0) {
              }
              ["_cascadeSave":protected] => array(0) {
              }
              ["_behaviors":protected] => NULL
            }
            ["Option"] => object(XF\Entity\UserOption)#300 (15) {
              ["_uniqueEntityId":"XF\Mvc\Entity\Entity":private] => int(3)
              ["rootClass":protected] => string(20) "XF\Entity\UserOption"
              ["_useReplaceInto":protected] => bool(false)
              ["_newValues":protected] => array(0) {
              }
              ["_values":protected] => array(11) {
                ["user_id"] => int(1)
                ["show_dob_year"] => int(0)
                ["show_dob_date"] => int(1)
                ["content_show_signature"] => int(1)
                ["receive_admin_email"] => int(0)
                ["email_on_conversation"] => int(1)
                ["is_discouraged"] => int(0)
                ["creation_watch_state"] => string(11) "watch_email"
                ["interaction_watch_state"] => string(11) "watch_email"
                ["alert_optout"] => string(0) ""
                ["use_tfa"] => int(0)
              }
              ["_relations":protected] => array(0) {
              }
              ["_previousValues":protected] => array(0) {
              }
              ["_options":protected] => array(0) {
              }
              ["_deleted":protected] => bool(false)
              ["_readOnly":protected] => bool(false)
              ["_writePending":protected] => bool(false)
              ["_writeRunning":protected] => bool(false)
              ["_errors":protected] => array(0) {
              }
              ["_cascadeSave":protected] => array(0) {
              }
              ["_behaviors":protected] => NULL
            }
          }
          ["_previousValues":protected] => array(0) {
          }
          ["_options":protected] => array(0) {
          }
          ["_deleted":protected] => bool(false)
          ["_readOnly":protected] => bool(false)
          ["_writePending":protected] => bool(false)
          ["_writeRunning":protected] => bool(false)
          ["_errors":protected] => array(0) {
          }
          ["_cascadeSave":protected] => array(0) {
          }
          ["_behaviors":protected] => NULL
        }
        ["Conversation"] => *RECURSION*
      }
      ["_previousValues":protected] => array(0) {
      }
      ["_options":protected] => array(0) {
      }
      ["_deleted":protected] => bool(false)
      ["_readOnly":protected] => bool(false)
      ["_writePending":protected] => bool(false)
      ["_writeRunning":protected] => bool(false)
      ["_errors":protected] => array(0) {
      }
      ["_cascadeSave":protected] => array(0) {
      }
      ["_behaviors":protected] => array(0) {
      }
    }
  }
  ["_behaviors":protected] => array(0) {
  }
}
 
batpool52! said:
["first_message_id"] => int(0)
["last_message_id"] => int(0)
["recipients"] => array(0) {
}
This should be populated.
The stuff is moved to
["_cascadeSave":protected]
which surprisingly is called in preSave. But there is no db->commit ever, so it will stay in cascade save mode.
Something like
PHP:
current($entity->_cascadeSave)
works. But I feel really dirty and I literally just showered.
 
Holy, sometimes I ask myself why I never go to sleep, lol. Obviously overriding the save() itself is the solution.

Edit: Good catch ninja. There are some entities which have no service, so that won't work for everything, but it will do the job for me.
 
Just a note, the missing params (and relations) are because they're not available at that point in the request. The message IDs (and recipients) are fast-updated in the service after saving, so they wouldn't be available even in the entity post-commit (as technically the commit there is only a save-point release, since there's a parent transaction inside the service).
 
Makes sense. Chris suggested to go with XF::runOnce, I did and that works perfectly well. I'm still not sure where to hook that in because it does not matter where I do that - runOnce gets triggered very late. That means entities are fully saved, so I've sticked to post_save. Would there be a better fit for that?
I'm trying to avoid class extensions at this point and I'm just going with one listener class for all events, because it's literally the same event - just a different hint aka entity, so class extensions would be overkill imho.
 
Post-save makes the most sense to me :) A lot of things in the core that need to run post-transaction are set up using \XF::runOnce() inside of _postSave() methods, and if this one spans multiple entities then the listener approach seems most appropriate.
 
Top Bottom