Jump to content

Attempt to assign property of non-object


Go to solution Solved by mac_gyver,

Recommended Posts

I am using an open source address book on my web site that is coded using PHP and connected to a MySQL database. I believe it was written for an older version. I am currently using PHP 5.4.23 and MySQL 5.5.32. I have no experience with PHP or MySQL, but I was able to figure out how to fix several errors. I still have one problem that I cannot figure out. I am hoping someone can help me. Thanks in advance.

I think it may be a syntax problem from using a newer version of PHP. I'm not exactly sure what the line is doing, but I commented it out and it works. It just doesn't get the option that tells it to open it in a popup window. I'm hoping that is an easy fix.  It starts by creating a new object.

// RETRIEVE OPTIONS THAT PERTAIN TO THIS PAGE
    $options = new Options();

I figured out that this line is doing a SQL query to a specific table. It will retrieve either a 1 or a 0. Or it will return an error. Also, that row in the database is configured as an "int(1)" and does not accept null values.

$options = mysql_fetch_array(mysql_query("SELECT displayAsPopup FROM " . TABLE_OPTIONS . " LIMIT 1", $db_link))
        or die(reportScriptError("Unable to retrieve options."));

So at this point $options should equal 1 with my current configuration. Then, I don't really understand what the next line is trying to do, but this is the line that fails.

$options->displayAsPopup = $options['displayAsPopup'];

This is the error I get.

Warning: Attempt to assign property of non-object in /public_html/members/search.php on line 37

Warning: Cannot modify header information - headers already sent by (output started at /public_html/members/search.php:37) in /public_html/members/search.php on line 114

 

 

I'm not sure if I'm using the correct terminology for this language, but $options seems like a UDT which appears to be defined by the following code. Maybe that is where the problem is. I really have no idea what is going on in there though.

<?php 
/************************************************************* 
 *  THE ADDRESS BOOK  :  version 1.04 
 *   
 *  lib/class-options.php 
 *  Object: retrieve and set global or user options 
 * 
 *************************************************************/ 

  
class Options { 
     
    // DECLARE OPTION VARIABLES 
    var $bdayInterval; 
    var $bdayDisplay; 
    var $displayAsPopup; 
    var $useMailScript; 
    var $picAlwaysDisplay; 
    var $picWidth; 
    var $picHeight; 
    var $picDupeMode; 
    var $picAllowUpload; 
    var $modifyTime; // not currently in use; reserved for future use 
    var $msgLogin; 
    var $msgWelcome; 
    var $countryDefault; 
    var $allowUserReg; 
    var $eMailAdmin; 
    var $requireLogin; 
    var $language; 
    var $defaultLetter; // test 
    var $limitEntries; // test 
     
    // DECLARE OTHER VARIABLES 
    var $global_options; 
    var $user_options; 
    var $message; 

     
    // CONSTRUCTOR FUNCTION 
    function Options() { 
        $this->get(); 
    } 
     
    function get() { 
        // This function retrieves global options first. Then, it retrieves user options 
        // if a user name is available, which will overwrite certain global options. 
        $this->set_global(); 
        if ((isset($_SESSION['username'])) && ($_SESSION['username'] != '@auth_off')) { 
            $this->set_user(); 
        } 
    } 
     
