We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 49407
    • 159 Posts
    Hello everyone, I am running PHP 5.4, and Modx 2.3.5.

    How can I utilize $modx within my extended class?

    Following Shawn Wilkerson's example...
    function __construct(modX & $modx, array $config= array ()) {
                /* Import modx as a reference */
                $this->modx= & $modx;

    I get this error...
    PHP Fatal error: Cannot assign by reference to overloaded object in .../core/components/classextender/model/extendeduser/extuser.class.php on line 9

    My snippet code is as follows...
    $grower->sendNotification( new $modx, 'empty_grow_reminder', $params );


    My class looks like this...
    <?php
    class extUser extends modUser {
        function __construct(xPDO & $xpdo) {
            parent::__construct($xpdo);
            $this->set('class_key','extUser');
        }
    
        public function sendNotification( modX & $modx, $type = 'general', $origin = 'system', $params = false ) {
        	$this->modx = & $modx;
        	$this->modx->log(modX::LOG_LEVEL_ERROR, 'This class is being called. : extuser.class.php');
            $notification = $this->modx->getObject('Notifications', array('type' => $type) );
            if ( !is_object($notification) || !($notification instanceof xPDOObject) ) {
                $this->modx->log(modX::LOG_LEVEL_ERROR, 'Failed to create object of type: Notification: sendNotification() : extuser.class.php');
                return false;
            }
        }


    I'm trying to pass $modx to the method because I have control over how/when it's invoked, as opposed to placing it in the constructor where on site load it's crashing the entire site including the manager.

    Please, for the sake of my sanity, could a level 9000 Modx/PHP pro chime in on this? Documentation on this is reminiscent of bigfoot lore. smiley

    This question has been answered by multiple community members. See the first response.

      • 3749
      • 24,544 Posts
      Take out the 'new' -- hopefully you don't want a new instance of MODX, you want the real one, which should be available in any request. wink

      I think the error is a byproduct of using a 'new' that's not followed by a class name ($modx is not a class name -- it's an instance of the class). new modX (which is the class name) would make sense, but as I said, I don't think you want a new instance of MODX and unless you're running a stand-alone script outside of MODX. In that case you should instantiate *and* initialize MODX earlier in the code.
        Did I help you? Buy me a beer
        Get my Book: MODX:The Official Guide
        MODX info for everyone: http://bobsguides.com/modx.html
        My MODX Extras
        Bob's Guides is now hosted at A2 MODX Hosting
      • discuss.answer
        • 49407
        • 159 Posts
        Quote from: BobRay at Oct 11, 2015, 11:51 PM
        Take out the 'new' -- hopefully you don't want a new instance of MODX, you want the real one, which should be available in any request. wink

        I think the error is a byproduct of using a 'new' that's not followed by a class name ($modx is not a class name -- it's an instance of the class). new modX (which is the class name) would make sense, but as I said, I don't think you want a new instance of MODX and unless you're running a stand-alone script outside of MODX. In that case you should instantiate *and* initialize MODX earlier in the code.

        I removed the "new" and it's still giving me the same error. Cleared modx cache and browser cache. Still...
        PHP Fatal error: Cannot assign by reference to overloaded object in .../core/components/classextender/model/extendeduser/extuser.class.php on line 9
          • 3749
          • 24,544 Posts
          It's a goofy error message, but I think it's caused by your class not having a $modx class variable. Php then assumes that your trying to overload the parent's $modx variable in your class. The fix would be:

          class extUser extends modUser {
              var $modx;
              function __construct(xPDO & $xpdo) {
              //etc.


          I suspect that with the fix, you can use $this->modx in your class instead of passing it.

          If that works, I think you can simplify the code a little like this:

          class extUser extends modUser {
              var $modx;
              function __construct(&$modx) {
                  $this->modx =& $modx;
                  /* parent::__construct($xpdo); */
                  $this->set('class_key','extUser');
              }
           
              public function sendNotification($type = 'general', $origin = 'system', $params = false ) {
                  $this->modx->log(modX::LOG_LEVEL_ERROR, 'This class is being called. : extuser.class.php');
                  $notification = $this->modx->getObject('Notifications', array('type' => $type) );
                  if ( !is_object($notification) || !($notification instanceof xPDOObject) ) {
                      $this->modx->log(modX::LOG_LEVEL_ERROR, 'Failed to create object of type: Notification: sendNotification() : extuser.class.php');
                      return false;
                  }
              }
              return true;
          }


            Did I help you? Buy me a beer
            Get my Book: MODX:The Official Guide
            MODX info for everyone: http://bobsguides.com/modx.html
            My MODX Extras
            Bob's Guides is now hosted at A2 MODX Hosting
            • 13428 ☆ A M B ☆
            • 1,031 Posts
            I don't think that it is a good idea to re-assign the 'global' $modx object to the class $modx object, which is already a reference to the 'global' $modx object, since it is inherited from modUser/modObject. You don't need that, it is already there.
              • 49407
              • 159 Posts
              Quote from: Jako at Oct 13, 2015, 02:16 AM
              I don't think that it is a good idea to re-assign the 'global' $modx object to the class $modx object, which is already a reference to the 'global' $modx object, since it is inherited from modUser/modObject. You don't need that, it is already there.

              Jako, If it ($modx) is already there, why does PHP give me an error "call to a member function 'log' on a non-object" at line 10, when include or remove the '$this->' from $this->modx->log()? Also why does Shawn Wilkerson's example show the following code?
              if (!class_exists('Sampleclass')) {
                  class Sampleclass
                  {
                      function __construct(modX & $modx, array $config= array ()) { // modX as a parameter
                          /* Import modx as a reference */
                          $this->modx= & $modx; // <--- And this here is where I am getting the overloading error.
                          /* Establish the environment */
                          $this->extPath= $modx->getOption('core_path',null, MODX_CORE_PATH).'components/extendeduser/';


              BobRay, I am not getting the overloading error after applying your code, removing the xPDO parameter from the constructor, however, now I am getting...
              PHP Fatal error: Call to a member function getOption() on a non-object in .../core/xpdo/om/xpdoobject.class.php on line 703
              Because there is no longer an xPDO object.

              When I use BOTH parameters, modX and xPDO with modX being the first parameter I get...
              PHP Catchable fatal error: Argument 2 passed to extUser::__construct() must be an instance of xPDO, none given, called in .../core/xpdo/xpdo.class.php on line 771 and defined in .../core/components/classextender/model/extendeduser/extuser.class.php on line 4

              When I switch the order of the params in the constructor I get this...
              PHP Catchable fatal error: Argument 2 passed to extUser::__construct() must be an instance of modX, none given, called in .../core/xpdo/xpdo.class.php on line 771 and defined in .../core/components/classextender/model/extendeduser/extuser.class.php on line 4

              Whatever piece of code is calling the extUser class on site run, is NOT sending the modX parameter and the modX does NOT already exist in the extUser class as stated by Jako.

              I've read and been told and have tested so many variable scenarios to this point, that fatally error, I am totally confused. All I know is that you seemingly cannot have modX and xPDO both in the class constructor.
              • discuss.answer
                • 49407
                • 159 Posts
                To get past the constructor I have tried this code...
                <?php
                class extUser extends modUser {
                    var $modx;
                    function __construct(xPDO & $xpdo) {
                        parent::__construct($xpdo);
                        $this->set('class_key','extUser');
                    }
                
                    public function sendNotification(&$modx, $type = 'general', $origin = 'system', $params = false ) {
                    	$this->modx = & $modx;
                    	$this->modx->log(modX::LOG_LEVEL_ERROR, 'This class is being called. : extuser.class.php');
                        $notification = $this->modx->getObject('Notifications', array('type' => $type) );
                        if ( !is_object($notification) || !($notification instanceof xPDOObject) ) {
                            $this->modx->log(modX::LOG_LEVEL_ERROR, 'Failed to create object of type: Notification: sendNotification() : extuser.class.php');
                            return false;
                        }
                    }
                }


                This actually works.

                So, now I know that xPDO is a required parameter in the constructor, that is already being sent on site load/instantiation. modX seemingly cannot be added to the constructor of the extUser class. Seemingly, modX must be carried in to each function in your extUser class.

                Maybe a function could be written above the constructor that carries modX into the class and then the constructor could call that function? I don't have much faith in that because you would need to be sending modX to that function somehow or creating a new instance of it?

                At least I learned something.

                Thank you very much BobRay, for your code example and suggestions. It seems that using &$modx, not modX & $modx is what eliminated the overloading error.
                  • 13428 ☆ A M B ☆
                  • 1,031 Posts
                  The two examples on RTFM Extending modUser work with different object types. One extends modUser and the other creates an own class and assigns $modx to $this->modx on construct.

                  The modUser class doesn't have $modx inside but $xpdo. So your sendNotification method could work with the following changes:

                  public function sendNotification($type = 'general', $origin = 'system', $params = false ) {
                          $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, 'This class is being called. : extuser.class.php');
                          $notification = $this->xpdo->getObject('Notifications', array('type' => $type) );
                          if ( !is_object($notification) || !($notification instanceof xPDOObject) ) {
                              $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, 'Failed to create object of type: Notification: sendNotification() : extuser.class.php');
                              return false;
                          }
                      }
                  


                  I am not sure, wether you could access all modX methods in that xpdo object.
                    • 3749
                    • 24,544 Posts
                    Jako is correct that the modUser class uses $xpdo rather than $modx (probably to make it more lightweight). I assumed that since $modx is an instance of $xpdo, it should work as well, but he's correct that you shouldn't need to send it at all, since your class is extending modUser and $this->xpdo should be all you need unless you need specific $modx methods like makeUrl(), sendRedirect(), runProcessor(), or runSnippet().

                    I think his code should work fine for you.
                      Did I help you? Buy me a beer
                      Get my Book: MODX:The Official Guide
                      MODX info for everyone: http://bobsguides.com/modx.html
                      My MODX Extras
                      Bob's Guides is now hosted at A2 MODX Hosting
                      • 13428 ☆ A M B ☆
                      • 1,031 Posts
                      I am not sure what is in $this->xpdo, if the new user is created with $modx->newObject('extUser'). The instance is created with $this and $this is $modx at that moment. So you should have access to all $modx methods in my opinion.

                      Try it and if acessing the methods is possible, you could use the following constructor for the extUser class:

                      class extUser extends modUser {
                          var $modx;
                      
                          function __construct(xPDO & $xpdo) {
                              parent::__construct($xpdo);
                              $this->modx = & $xpdo;  // maybe $this->modx = & $this->xpdo could work too, if I am right
                              $this->set('class_key','extUser');
                          }
                       


                      Since it is assigned as reference, the memory impact should be not that high.