Jump to content

OOP Class Static Call


johnsmith153

Recommended Posts

Is it ok to do this?

class Two {

function anything() {
   classOne::anyMethod();
}

}

 

I'm sure it is but this doesn't pose very well for if I wanted to swop out one class for another. I'd then have to make changes to the code (unless I were sure all classes were named the same).

 

--

 

What I want it for (and this may be another issue), is this:

 

I may need to create more than one database instance:

//Database exends mysqli
$db[1] = new Database(2);//database 2 used this time
$db[2] = new Database(5);//db5

 

I then always use Database::closeAll() at any point in my script to ensure all connections are closed. Of course $this->close wouldn't close all instances/connections, just the one I was working on.

 

I know I don;t have to close all connections, but I may as well, and there are other occasions where the first part of this question applies, so please don't just respond "no need to close".

 

Database::closeAll() is this:

public static function closeAll() {

	//closes ALL active instances (not just this one)

	global $db;

	foreach($db as $v) {

		$db[$v]->close(); unset($db[$v]);

	}
        }

Link to comment
Share on other sites

What does the first part of your post have to do with the second part?

 

 

class Database {

protected $_connection = null;
protected static $_instances = array();

protected function __clone() {}
protected function __construct(/* ... */) { /* ... */ }

public function close() {
	// ...

	$this->_connection = null;
}

public static function closeAll() {
	foreach (self::$_instances as $instance) $instance->close();
}

public static function instance($database) {
	if (!isset(self::$_instances[$database])) self::$_instances[$database] = new self(/* ... */);
	return self::$_instances[$database];
}

}

There. Something to get you started.

Link to comment
Share on other sites

Is it ok to do this?

class Two {

function anything() {
   classOne::anyMethod();
}

}

classOne should likely be an instance of an object with a well defined interface that Two understands. Static methods in general should be used very sparingly, if your using them allot, your likely not doing things the right way.

 

Firstly, your closeAll() method shouldn't be static. You require an instance if the Database class to use it, you may as well require the instance to close it.

 

Having closeAll() close connections not related to the current instance is a bad idea and goes completely against any OOP design principles, so does this use of the global keyword. Both of them completely break encapsulation.

Link to comment
Share on other sites

Would something like this be the right way to do it?

 

<?php
class DatabaseAccess extends mysqli {

public function __construct($dbName) {

	parent::__construct("etc. etc. etc.");

}

public function escape($val) {

	return parent::real_escape_string($val);

}

//and various others of course

}

class DatabaseControl  {

private $instances = array();

public function __construct() {}

public function instantiate($databaseName) {

	$this->instances[$databaseName] = new DatabaseAccess($databaseName);

}

public function closeAll() {

	//close all instances of Database
	foreach($this->instances as $db) {

		$instances[$db]->close;

	}

}

}

$db = new DatabaseControl();//do this once only per script

//create new connections to each of different databases
$db->instantiate("people");
$db->instantiate("products");

//close ALL instances that have been created
$db->closeAll();
?>

Link to comment
Share on other sites

No. You would have a completely different Database object connected to each different database. Multiple databases are a rarity, and besides, using your method you would need to pass the name of the database you wanted to work with along with every query.

 

1 Database object should represent 1 database.

Link to comment
Share on other sites

So should I be using requinix's example?

 

How would I fit that into what I already have?

 

I currently do DB access like this:

class DatabaseAccess extends mysqli {
   
   public function __construct($dbName) {
  
      parent::__construct("etc. etc. etc.");
   
   }
   
   public function escape($val) {
   
      return parent::real_escape_string($val);
      
   }
   
   //and various others of course

}
$db1 = new DatabaseAccess("people");
$db2 = new DatabaseAccess("products");

 

I am trying to get rid of the need to instantiate $db1, $db2 etc.

Link to comment
Share on other sites

I am trying to get rid of the need to instantiate $db1, $db2 etc.

There's going to be instantiation somewhere. If you're talking about having to create new ones in your regular code then use a singleton/multiton pattern - such as what I did in my code.

Database::instance("people")->query("whatever");

 

But now I'm wondering whether you actually need multiple connections. Very rarely is that the case, and it generally involves processing two different things at once.