    function set_global() { 
        // This function restores all options to the administrator-specified global settings. 
        // Call this function when you need to ignore the user-specified settings. 
        // Note: If you do not call this function, you can still obtain global settings 
        // directly using the $this->global_options variable. 
        global $db_link; 
         
        $this->global_options = mysql_fetch_array(mysql_query("SELECT * FROM " . TABLE_OPTIONS . " LIMIT 1", $db_link)) 
                or die(reportScriptError("Unable to retrieve global options.")); 

        $this->bdayInterval     = $this->global_options['bdayInterval']; 
        $this->bdayDisplay      = $this->global_options['bdayDisplay']; 
        $this->displayAsPopup   = $this->global_options['displayAsPopup']; 
        $this->useMailScript    = $this->global_options['useMailScript']; 
        $this->picAlwaysDisplay = $this->global_options['picAlwaysDisplay']; 
        $this->picWidth         = $this->global_options['picWidth']; 
        $this->picHeight        = $this->global_options['picHeight']; 
        $this->picDupeMode      = $this->global_options['picDupeMode']; 
        $this->picAllowUpload   = $this->global_options['picAllowUpload']; 
        $this->modifyTime       = $this->global_options['modifyTime']; 
        $this->msgLogin         = stripslashes( $this->global_options['msgLogin'] ); 
        $this->msgWelcome       = stripslashes( $this->global_options['msgWelcome'] ); 
        $this->countryDefault   = $this->global_options['countryDefault']; 
        $this->allowUserReg     = $this->global_options['allowUserReg']; 
        $this->eMailAdmin       = $this->global_options['eMailAdmin']; 
        $this->requireLogin     = $this->global_options['requireLogin']; 
        $this->language         = $this->load_lang($this->global_options['language']); 
        $this->defaultLetter    = $this->global_options['defaultLetter']; 
        $this->limitEntries     = $this->global_options['limitEntries']; 
    } 
     
    function set_user() { 
        // This function overrides admin-specified options with user options. 
        // Call this function if you need to restore the user settings after resetting 
        // to global settings. 
        // Note: If you do not call this function, you can still obtain the user settings 
        // directly using the $this->user_options variable. 
        global $db_link; 
         
        $this->user_options = mysql_fetch_array(mysql_query("SELECT * FROM " . TABLE_USERS . " WHERE username='" . $_SESSION['username'] . "' LIMIT 1", $db_link)) 
                or die(reportScriptError("Unable to retrieve user options.")); 

        if (!is_null($this->user_options['bdayInterval']))   $this->bdayInterval = $this->user_options['bdayInterval']; 
        if (!is_null($this->user_options['bdayDisplay']))    $this->bdayDisplay = $this->user_options['bdayDisplay']; 
        if (!is_null($this->user_options['displayAsPopup'])) $this->displayAsPopup = $this->user_options['displayAsPopup']; 
        if (!is_null($this->user_options['useMailScript']))  $this->useMailScript = $this->user_options['useMailScript']; 
        if (!is_null($this->user_options['language']))       $this->language = $this->load_lang($this->user_options['language']); 
        if (!is_null($this->user_options['defaultLetter']))  $this->defaultLetter = $this->user_options['defaultLetter']; 
        if (!is_null($this->user_options['limitEntries']))   $this->limitEntries = $this->user_options['limitEntries']; 
    } 
     
