$this->a->b->c->d calling methods from a superclass in php - php

Hello i want to make something on classes
i want to do a super class which one is my all class is extended on it
____ database class
/
chesterx _/______ member class
\
\_____ another class
i want to call the method that is in the database class like this
$this->database->smtelse();
class Hello extends Chesterx{
public function ornekFunc(){
$this->database->getQuery('popularNews');
$this->member->lastRegistered();
}
}
and i want to call a method with its parent class name when i extend my super class to any class

I'm not quite sure what you mean by your last sentence but this is perfectly valid:
class Chesterx{
public $database, $member;
public function __construct(){
$this->database = new database; //Whatever you use to create a database
$this->member = new member;
}
}

Consider the Singleton pattern - it usually fits better for database interactions. http://en.wikipedia.org/wiki/Singleton_pattern.

you could also consider using methods to get the sub-Objects
The advantage would be that the objecs are not initialized until they are need it, and also provides a much more loosely coupled code that lets you change the way the database is initialized more easy.
class Chesterx{
public $database, $member;
public function getDatabase() {
if (!$this->database ) {
$this->database = new database; //Whatever you use to create a database
}
return $this->database;
}
public function getMember() {
if (!$this->member) {
$this->member = new member;
}
return $this->member;
}
}

Related

How to instance a parent class without using DI

I am trying out a MVC concept where the main model for a database stems or trees off other models. I wanted to have a main database sort of model which does the connecting and queries. Then, other models are built to support the controller. Ie, a product model can be extended off the main database model to then query rather than using dependency injection.
My current ideology and attempt looks like this for the main database model:
namespace Portfolio\Application;
abstract class DriverModel {
private static $driver;
private $entity;
private function __construct() {
// Connection to the PDO will be done in here
}
private function __clone() {}
public static function getInstance() {
if(self::$driver)
return self::$driver;
self::$driver = new self();
return self::$driver;
}
protected function q($sql, $values = []) {
$stmt = $this->entity->Prepare($sql);
$stmt->execute($values);
return $stmt;
}
}
Then my example profile controller would look something like this (having the methods to use the main database to run queries):
class ProfileModel extends DriverModel {
public function doSomeQ() {
$this->q('SELECT fname FROM users WHERE id = ?', [(int)1]);
}
}
However, When I execute this line of code:
print_r(ProfileModel::getInstance()->doSomeQ());
I am left with this error: (which makes sense.)
Uncaught Error: Cannot instantiate abstract class.
I then remove the abstract attribute from the class (class DriverModel) but now, the instance I am receiving is the instance from the parent class meaning if I do a print_r() on the getInstance() method to the ProfileModel, there is no doSomeQ() method.
Any help on achieving this methodology would be helpful.
You have to use get_called_class() method instead of new self();
http://php.net/manual/en/function.get-called-class.php
Attached you can find sample who show your expected behaviour
class Main {
public static function getInstance() {
$class = get_called_class();
return new $class();
}
}
class Foo extends Main{
}
var_dump(Foo::getInstance()); // Output Foo object

PHP Static v Singleton class - ConnectionFactory explained

