Reputation: 15670
I have created a CI model that dynamically loads certain classes depending on a parameter that is passed in. These classes are just wrapper classes around phpseclib to make ssh connections to different devices. What I'm noticing is that when I try to execute one particular method, I'm getting the above error message.
Here's some sample code to help you understand what I'm doing. This is what my model looks like:
public function get_portstatusall($ip, $switchname)
{
$classname = $this->switchToClassName($switchname);
try{
include_once(APPPATH.'libraries/'.$classname.'.php');
$switch_obj = new $classname($ip, 'password', '');
$switch_obj->connect();
$data = $switch_obj->dosomething();
$switch_obj->disconnect();
return $data;
}
catch (Exception $e) {
echo 'this really should be logged...';
return false;
}
}
public function get_portstatusindividual($ip, $switchname)
{
$classname = $this->switchToClassName($switchname);
try{
include_once(APPPATH.'libraries/'.$classname.'.php');
$switch_obj = new $classname($ip, 'password', '');
$switch_obj->connect();
$data = $switch_obj->dosomethingelse();
$switch_obj->disconnect();
return $data;
}
catch (Exception $e) {
echo 'this really should be logged...';
return false;
}
}
As you can see, i'm dynamically determining which class to load depending on the switchname that is passed in. This code successfully loads a class called "device123.php", let's say. Class device123 in turn, instantiates the SSH2 object that comes with the phpseclib, and uses it to send ssh commands to the device.
Here's a clip of code from device 123:
class device123
{
// sample code to demo how to use phpseclib to create an interactive ssh session.
//this library relies on phpseclib. you must include this class and SSH2.php from Net/phpseclib.
private $_hostname;
private $_password;
private $_username;
private $_connection;
private $_data;
private $_timeout;
private $_prompt;
public function __construct($hostname, $password, $username = "", $timeout = 10)
//public function __construct($params)
{
echo 'in the switch constructor<br>';
set_include_path(get_include_path() . PATH_SEPARATOR . '/var/www/phpseclib');
include('Net/SSH2.php');
$this->_hostname = $hostname;
$this->_password = $password;
$this->_username = $username;
} // __construct
public function connect()
{
$ssh = new Net_SSH2($this->_hostname);
if (!$ssh->login($this->_username, $this->_password)) { //if you can't log on...
die("Error: Authentication Failed for $this->_hostname\n");
}
else {
$output= $ssh->write("\n"); //press any key to continue prompt;
$prompt=$ssh->read('/([0-9A-Z\-])*(#)(\s*)/i', NET_SSH2_READ_REGEX);
if (!$prompt) {
die("Error: Problem connecting for $this->_hostname\n");
}
else {
$this->_connection = $ssh;
}
}
} // connect
public function close()
{
$this->_send('exit');
} // close
public function disconnect()
{
$this->_connection->disconnect();
$ssh=NULL;
}
I don't think I quite understand how I can be redeclaring the SSH2 class... but i wanted to see if perhaps I was not destroying / cleaning up after myself properly. To help troubleshoot, I've tried adding debug echo statements in the constructor and destructor of both the SSH2 class, and also the wrapper class called device123. It all looks proper...
I don't think I'm on the right track... Can you tell me where you think I should start looking? Is it because it's possible that both methods are called ... one after the other... and both can possibly load the same class?
Thanks.
Upvotes: 1
Views: 3052
Reputation: 7941
All php classes must have unique names. You should include
all the files at one place, keep track of all loaded classes if you want a lazy loading, or just use http://cz.php.net/include_once. The same goes for the require
function.
The _once
postfix does exactly what you need: it prevents the files from loading if it already has been loaded, thus preventing the class redeclaration.
Upvotes: 0
Reputation: 10310
Php gives such error when you are trying to load class multiple times like same name class exists in other source file.
Upvotes: 0