    function save_global() { 
        // This function saves global settings to the database, in the options table. 
        // It assumes that the options have already been placed in the $_POST superglobal. 
        global $db_link; 
        global $lang; 

        // CHECK NUMERICAL INPUT 
        // This is DIFFERENT from the previous implemenation (TAB 1.03 and earlier) 
        // where empty or faulty information resulted in resetting the value to a 
        // hard-coded default value. Here, it will check if the $_POST value is valid, 
        // and if so, it will overwrite the existing setting. Otherwise the original 
        // value (whatever it is) is retained. 
        if (($_POST['bdayInterval'] > 0) && is_numeric($_POST['bdayInterval']))     $this->bdayInterval = $_POST['bdayInterval']; 
        if (($_POST['picWidth'] > 0) && is_numeric($_POST['picWidth']))             $this->picWidth = $_POST['picWidth']; 
        if (($_POST['picHeight'] > 0) && is_numeric($_POST['picHeight']))           $this->picHeight = $_POST['picHeight']; 
        if (($_POST['picDupeMode'] == 1) || ($_POST['picDupeMode'] == 2) || ($_POST['picDupeMode'] == 3))  $this->picDupeMode = $_POST['picDupeMode']; 
        if (($_POST['countryDefault']))                                             $this->countryDefault = $_POST['countryDefault']; 
        if (($_POST['limitEntries'] >= 0) && is_numeric($_POST['limitEntries']))    $this->limitEntries = $_POST['limitEntries']; 
         
        if ($_POST['language']) $this->language = $_POST['language'];    // not numerical, but the same principle applies 
        $this->defaultLetter = (empty($_POST['defaultLetter'])) ? "" : $_POST['defaultLetter']; // if no value is sent, then turn defaultLetter off (note: off must be empty string, NOT 0 value) 

        // CLEAN UP STRING INPUT 
        // These are allowed to be blank. We will take these "as is" -- no checking is done. 
        $this->msgLogin   = addslashes(strip_tags(trim($_POST['msgLogin']),'<a><b><i><u><p><br>')); 
        $this->msgWelcome = addslashes(strip_tags(trim($_POST['msgWelcome']),'<a><b><i><u><p><br>')); 
         
        // CHECKBOXES 
        // If the variable does not exist in $_POST, that means the checkbox is turned off! 
        // Give it a value of 0 so we know what to enter into the database. 
        // Everything else results in 1 (which should be the contents of the $_POST variable anyway, but let's be sure 
        $this->bdayDisplay      = (empty($_POST['bdayDisplay'])) ? 0 : 1; 
        $this->displayAsPopup   = (empty($_POST['displayAsPopup'])) ? 0 : 1; 
        $this->useMailScript    = (empty($_POST['useMailScript'])) ? 0 : 1; 
        $this->picAlwaysDisplay = (empty($_POST['picAlwaysDisplay'])) ? 0 : 1; 
        $this->picAllowUpload   = (empty($_POST['picAllowUpload'])) ? 0 : 1; 
        $this->allowUserReg     = (empty($_POST['allowUserReg'])) ? 0 : 1; 
        $this->eMailAdmin       = (empty($_POST['eMailAdmin'])) ? 0 : 1; 
        $this->requireLogin     = (empty($_POST['requireLogin'])) ? 0 : 1; 

        // CREATES THE QUERY AND UPDATES THE OPTIONS TABLE 
        $sql = "UPDATE " . TABLE_OPTIONS . " SET  
                bdayInterval      = $this->bdayInterval, 
                bdayDisplay       = $this->bdayDisplay, 
                displayAsPopup    = $this->displayAsPopup, 
                useMailScript     = $this->useMailScript, 
                picAlwaysDisplay  = $this->picAlwaysDisplay, 
                picWidth          = $this->picWidth, 
                picHeight         = $this->picHeight, 
                picDupeMode       = $this->picDupeMode, 
                picAllowUpload    = $this->picAllowUpload, 
                modifyTime        = $this->modifyTime, 
                msgLogin          = '$this->msgLogin', 
                msgWelcome        = '$this->msgWelcome', 
                countryDefault    = '$this->countryDefault', 
                allowUserReg      = $this->allowUserReg, 
                requireLogin      = $this->requireLogin, 
                eMailAdmin        = $this->eMailAdmin, 
                language          = '$this->language', 
                defaultLetter     = '$this->defaultLetter', 
                limitEntries      = $this->limitEntries"; 

        mysql_query($sql, $db_link) 
            or die(reportSQLError($lang['ERR_OPTIONS_NO_SAVE'])); 

        $this->get(); 
        $this->message = $lang['OPT_SAVED']; 

        return true; 
    } 
     
     
    function save_user() { 
        // This function saves user settings to the database, in the users table. 
        // This is largely similar in function to save_global() except that there are much fewer 
        // options to deal with. It may be better to condense the two functions into  
        // one function so as to avoid repetition of code but we can worry about that later. 
        global $db_link; 
        global $lang; 
         
        // CHECK INPUT 
        // Condensed version of events from save_global(). 
        if (($_POST['bdayInterval'] > 0) && is_numeric($_POST['bdayInterval']))     $this->bdayInterval = $_POST['bdayInterval']; 
        if (($_POST['limitEntries'] >= 0) && is_numeric($_POST['limitEntries']))    $this->limitEntries = $_POST['limitEntries']; 
        if ($_POST['language']) $this->language = $_POST['language']; 
        $this->defaultLetter    = (empty($_POST['defaultLetter'])) ? "" : $_POST['defaultLetter']; 
        $this->bdayDisplay      = (empty($_POST['bdayDisplay'])) ? 0 : 1; 
        $this->displayAsPopup   = (empty($_POST['displayAsPopup'])) ? 0 : 1; 
        $this->useMailScript    = (empty($_POST['useMailScript'])) ? 0 : 1; 

        // CREATES THE QUERY AND UPDATES THE OPTIONS TABLE 
        $sql = "UPDATE " . TABLE_USERS . " SET  
                bdayInterval      = $this->bdayInterval, 
                bdayDisplay       = $this->bdayDisplay, 
                displayAsPopup    = $this->displayAsPopup, 
                useMailScript     = $this->useMailScript, 
                language          = '$this->language', 
                defaultLetter     = '$this->defaultLetter', 
                limitEntries      = $this->limitEntries 
                WHERE username='" . $_SESSION['username'] . "'"; 
        mysql_query($sql, $db_link) 
            or die(reportSQLError($lang['ERR_OPTIONS_NO_SAVE'])); 
         
        $this->get(); 
        $this->message = $lang['OPT_SAVED_USER']; 

        return true; 
    } 
     