I'm new to this level of PHP programming and I've been reading a post about singleton and static classes. I'm in the process of writing a class that would facilitate my DB connections.
I came across the following code by Jon Raphaelson (here) :
class ConnectionFactory
{
private static $factory;
public static function getFactory()
{
if (!self::$factory)
self::$factory = new ConnectionFactory(...);
return self::$factory;
}
private $db;
public function getConnection() {
if (!$this->db) // this line was modified due to comment
$this->db = new PDO(...); // this line was modified due to comment
return $db;
}
}
function getSomething()
{
$conn = ConnectionFactory::getFactory()->getConnection();
.
.
.
}
It seemed like I had found what I was looking for, however I have a few questions about it.
self::$factory = new ConnectionFactory(...); - I don't see a constructor in this class. Do I just create this constructor and pass in the db details ('dbname', 'user', 'pass', etc)?
the getSomething() function, I'm assuming that the intent was to put all of the actual functions that would retrieve data within the ConnectionFactory class - and this is the reason for this function being in this class. Otherwise, I would have expected this function to be within another class. [edit] SKIP THIS QUESTION, I didn't see the one bracket.
What happens when two users are logged into the site and are requesting the DB connection (both are doing updates, etc)? Will it be an issue that this is a singleton?
Thanks!
This is mostly to expand on my comments under the question...
The better "singleton" pattern would be this:
class ConnectionFactory {
protected static $connection;
public function getConnection() {
if (!self::$connection) {
self::$connection = new PDO(...);
}
return self::$connection;
}
}
The users of this factory should expect an instance of it, not call it themselves:
class Foo {
protected $connectionFactory;
public function __construct(ConnectionFactory $factory) {
$this->connectionFactory = $factory;
}
public function somethingThatNeedsAConnection() {
$connection = $this->connectionFactory->getConnection();
...
}
}
$foo = new Foo(new ConnectionFactory);
This allows Foo to get a connection itself when needed, but also allows you to inject some alternative connection into Foo, for example for testing purposes.
As a convenience measure and to cut down on instantiation complexity, this pattern is also good:
class Foo {
protected $connectionFactory;
public function __construct(ConnectionFactory $factory = null) {
if (!$factory) {
$factory = new ConnectionFactory;
}
$this->connectionFactory = $factory;
}
...
}
This still allows the dependency to be injected and overridden, but it doesn't require you to inject a factory every time you instantiate Foo.
The factory is a singleton because you're not want more than one factory.
You don't need a constructor, you can setup whatever state you need for the factory the getFactory() method. The getFactory() function doesn't get a connection, so don't do any connection related setup here, but not the connection object itself. Factories 'build instances' of classes for you to use, so you'd use the getConnection() method to set the state and construct the connection object the factory is supposed to generate.
getSomething() isn't a method in the ConnectionFactory class, it's just a example of using the factory class to get a factory, then get a connection.
I personally hate method chaining in PHP. What's really happening in getSomething() is:
function getSomething()
{
$factory = ConnectionFactory::getFactory();
$conn = $factory->getConnection();
.
.
.
}
A class doesn't need an explicit constructor in order to be instantiated with new ClassName(). However, if the class is supposed to be a singleton (and it looks like it in this case), the entire point of the pattern is making such instantiations impossible from outside of the class which is why I believe there should be a constructor declared with private keyword.
The get getSomething() is a "standalone" function with an example of using your class.
No. Multiple users use multiple instances of PHP processing your script and nothing is shared among them.

PHP Singleton extending class

I am new to OOP (PHP) and just met the design pattern - singleton.
I have found a DB class which uses mysqli (singleton class). I have added some custom methods to it (insert_id(), query(), fetch_result(), etc).
Then I created a new class called UserTools and I want to extend the database class to use the methods I've created previously (query(), fetch_result(), etc).
But I get this error:
Fatal error: Call to private Database::__construct() from invalid context in (...)
when I try to create instance of the new class (User Tools).
What should I do? Is it a right structure?
There are several way to achieve what you want.
One would be :
class UserTools {
private $db;
function __construct() {
$this->db = Database::db_connect();
}
function login() { /* ... */}
}
Although it would be better to directly pass the database instance to the constructor like this :
class UserTools {
private $db;
function __construct($db) {
$this->db = $db;
}
function login() { /* ... */}
}
// Usage
$userTools = new UserTools(Database::db_connect());
If you're really lazy you could just modify your database class and make the constructor public :
class Database {
/* ... */
public function __construct(){/* ... */}
/* ... */
}
class UserTools extends Database {/* ... */}
But I really discourage you to use the latter one. It's really bad code and it doesn't make sense in a logical point of view. Your UserTools class use a database instance. It is not a database.
It is my understanding that only protected and public methods and variables are inherited through extension, not private ones. Try changing your methods/variables from private to protected. public ones are visible to all.
For more information, See: PHP Visibility (Manual)
Edit
Understand the Singleton pattern. It is called 'singleton' because only one instance of a class is expected. Because of this, most classes implementing the singleton pattern define the constructor as private to restrict you from creating more than one.
To create an instance of a singleton, most classes define some kind of getInstance static method, which is public. This public method calls the private constructor, which probably sets flags indiciating that the class has been instantiated in order to prevent further attempts to instantiate the class. The getInstance method returns the results of calling the constructor, essentially the instance of the class.
You could write something like
class UserTools extends DB {
....
}
A quick example on inheritance in PHP:
class A {
public $a;
public function set_a($new_a) { $this->a = $new_a; return $this; }
public function get_a() { return $this->a; }
}
class B extends A {
public $b;
public function set_b($new_b) { $this->b = $new_b; return $this; }
public function get_b() { return $this->b; }
}
$objb = new B();
$objb->set_a("Some Value")->get_a(); //Some Value
The singleton pattern in most cases prevents instantiating the Singleton class by defining the constructor as private (ie private function __construct()).
So if you try to instantiate either your custom class or the original one that you're extending you will get the message above. You should either create a different class or define and use your function as static (eg public static function query($sql, $dbconnection)).
See http://php.net/manual/en/language.oop5.patterns.php

