Michdd Posted September 17, 2009 Share Posted September 17, 2009 I have a class that has these variables: public $socket, $id, $x, $y, $direction; Within another class I'm looping through an array of those classes.. And I'm getting this error(sometimes): Notice: Undefined property: stdClass::$socket Which makes no sense because I'm not creating any stdClass instances.. So I used print_r to see what this was and I get this: stdClass Object ( [x] => 2 [y] => 1 [direction] => 3 ) That's strange because it's almost the same as my Character class, except it's missing the socket and id properties. Also, just a note, both the socket and the id are set in the character class within the constructor. Anyone have any idea why this could be happening? Quote Link to comment https://forums.phpfreaks.com/topic/174529-really-confused/ Share on other sites More sharing options...
trq Posted September 17, 2009 Share Posted September 17, 2009 You'll get a stdClass object if you simply start using a variable as an object. eg; $a->foo = 'bar'; $a->bob = 'blah'; print_r($a); Obviously your not instantiating your class properly or something. We need to see some relevant code. Quote Link to comment https://forums.phpfreaks.com/topic/174529-really-confused/#findComment-919926 Share on other sites More sharing options...
Michdd Posted September 17, 2009 Author Share Posted September 17, 2009 That's strange, because it only happens sometimes.. Here's the relevant code: Creating the object. case PACKET_GETCHARID: $character = new Character($client, count($this->characters)); $this->characters[] = $character; Character class is really simple: class Character { public $socket, $id, $x, $y, $direction; public function __construct($s, $id) { $this->socket = $s; $this->id = $id; echo "Character created! ({$this->socket}, {$this->id})\n"; } } Quote Link to comment https://forums.phpfreaks.com/topic/174529-really-confused/#findComment-920001 Share on other sites More sharing options...
Michdd Posted September 17, 2009 Author Share Posted September 17, 2009 Anyone got any ideas? Quote Link to comment https://forums.phpfreaks.com/topic/174529-really-confused/#findComment-920248 Share on other sites More sharing options...
mikesta707 Posted September 17, 2009 Share Posted September 17, 2009 this line $this->characters[] = $character; you only use the this symbol inside the class itself. when you want to call a method of a class you instantiated inside a variable, you use the variable name $character->characters[] = $character; should help you out Quote Link to comment https://forums.phpfreaks.com/topic/174529-really-confused/#findComment-920255 Share on other sites More sharing options...
Michdd Posted September 17, 2009 Author Share Posted September 17, 2009 this line $this->characters[] = $character; you only use the this symbol inside the class itself. when you want to call a method of a class you instantiated inside a variable, you use the variable name $character->characters[] = $character; should help you out I am using it it inside it's class.. The character class doesn't have an array of other characters (How would that make any sense?) $characters is a property of the server class, which is what it's in. Even if that was the issue, it wouldn't work only sometimes. Quote Link to comment https://forums.phpfreaks.com/topic/174529-really-confused/#findComment-920263 Share on other sites More sharing options...
mikesta707 Posted September 17, 2009 Share Posted September 17, 2009 if you are Creating the object. case PACKET_GETCHARID: $character = new Character($client, count($this->characters)); $this->characters[] = $character; Character class is really simple: class Character { public $socket, $id, $x, $y, $direction; public function __construct($s, $id) { $this->socket = $s; $this->id = $id; echo "Character created! ({$this->socket}, {$this->id})\n"; } } I thought when you said Creating Object, you meant that you were instantiating the object outside of the class. not to mention that I don't see any characters attribute in your character class itself. and if that is inside the character class, than why does the class instantiate objects of itself and store them in a seemingly non-existant class variable? sorry if I misread what you posted, but the little that was posted didn't make much sense in the context it was in. perhaps post what is above or below the Object creation code you posted so I can get a better idea of why you are why that particular snippet is there. Quote Link to comment https://forums.phpfreaks.com/topic/174529-really-confused/#findComment-920267 Share on other sites More sharing options...
Michdd Posted September 17, 2009 Author Share Posted September 17, 2009 The first snippet I posted (creating the object and putting it in $this->characters) is within my Server class. The second snippet is just the Character class. Quote Link to comment https://forums.phpfreaks.com/topic/174529-really-confused/#findComment-920289 Share on other sites More sharing options...
KevinM1 Posted September 17, 2009 Share Posted September 17, 2009 The first snippet I posted (creating the object and putting it in $this->characters) is within my Server class. The second snippet is just the Character class. Are there any other places within your Server class where you instantiate and store Characters? Also, can you show us the loop that's giving the error? Quote Link to comment https://forums.phpfreaks.com/topic/174529-really-confused/#findComment-920290 Share on other sites More sharing options...
Michdd Posted September 17, 2009 Author Share Posted September 17, 2009 Nope, that's the only place where characters are instantiated and stored in $characters. I seem to be getting the error in different places; where ever I try to access the $id or $socket properties of the class. One place specifically is this: private function getCharacterIndex($client) { foreach($this->characters as $index => $character) { if($character->socket == $client) { return $index; break; } } } Quote Link to comment https://forums.phpfreaks.com/topic/174529-really-confused/#findComment-920292 Share on other sites More sharing options...
KevinM1 Posted September 17, 2009 Share Posted September 17, 2009 I'm wondering if your data members are being overwritten somewhere, as nothing in your syntax jumps out at me. Try this: make your character data members private and give them appropriate accessor methods. For example - class Character { private $socket, $id, $x, $y, $direction; public function __construct($s, $id) { $this->socket = $s; $this->id = $id; } public function getSocket() { if ($this->socket) { return $this->socket; } else { return null; } } public function setSocket($s) //just in case you need to reset/change it { $this->socket = $s; } //etc for the rest of the data members } It's a bit of a hassle, but it ensures that your objects are properly encapsulated. You may have a conditional or something else in your system that's trying to assign to the socket data member rather than check for its value (in other words, a missing or extraneous '=' somewhere). Quote Link to comment https://forums.phpfreaks.com/topic/174529-really-confused/#findComment-920299 Share on other sites More sharing options...
Michdd Posted September 17, 2009 Author Share Posted September 17, 2009 That's a really good idea, that I could be using '=' in a conditional by accident. However I don't think your idea is necessary. Only currently the source of this is quite small, under 200 lines in total. I searched everything and double checked for those errors, found nothing. Additionally, it seems like more than a coincidence that the two variables being set in the constructor are the two that are sometimes not being found. Quote Link to comment https://forums.phpfreaks.com/topic/174529-really-confused/#findComment-920307 Share on other sites More sharing options...
Michdd Posted September 17, 2009 Author Share Posted September 17, 2009 I just thought this could possibly help figure out the problem.. It's the only other place where $characters is messed with.. I still don't see how there could be a problem.. but who knows. private function disconnected($client) { $index = array_search($client, $this->clients); $char_index = $this->getCharacterIndex($client); socket_close($this->clients[$index]); unset($this->clients[$index]); unset($this->characters[$char_index]); $this->characters = array_merge($this->characters); $this->sendMessageToAll(PACKET_REMOVE_CHARACTER . " " . $char_index); echo "A client disconnected\n"; } Quote Link to comment https://forums.phpfreaks.com/topic/174529-really-confused/#findComment-920310 Share on other sites More sharing options...
KevinM1 Posted September 17, 2009 Share Posted September 17, 2009 Without seeing more code, I cannot give an answer. Quote Link to comment https://forums.phpfreaks.com/topic/174529-really-confused/#findComment-920317 Share on other sites More sharing options...
Michdd Posted September 17, 2009 Author Share Posted September 17, 2009 Here's my entire Server class source: class Server { public public $port = 5445, $address = '192.168.1.201'; private $clients, $master, $characters; public function __construct() { if (($this->master = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) < 0) echo "socket_create() failed, reason: " . socket_strerror($master) . "\n"; socket_set_option($this->master, SOL_SOCKET, SO_REUSEADDR, 1); if (($ret = socket_bind($this->master, $this->address, $this->port)) < 0) echo "socket_bind() failed, reason: " . socket_strerror($ret) . "\n"; if (($ret = socket_listen($this->master, 5)) < 0) echo "socket_listen() failed, reason: " . socket_strerror($ret) . "\n"; $this->clients = Array($this->master); $this->run(); } private function run() { while(true) { $changed_sockets = $this->clients; $num_changed_sockets = socket_select($changed_sockets, $write = NULL, $except = NULL, NULL); foreach($changed_sockets as $client) { if($client == $this->master) { $this->acceptNewClient(); } else { $this->readMessageFromClient($client); } } } } private function acceptNewClient() { if(($client = socket_accept($this->master)) < 0) { echo "socket_accept() failed: reason: " . socket_strerror($msgsock) . "\n"; return; } else { socket_write($client, '<?xml version="1.0"?><cross-domain-policy><allow-access-from domain="*" to-ports="*"/></cross-domain-policy>' . chr(0x00)); $this->clients[] = $client; socket_getpeername($client, $client_ip); echo "Client successfully connected from " . $client_ip . "\n"; } } private function sendMessageToClient($client, $packet) { socket_write($client, $packet); } private function sendMessageToAll($packet) { foreach($this->clients as $client) { if($client == $this->master) continue; socket_write($client, $packet); } } private function sendMessageToAllLimited($sender, $packet) { foreach($this->clients as $client) { if($client == $this->master || $client == $sender) continue; socket_write($client, $packet); } } private function readMessageFromClient($client) { $buffer = socket_read($client, 2048); if(!$buffer) $this->disconnected($client); else { if(trim($buffer) == '<policy-file-request/>') return; $packet = explode(' ', $buffer, 2); switch($packet[0]) { case PACKET_CHAT: $this->sendMessageToAll(PACKET_CHAT . " $client wrote: {$packet[1]}"); break; case PACKET_GETCHARID: $character = new Character($client, count($this->characters)); $this->characters[] = $character; $this->sendMessageToClient($client, PACKET_GETCHARID . " " . $character->id); break; case PACKET_WALK: $data = explode(',', $packet[1]); $this->characters[$data[0]]->x = $data[1]; $this->characters[$data[0]]->y = $data[2]; $this->characters[$data[0]]->direction = $data[3]; echo "$client : ({$this->characters[$data[0]]->x}, {$this->characters[$data[0]]->y})\n"; $this->sendMessageToAllLimited($client, PACKET_WALK . " " . $this->characters[$data[0]]->id . "," . $this->characters[$data[0]]->x . "," . $this->characters[$data[0]]->y); break; default: break; } } } private function disconnected($client) { $index = array_search($client, $this->clients); $char_index = $this->getCharacterIndex($client); socket_close($this->clients[$index]); unset($this->clients[$index]); unset($this->characters[$char_index]); $this->characters = array_merge($this->characters); $this->sendMessageToAll(PACKET_REMOVE_CHARACTER . " " . $char_index); echo "A client disconnected\n"; } private function getCharacterIndex($client) { foreach($this->characters as $index => $character) { if($character->socket == $client) { return $index; break; } } } } Quote Link to comment https://forums.phpfreaks.com/topic/174529-really-confused/#findComment-920324 Share on other sites More sharing options...
KevinM1 Posted September 17, 2009 Share Posted September 17, 2009 Your best bet is to: 1. Do what I suggested before. I'm a big stickler for keeping data members private specifically for this reason. Named accessor methods make it easier to see where/how an object's data members are being used, and keeping them private protects them from stray overwrites. 2. Write some error handling code. Ensure that a Character exists. Ensure that the proper data members have values before accessing them. Code defensively. 3. Write debugging output. At each major step of the process, output the appropriate info. That all written, I think I may have just spotted your problem: it looks like your PACKET_WALK case is being invoked before you actually create a character. That explains why those secondary data members are filled, but not the ones you usually set in the constructor. $character becomes a default object at that point. Quote Link to comment https://forums.phpfreaks.com/topic/174529-really-confused/#findComment-920340 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.