    function reset_user() { 
        // This function is designed to clear the user's settings and have all option variables 
        // set to NULL in the database. NULL means neither yes or no, and will force the 
        // script to look to the global options table for information. 
        global $db_link; 
        global $lang; 

        // QUERY 
        $sql = "UPDATE " . TABLE_USERS . " SET  
                bdayInterval      = NULL, 
                bdayDisplay       = NULL, 
                displayAsPopup    = NULL, 
                useMailScript     = NULL, 
                language          = NULL, 
                defaultLetter     = NULL, 
                limitEntries      = NULL 
                WHERE username='" . $_SESSION['username'] . "'"; 
        mysql_query($sql, $db_link) 
            or die(reportSQLError($lang['ERR_OPTIONS_NO_SAVE'])); 
         
        // RESET MEMBER VARIABLES 
        $this->set_global();     
         
        $this->message = $lang['OPT_RESET_USER']; 
        return true; 
    } 
         
    function load_lang($file) { 
        global $php_ext; 
        // The following variables are loaded from country files. Make these global scope 
        global $lang; 
        global $country; 
         
        $fullpath = dirname($_SERVER['SCRIPT_FILENAME']) . '/' . PATH_LANGUAGES . $file . '.' . $php_ext; 
        // This function takes the value returned by the 'language' column in global or user options table, 
        // and checks to make sure that the file exists in the /language directory. If it exists, it loads 
        // the language into memory. If it does not exist, it attempts to loads 'english' (the default language). 
        if (file_exists($fullpath)) { 
            require_once($fullpath); 
            return $file; 
        } else { 
            require_once(dirname($_SERVER['SCRIPT_FILENAME']) . '/' . PATH_LANGUAGES . 'english.' . $php_ext); 
            $this->message = $lang['OPT_LANGUAGE_MISSING']; 
            return 'english'; 
        }  
    } 
     
// END Options 
} 


?>

The problem is you're trying to use the "$options" variable for two different things at the same time: one for an object and one for a row from a database query. Pick one to call "options" and change the name of the other one.

Are you talking about in the single line that is failing or in the other PHP file?  I see in the other file there is a class and a function that are both called options.  Is this what I want to change?  If so, I am assuming that I would want to change the function.  The class is probably called from several locations.  Does that sound accurate?  I really don't know anything about PHP.

or in the other PHP file?

 

 

if the posted lines of code are from multiple separate places in the program, they could be the intended usage. it may also be that the code has always been foo-bar and with warning messages turned off 'functioned' as the author intended.

 

post at least 5-10 lines of code leading up to and including the line where the error is occurring. also, posting a link to the original site where you got this script would help.

You can find the script here.  It is no longer in development and the author's web site doesn't exist anymore.  I believe this functioned correctly on previous versions of PHP, but I'm not positive.  I did fix several other errors that were from changes in syntax.

http://sourceforge.net/projects/theaddressbook/

 