So: why do you need "people" and a "products" connections?

Link to comment
Share on other sites

I definitely have the need for more than one database. This can't be changed.

 

People / products are examples.

 

Are you saying to use the connection to select db1, perform the query and then select db2 (same connection) and perform that query?

 

I'm sure there is a reason why I don't, but can't think of one now!

 

thorpe said "Multiple databases are a rarity", did he mean using more than one connection is a rarity?

Link to comment
Share on other sites

No, the db design isn't flawed. There are 3 databases - all are on the same server. I'm sure there are areas for improvement, but I'm happy to leave this as it is.

 

The key thing for me is the number of connections I'm creating.

 

Should I just be making one connection and selecting a different database rather than making as many connections during the script as number of databases I am dealing with?

 

Is this where I am going wrong?

 

(when I say 3 databases, I mean 3 x MySQL databases holding lots of tables (all controlled on PHPMyAdmin), I'm not talking about different database types)

Link to comment
Share on other sites

If all the databases are on one server, you should use one connection and simply switch databases.

 

I still think your database design sounds very suspect. Why do you think you need three different databases? How do you propose to execute join queries across these different databases?

Link to comment
Share on other sites

thorpe, thanks for your help (and others who have posted).

 

Also (forget the Database class for a second), if I find myself doing this (which you have mentioned isn't good):

<?php
class Two {

//lots of other stuff as well of course

public function whatever() {

	One::something();

}

}

$two = new Two();
?>

 

 

Should I really be doing this:

<?php
class Two {

private $instanceOfOne;

//lots of other stuff as well of course

public function __construct($one) {

	$this->instanceOfOne = $one;		

}

public function whatever() {

	$this->instanceOfOne->something();

}

}

$one = new One();
$two = new Two($one);
?>

 

If not, how else do I prevent having to use static calls (One::something).

Link to comment
Share on other sites

Those examples do not help me. I told you the other day when you first asked for critique of your database class that I thought the idea was way off track. I still stick to that.

 

I'm not sure I can be of more help here. The entire design is not something I would work with.

Link to comment
Share on other sites

I'm not talking about a database. What design? They're examples.

 

The question is overall in OOP. If I find mysef using a static call (because I don't have the instance available) should I pass the instance in?

 

So, how would I make the instance (of another class, say class B) available in the class I am working with (say class A)?

Link to comment
Share on other sites

So, how would I make the instance (of another class, say class B) available in the class I am working with (say class A)?

 

Pass it in via a method or constructor. In doing so however, you must insure that the object you are passing in implements an interface that the class being passed the object understands.

Link to comment
Share on other sites

How?

 

An example.

 

<?php

abstract class Foo
{
    abstract function bar();
    abstract function bob();
}

class A extends Foo
{
    public function boo()
    {
        echo "This is A->boo()";
    }

    public function bob()
    {
        echo "This is A->bob()";
    }
}

class B
{
    private $foo;
    public function __construct(Foo $obj)
    {
        $this->foo = $obj;
    }
}

 

Using my example above, class B can happily call $this->foo->boo() & $this->foo->bob() and is guaranteed that those methods will exist.

Link to comment
Share on other sites

So what is wrong with mine?

 

You made it sound as though mine was wrong.

 

All I wanted to know is how to call another class and avoid using so many static calls.

 

Your example is slightly better (and slightly more advanced than mine), but there's no need to make me think anything was wrong with mine fitting what I wanted it to do.

 

Thanks again for all your help.

Link to comment
Share on other sites

Would it not have been better to say something like this?

 

"Yes, your example does everything you asked for, however, it doesn't do xyz which is very important in circumstances such as abc. If you are developing only for yourself or are maintaing a small site then you can probably get away without some of the advanced things for now, but I really suggest looking into this very soon."

Link to comment
Share on other sites

No, you're being silly.

 

All you've done is used type hinting and added some empty functions in a parent class so as to ensure the method exists.

 

A bit like completing a jigsaw with one piece missing. I'd tell someone to add the missing piece, you'd imply that the whole jigsaw is rubbish and that they should start again.

 

That said, thanks for all your help.

Link to comment
Share on other sites

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.