Properly using classes in other classes in php?

Should have asked someone this a long time ago.
What is the best way to use other classes within another class?
For instance, lets say I have an application class:
class Application
{
public function displayVar() {
echo 'hello world';
}
}
and a database class
class Database
{
// connects to db on construct
public function query() {
// queries db
}
}
now, i want to add a function to my application class that uses a function from the db class
class Application
{
public function displayVar() {
echo 'hello world';
}
public function getVar() {
global $db;
$sql = foo;
$db->query($sql);
}
}
so then I have
$db = new Database();
$app = new Application();
$app->getVar('var');
Is there a better way of doing this? Really what I am looking for is the standard way of doing it, not another way of rigging it.
There are a couple of ways of doing that. Global variables is certainly one way and the most looked down upon too. You can create a Singleton and all other classes that need database access would call upon this singleton.
final class Database {
private static $connection;
public static function getInstance() {
if(self::$connection == NULL) {
self::$connection = // init your database connection
}
return self::$connection;
}
}
And use this database connection object in whatever class needs it.
class Application {
public function displayVar() {
echo 'hello world';
}
public function getVar() {
$db = Database::getInstance();
$sql = foo;
$db->query($sql);
}
}
This is all well for a start and a great step beyond using global variables, but you can do better with Dependency Injection. Dependency Injection is a simple concept that if a class has any external dependencies, such as the database connection in your example, you explicitly pass those to the needy class in its constructor or a method. So the new code would look something like Jonathan's solution. A major advantage of using dependency injection is in unit testing, where you can easily replace this actual database object with a mock object and pass it to whoever needs it.
class Application {
private $db;
public function __construct(Database $db) {
$this->db = $db;
}
public function displayVar() {
echo 'hello world';
}
public function getVar() {
$sql = foo;
$this->db->query($sql);
}
}
For smaller projects, you can easily do it yourself. For large projects, there are various DI frameworks available for PHP
$db could be a property of your Application class. Any reference to it from within an instance of Application would be done via $this - $this->db
class Application {
private $db = null;
public function setDB($name) {
$this->db = new Database($name);
}
}
Include the class file (or set up autoinclude) in each PHP file that needs the class in question. Then instantiate it as needed.
If you need to have a "common" instance of an object, you can look at the Singleton and Factory patterns:
Singleton Pattern
Factory Pattern

In a PHP5 class, when does a private constructor get called?

Let's say I'm writing a PHP (>= 5.0) class that's meant to be a singleton. All of the docs I've read say to make the class constructor private so the class can't be directly instantiated.
So if I have something like this:
class SillyDB
{
private function __construct()
{
}
public static function getConnection()
{
}
}
Are there any cases where __construct() is called other than if I'm doing a
new SillyDB()
call inside the class itself?
And why am I allowed to instantiate SillyDB from inside itself at all?
__construct() would only be called if you called it from within a method for the class containing the private constructor. So for your Singleton, you might have a method like so:
class DBConnection
{
private static $Connection = null;
public static function getConnection()
{
if(!isset(self::$Connection))
{
self::$Connection = new DBConnection();
}
return self::$Connection;
}
private function __construct()
{
}
}
$dbConnection = DBConnection::getConnection();
The reason you are able/would want to instantiate the class from within itself is so that you can check to make sure that only one instance exists at any given time. This is the whole point of a Singleton, after all. Using a Singleton for a database connection ensures that your application is not making a ton of DB connections at a time.
Edit: Added $, as suggested by #emanuele-del-grande

Categories