Here is the entire page called search.php.  It fails on line 37, which I currently have commented out.  The page works with the line commented but it opens the search results on the same page instead of in a popup window, even when the displayaspopup option is enabled.

<?php
/*************************************************************
 *  THE ADDRESS BOOK  :  version 1.04d
 *   
 *  CHANGE LOG since 1.04 release on 30 May 05 where + sign indicates if this particular file was modified
 *			1.04a - Corrected <? to <?php for all instances due to some servers having short_open_tags set to off. 
 *			1.04b - Corrected 3 more cases of <? which were missed earlier. Only affects index.php
 *			1.04c - Corrected mailsend.php syntax error (extraneous open bracket [).
 *			1.04d - Corrected Javascript error in mailto.php
 *					Corrected improper default country select in edit.php
 *					Removed use of file_get_contents() from options.php and users.php due to pre php4.3 incompatibility
 *		+			Changed call to charset iso-8859-1 from hard code in header to variable to accomodate greek and other non- 8859-1 languages
 ****************************************************************  
 *  search.php
 *  Searches address book entries. 
 *
 *************************************************************/


// ** GET CONFIGURATION DATA **
    require_once('constants.inc');
    require_once(FILE_FUNCTIONS);
    require_once(FILE_CLASS_OPTIONS);


// ** OPEN CONNECTION TO THE DATABASE **
    $db_link = openDatabase($db_hostname, $db_username, $db_password, $db_name);

// ** CHECK FOR LOGIN **
	checkForLogin();

// RETRIEVE OPTIONS THAT PERTAIN TO THIS PAGE
	$options = new Options();

    $options = mysql_fetch_array(mysql_query("SELECT displayAsPopup FROM " . TABLE_OPTIONS . " LIMIT 1", $db_link))
		or die(reportScriptError("Unable to retrieve options."));
    //$options->displayAsPopup = $options['displayAsPopup'];


// PHP code is placed BEFORE sending any HTML information because we want the script to 
// stop processing and send another file instead if a single entry is found.
// Because we don't rely on the browser to redirect, this allows pressing 'back' on the
// browser to take us back to the list, and not keep forwarding.


// See if search terms have been passed to this page.
	$goTo = $_POST['goTo'];
    if (!$goTo AND !$search) {
        echo("<P>".$lang['SEARCH_TERMS']);
        exit();
    }

// goTo functionality
// Search does not work so we'll make it do the same thing as goTo for now.
    if ($search) {
        $goTo = $search;
    }
    if ($goTo) {
        $gotosql = "SELECT id, CONCAT(lastname,', ',firstname) AS fullname, lastname, firstname
                   FROM " . TABLE_CONTACT . "
                   WHERE 
                     CONCAT(firstname,' ', lastname) LIKE '%$goTo%' OR
                     CONCAT(firstname,' ', middlename,' ', lastname) LIKE '%$goTo%' OR
                     nickname LIKE '%$goTo%'
                   ORDER BY fullname";
        $r_goto = mysql_query($gotosql, $db_link);
        $numGoTo = mysql_num_rows($r_goto);

    }

// print results
    if ($numGoTo == 1) {
        $t_goto = mysql_fetch_array($r_goto); 
        $contact_id = $t_goto['id'];
		if ($options->displayAsPopup == 1) { 
        	$theAddress = FILE_ADDRESS."?id=".$contact_id; 
?>
<HTML>
<HEAD>
	<TITLE> <?php  echo "$lang[TITLE_TAB] - $lang[SEARCH_LBL]" ?></TITLE>
	<meta http-equiv="Content-Type" content="text/html; charset=<?php echo $lang['CHARSET']?>">
	<LINK REL="stylesheet" HREF="styles.css" TYPE="text/css">
	<SCRIPT LANGUAGE="JavaScript">
	<!--
	window.open('<?php echo($theAddress); ?>',null,'width=600,height=450,scrollbars,resizable,menubar,status'); history.back();
	// -->
	</SCRIPT>
</HEAD>
<BODY>

<CENTER>
<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0 WIDTH=570>
  <TR>
    <TD CLASS="headTitle"><?php echo $lang['SEARCH_RESULTS']?></TD>
  </TR>
  <TR>
    <TD CLASS="infoBox">

      <TABLE BORDER=0 CELLPADDING=10 CELLSPACING=0 WIDTH=500><TR VALIGN="top"><TD CLASS="data">
One entry found. It will appear in a new window. If no window appears, <A HREF="#" onClick="window.open('<?php echo($theAddress); ?>',addressWindow,'width=600,height=450,scrollbars,resizable,menubar,status'); return false;">click here</A>.
      </TD></TR></TABLE>

    </TD>
  </TR>
</TABLE>
</CENTER>


</BODY>
</HTML>
<?php
      	}         
		else {
	        header("Location: " . FILE_ADDRESS . "?id=$contact_id"); 
		}
        exit;
    }

