/    Sign up×
Community /Pin to ProfileBookmark

Cant seem to figure this OOP issue out (new to OOP but not PHP)

I keep getting a fatal error message “Fatal error: Call to a member function save() on a non-object”
Here is my code. If anyone can help me figure this out it would be great. I am new to OOP (its a harder transition from procedural than I thought it would be!)

[code=php]
<?php
define (“DB_USER” , “#######”); // Insert database username
define (“DB_PASSWORD” , “#######”); // Insert database password
define (“DB_HOST” , “localhost”); // Insert database host
define (“DB_NAME” , “#######”); // Insert database name

Class Contact extends AbstractModel {

protected $dbc;
protected $_user = array();

public function __construct() {

//Connect to the Database
@$dbc=new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
$this->dbc = $dbc;

if(mysqli_connect_errno()) {
die(‘The connection to the database could not be established.’);
}

} // End of Constructor Function

public function load($id) { // Runs a SELECT Query and stores in array

$q = “SELECT id, name, email FROM contacts WHERE id=’$id'”;
$r = $this->dbc->query($q);
$user = $r->fetch_array(MYSQLI_ASSOC);
$this->_user = $user;
}

public function getData($key = false) { // Returns data

if ($key) {
return $this->_user[”.$key.”];
}else{
return $this->_user;
}
}

public function setData($arr, $value=false) { // UPDATES rows in the database

$temp =

if (is_array($arr)) {
$new = array_merge($this->_user, $arr);
$this->_user = $new;
}else{
$this->_user[$arr] = $arr[$value];
}

}

public function save() {

if ($this->_user[‘id’]) {
$q = “UPDATE contacts SET name=’$this->_user[‘name’]’, email=’$this->_user[’email’]’ WHERE id=$this->_user[‘id’]”;
$r = $this->dbc->query($q);
}else{
$q = “INSERT INTO contacts (name, email) VALUES (‘$this->_user[‘name’]’, ‘$this->_user[’email’])”;
$r = $this->dbc->query($q);
}
}

public function delete($id) {

}

}
[/code]

and here is the code I am running:

[code=php]
$contact->setData(‘name’, ‘John Walker’)->save(); //Should run an UPDATE query
echo ‘<br/><br/>’;
print_r($contact->load(1)->getData());
//Should print
// id => 1,
// name => John Walker
// email => [email protected]

$contact->setData(array(
“id” => 1,
“name” => “John Doe the 2nd”,
“email” => “[email protected]
))->save();
echo ‘<br/><br/>’;
print_r($contact->load(1)->getData());
//Should print
// id => 1,
// name => John Doe the 2nd
// email => [email protected]
[/code]

to post a comment
PHP

10 Comments(s)

Copy linkTweet thisAlerts:
@NogDogFeb 05.2014 — Which line is failing? For now, I'll assume it's a line in the calling code where you reference $contact->, in which case you need to look at where that variable gets set -- or is it actually being set at all? (If it is that line, then the error is telling you that $contact is not an object, but some other type of variable (string, integer, null, etc.).
Copy linkTweet thisAlerts:
@chickenlandFeb 05.2014 — Add

[code=php]return $this;[/code] to the end of your function [code=php]public function setData[/code]
Copy linkTweet thisAlerts:
@mccoauthorFeb 05.2014 — Add

[code=php]return $this;[/code] to the end of your function [code=php]public function setData[/code][/QUOTE]


Thanks, that worked for that issue but now I am having issues with updating the database in the save() Here is the function: Can you look over it and see where I am messing up?

[code=php]
public function save() {

if ($this->_user['id']) {
$q = "UPDATE contacts SET name='$this->_user['name']', email='$this->_user['email']' WHERE id=$this->_user['id']";
$r = $this->dbc->query($q);
}else{
$q = "INSERT INTO contacts (name, email) VALUES ('$this->_user['name']', '$this->_user['email'])";
$r = $this->dbc->query($q);
if ($this->dbc->affected_rows == 1) {
$this->_user['id'] = $this->dbc->insert_id;
return $this;
}
}
}
[/code]
Copy linkTweet thisAlerts:
@NogDogFeb 05.2014 — If you want complex variable expressions to be interpolated within a double-quoted string, use "complex variable notation" (i.e. curly braces):
[code=php]
$q = "UPDATE contacts SET name='{$this->_user['name']}', email='{$this->_user['email']}' WHERE id={$this->_user['id']}";
[/code]

However, since you are using MySQLi, I'd really like to see you use a prepared statement and bound parameters instead of using (potentially unsanitized) external inputs directly within a query.
Copy linkTweet thisAlerts:
@mccoauthorFeb 05.2014 — Thanks NogDog. Yes I know about prepared statements, I am just trying to get the functionality down first then I will work on the security. For some reason when I attempt to use this code:

[code=php]
$contact->setData('name', 'John Walker')->save(); //Should run an UPDATE query
echo '<br/><br/>';
print_r($contact->load(1)->getData());
[/code]


with these functions:

[code=php]
public function setData($arr, $value=false) { // UPDATES rows in the database

if (is_array($arr)) {
$new = array_merge($this->_user, $arr);
$this->_user = $new;
}else{
$this->_user[''.$arr.''] = $arr[''.$value.''];
}
return $this;
}

public function save() {

if (isset($this->_user['id'])) {
$q = "UPDATE contacts SET name='{$this->_user['name']}', email='{$this->_user['email']}' WHERE id={$this->_user['id']}";
$r = $this->dbc->query($q);
return $this;
}else{
$q = "INSERT INTO contacts (name, email) VALUES ('{$this->_user['name']}', '{$this->_user['email']})";
$r = $this->dbc->query($q);
if ($this->dbc->affected_rows == 1) {
$this->_user['id'] = $this->dbc->insert_id;
return $this;
}
}
}
[/code]


it returns name=>n instead of name=>John Walker

I believe it is something I have wrong with this line:
[code=php] $this->_user[''.$arr.''] = $arr[''.$value.'']; [/code]

What do you think?
Copy linkTweet thisAlerts:
@mccoauthorFeb 05.2014 — Ok so I figured out my last question and I have one more question about this issue:

How could I better format this function:
[code=php]
public function save() {

if (isset($this->_user['id'])) {
$q = "UPDATE contacts SET name='{$this->_user['name']}', email='{$this->_user['email']}' WHERE id={$this->_user['id']}";
$r = $this->dbc->query($q);
return $this;
}else{
$q = "INSERT INTO contacts (name, email) VALUES ('{$this->_user['name']}', '{$this->_user['email']})";
$r = $this->dbc->query($q);
if ($this->dbc->affected_rows == 1) {
$this->_user['id'] = $this->dbc->insert_id;
return $this;
}
}
}
[/code]

so it checks for an id value and if there is no id it runs an insert. If there is an id then it runs an update. The update portion is working but the insert is not.
Copy linkTweet thisAlerts:
@NogDogFeb 05.2014 — Try changing this...
[code=php]if (isset($this->_user['id'])) {[/code]
...to this...
[code=php]if (!empty($this->_user['id'])) {[/code]
You initialize $_user to be an array, so it is always "set" (I believe).
Copy linkTweet thisAlerts:
@NogDogFeb 05.2014 — Never mind, I was reading that as testing if $_user was set, not the specific array element -- unless you set that element to an empty string if it's not yet set (as opposed to NULL)?
Copy linkTweet thisAlerts:
@NogDogFeb 05.2014 — PS: Here's a way you could avoid some code repetition:
[code=php]
public function save() {
if (!empty($this->_user['id'])) {
$sql = "UPDATE contacts SET name='{$this->_user['name']}', email='{$this->_user['email']}' WHERE id={$this->_user['id']}";
}
else {
$sql = "INSERT INTO contacts (name, email) VALUES ('{$this->_user['name']}', '{$this->_user['email']})";
}
$r = $this->dbc->query($sql);
if($r == false) {
throw new Exception($this->dbc->error.PHP_EOL.$sql);
}
if (empty($this->_user['id']) and $this->dbc->affected_rows == 1) {
$this->_user['id'] = $this->dbc->insert_id;
}
return $this;
}
[/code]
Copy linkTweet thisAlerts:
@BelrickFeb 07.2014 — Hi

You could use this instead:

[code=php]
$q = "INSERT INTO contacts (name, email) VALUES ('{$this->_user['name']}', '{$this->_user['email']})
ON DUPLICATE KEY UPDATE SET name='{$this->_user['name']}', email='{$this->_user['email']}'";


[/code]


Personally I like stripping sql code out into its own class like so

[code=php]




class DBClass {

function update($table, $key, $data = array()){
try{
$dbh = new PDO("mysql:host=$this->hostname;dbname=$this->database","$this->username","$this->password");
}
catch(PDOException $e){
$dbh = null;

}
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$string = "UPDATE $table SET ";
$fields = "";
$values = array();
foreach($data as $key => $value){
$fields .= "$key=?,";
$values[] = $value;
}
$fields = substr($fields, 0, -1);
$values[] = $key;
$string .= $fields." WHERE id=?";
$query = $dbh->prepare($string);
$query->execute($values);

$dbh = null;
}

function insert($table, $data){
try{
$dbh = new PDO("mysql:host=$this->hostname;dbname=$this->database","$this->username","$this->password");
}
catch(PDOException $e){
$dbh = null;

}

$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$string = "INSERT INTO $table ";
$fields = "(";
$values = "(";
foreach($data as $key => $value){
$fields .= "$key,";
$values .= "?,";
$data2[] = $value;
}
$fields = substr($fields, 0, -1);
$values = substr($values, 0, -1);
$fields .= ")";
$values .= ")";
$string .= $fields." values ".$values;
$query = $dbh->prepare($string);
$query->execute($data2);

$dbh = null;
}
}

//usage

$values = array('columnAname' => $valueA,'columnBname' => $valueB);
$dbobject = new DBClass();
$dbobject->update("tablename",$key, $values);

[/code]
×

Success!

Help @mcco spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 5.28,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @AriseFacilitySolutions09,
tipped: article
amount: 1000 SATS,

tipper: @Yussuf4331,
tipped: article
amount: 1000 SATS,

tipper: @darkwebsites540,
tipped: article
amount: 10 SATS,
)...