?>
<HTML>
<HEAD>
	<TITLE> <?php  echo "$lang[TITLE_TAB] - $lang[SEARCH_LBL]" ?></TITLE>
	<LINK REL="stylesheet" HREF="styles.css" TYPE="text/css">
	<meta http-equiv="Content-Type" content="text/html; charset=<?php echo $lang['CHARSET']?>">
</HEAD>
<BODY>

<CENTER>
<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0 WIDTH=570>
  <TR>
    <TD CLASS="headTitle"><?php echo $lang['SEARCH_LBL'] ?></TD>
  </TR>
  <TR>
    <TD CLASS="infoBox">

      <TABLE BORDER=0 CELLPADDING=10 CELLSPACING=0 WIDTH=500><TR VALIGN="top"><TD CLASS="data">
<?php

    // print search info
    echo("<B>".$lang['SEARCH_MATCH']. " $goTo ".$lang['SEARCH_IN_NAME']."</B>");

    // print results in case $numGoTo did not equal 1
    if ($numGoTo == 0) {
        echo("<P>".$lang['SEARCH_NONE']);
        echo("<P><B><A HREF=\"" . FILE_LIST . "\">".$lang['BTN_RETURN']."</A></B>");
    }
    else {
        echo("<P>".$lang['SEARCH_MULTIPLE']."<P>");
        while ($t_goto = mysql_fetch_array($r_goto) ) {
            $contact_id = $t_goto['id'];
            $contact_name = $t_goto['fullname'];
            $contact_firstname = $t_goto['firstname'];
            $contact_lastname = $t_goto['lastname'];
			if (!$contact_firstname) { $contact_name = $contact_lastname; }

	        if ($options->displayAsPopup == 1) {
	            $popupLink = " onClick=\"window.open('" . FILE_ADDRESS . "?id=$contact_id','addressWindow','width=600,height=450,scrollbars,resizable,menubar,status'); return false;\"";
	        }

            echo("<BR><A HREF=\"" . FILE_ADDRESS . "?id=$contact_id\"$popupLink>$contact_name</A>\n");
        }
        echo("<P><B><A HREF=\"" . FILE_LIST. "\">".$lang['BTN_RETURN']."</A></B>");
    }

?>
      </TD></TR></TABLE>

    </TD>
  </TR>
</TABLE>
</CENTER>




</BODY>
</HTML>

  • Solution

ASSUMING (<--- making a big assumption) that the options class functions correctly, i.e. getting the global settings, then modifying them with any user settings, then the offending mysql logic in the search.php page should not be needed.

 

try it with the following lines commented out -

    //$options = mysql_fetch_array(mysql_query("SELECT displayAsPopup FROM " . TABLE_OPTIONS . " LIMIT 1", $db_link))
    //    or die(reportScriptError("Unable to retrieve options."));
    // $options->displayAsPopup = $options['displayAsPopup'];

i suggested commenting out the three lines that are setting $options variable from the inline mysql query code.

 

the rest of the code on that page expects $options to be an instance of the options class. therefore, any code that is directly setting $options to anything else, doesn't belong.

That seems to work.  I'm wondering if that will cause the Global option to override the User option though.  If so, I don't think that will be much of an issue.  I think this will work for me, unless you have any other suggestions after finding out the results of that test.

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.