I followed this link already before asking - Answer is in JAVA context and this for constructor in PHP .
Since I am starter, my implementation of my PHP code in OOP concepts, so I am really willing to know about the usage and benefits or when to use constructor in PHP abstract class.
Please provide an example in real world context to grab the concept better.
PS - Although I am following PHP Manuals to understand OOP concepts but I am finding it little bit hard to understand, any help with the links/blog to follow is really appreciable.
My Code -
<?php
abstract class grandClass
{
abstract function grandmethod();
function __construct()
{
echo "I am grandClass constructor";
}
}
abstract class parentClass extends grandClass
{
abstract function raiseFlag();
function grandmethod()
{
echo "This is grandmethod!!!","<br />";
}
public function getValue()
{
echo "Zero is the blackhole for the numbers!!","<br />";
}
}
class childClass extends parentClass
{
function raiseFlag()
{
echo "Peaceful thoughts!!","<br />";
}
}
$myobj = new childClass();
$myobj->raiseFlag();
$myobj->getValue();
$myobj->grandmethod();
Constructor in abstract class is the same as in concrete class. Use constructors when they are needed, for example, if you need to intialize some data or assign some resources.
I'll give you an example:
abstract class Db
{
protected $pdo;
public function __construct($pdo)
{
$this->pdo = $pdo;
}
abstract function select($table, $fields);
}
class Db_Mysql extends Db
{
public function select($table, $fields)
{
// Build MySQL specific select query
// then execute it with $this->pdo
}
}
class Db_Pgsql extends Db
{
public function select($table, $fields)
{
// Build PostgreSQL specific select query
// then execute it with $this->pdo
}
}
// Usage:
$db = new Db_Mysql($pdo);
$db->select('users', array('id', 'name'));
Related
Have a look at the following trait:
trait PrimaryModelRest {
use RestController;
protected $primaryModel;
public function __construct() {
$mc = $this->getPrimaryModelClass();
try {
$this->primaryModel = new $mc();
if(!($this->primaryModel instanceof Model)) {
throw new ClassNotFoundException("Primary Model fatal exception: The given Class is not an instance of Illuminate\Database\Eloquent\Model");
}
} catch (Exception $e) {
throw new WrongImplementationException("Primary Model Exception: Class not found.");
}
}
/**
* #return string: Classname of the primary model.
*/
public abstract function getPrimaryModelClass();
// various functions here
}
As you can see the trait makes sure that the using class holds a certain model instance and it implements certain methods. This works as long as the implementing class does not override the constructor.
So here is my question: I want to make sure that either the constructor is called or a better solution, such that I can instantiate this model on initialization.
Please make in answer which respects Multiple inheritance as well es Multi-Level inheritance.
I think you are trying to make the trait do a job it is not designed for.
Traits are not a form of multiple inheritance, but rather "horizontal reuse" - they're often described as "compiler-assisted copy-and-paste". As such, the job of a trait is to provide some code, so that you don't have to copy it into the class manually. The only relationship it has is with the class where the use statement occurs, where the code is "pasted". To aid in this role, it can make some basic requirements of that target class, but after that, the trait takes no part in inheritance.
In your example, you are concerned that a sub-class might try to access $primaryModel without running the constructor code which initialises it, and you are trying to use the trait to enforce that; but this is not actually the trait's responsibility.
The following definitions of class Sub are completely equivalent:
trait Test {
public function foo() {
echo 'Hello, World!';
}
}
class ParentWithTrait {
use Test;
}
class Sub inherits ParentWithTrait {
}
vs:
class ParentWithMethodDefinition {
public function foo() {
echo 'Hello, World!';
}
}
class Sub inherits ParentWithMethodDefinition {
}
In either case, class Sub could have its own definition of foo(), and by-pass the logic you'd written in the parent class.
The only contract that can prevent that is the final keyword, which in your case would mean marking your constructor as final. You can then provide an extension point that can be overridden for sub-classes to add their own initialisation:
class Base {
final public function __construct() {
important_things(); // Always run this!
$this->onConstruct(); // Extension point
}
protected function onConstruct() {
// empty default definition
}
}
class Sub {
protected function onConstruct() {
stuff_for_sub(); // Runs after mandatory important_things()
}
}
A trait can also mark its constructor as final, but this is part of the code being pasted, not a requirement on the class using the trait. You could actually use a trait with a constructor, but then write a new constructor as well, and it would mask the trait's version completely:
trait Test {
final public function __construct() {
echo "Trait Constructor";
}
}
class Noisy {
use Test;
}
class Silent {
use Test;
public function __construct() {
// Nothing
}
}
As far as the trait is concerned, this is like buying a bottle of beer and pouring it down the sink: you asked for its code and didn't use it, but that's your problem.
Crucially, though, you can also alias the methods of the trait, creating a new method with the same code but a different name and/or a different visibility. This means you can mix in code from traits which declare constructors, and use that code in a more complex constructor, or somewhere else in the class altogether.
The target class might also use the "final + hook" pattern:
trait TestOne {
final public function __construct() {
echo "Trait TestOne Constructor\n";
}
}
trait TestTwo {
final public function __construct() {
echo "Trait TestTwo Constructor\n";
}
}
class Mixed {
final public function __construct() {
echo "Beginning\n";
$this->testOneConstructor();
echo "Middle\n";
$this->testTwoConstructor();
echo "After Traits\n";
$this->onConstruct();
echo "After Sub-Class Hook\n";
}
use TestOne { __construct as private testOneConstructor; }
use TestTwo { __construct as private testTwoConstructor; }
protected function onConstruct() {
echo "Default hook\n";
}
}
class ChildOfMixed extends Mixed {
protected function onConstruct() {
echo "Child hook\n";
}
}
The trait hasn't forced the Mixed class to implement this pattern, but it has enabled it, in keeping with its purpose of facilitating code reuse.
Interestingly, the below code doesn't work, because the as keyword adds an alias, rather than renaming the normal method, so this ends up trying to override the final constructor from Mixed:
class ChildOfMixed extends Mixed {
use TestTwo { __construct as private testTwoConstructor; }
protected function onConstruct() {
$this->testTwoConstructor();
echo "Child hook\n";
}
}
Use a base class, this will let you handle the trait as a parent.
<?php
trait StorageTrait
{
public function __construct()
{
echo "Storage Trait";
}
}
class StorageAttempt
{
use StorageTrait;
public function __construct()
{
parent::__construct();
echo " - Storage Attempt";
}
}
abstract class StorageBase
{
use StorageTrait;
}
class MyStorage extends StorageBase
{
public function __construct()
{
parent::__construct();
echo ' - My Storage';
}
}
new StorageAttempt(); // won't work - will trigger error
new MyStorage(); // will display "Storage Trait - My Storage"
Also if you are using traits you can also work with properties and getters & setters.
Example: A Storage trait involves that a Storage Engine will be used. You can add the storageEngine property and its getters and setters. (with or without Type Hinting)
interface StorageEngineInterface{}
trait StorageTrait
{
/**
* #var StorageEngineInterface
*/
protected $storageEngine;
/**
* #return StorageEngineInterface
*/
public function getStorageEngine(): StorageEngineInterface
{
return $this->storageEngine;
}
/**
* #param StorageEngineInterface $storageEngine
*/
public function setStorageEngine(StorageEngineInterface $storageEngine)
{
$this->storageEngine = $storageEngine;
return $this;
}
}
Note: this is just an explanation so you can better understand how Traits work
UPDATE
To avoid conflict you can use aliases for trait methods. This way you can use both constructors (from trait and from extended class) you can do the following
class DifferentStorage
{
public function __construct()
{
echo ' diff ';
}
}
class MyDifferentStorage extends DifferentStorage
{
use StorageTrait {
StorageTrait::__construct as otherConstructor;
}
public function __construct()
{
parent::__construct();
self::otherConstructor();
}
}
You could use the interface injection pattern: implement an interface iPrimaryModelRest into the same class that uses the trait PrimaryModelRest:
interface iPrimaryModelRest {
public function init();
public abstract function getPrimaryModelClass();
}
The class that uses the trait woud look like this:
class cMyClass implements iPrimaryModelRest {
use PrimaryModelRest;
}
Then, whenever the class is instantiated (not only autoloaded) you could call a special factory-like initialisation function like this:
class cMyApp {
public function start() {
/** #var cMyClass $oClass */ // enlighten IDE
$oClass = $this->init(new cMyClass);
}
public function init($oClass) {
if ($oClass instanceof iPrimaryModelRest) {$oClass->init();}
if ($oClass instanceof whateverinterface) {
// pass optional stuff, like database connection
}
}
}
The interface is used to determine the capabilities of the class, and sets data/runs corresponding functions. If I'm not mistaken then this pattern is called a Service Locator.
I needed a trait for database connection. To avoid using the __construct in a trait, I've used a magic getter instead:
trait WithDatabaseConnection
{
public function __get(string $name)
{
if ($name === 'pdo') {
return App::make(\PDO::class);
}
trigger_error("Property $name does not exist.");
return null;
}
}
class Foo {
use WithDatabaseConnection;
public function save() {
$this->pdo->query('...');
}
}
I'm new to object oriented php. And if there are no functions in the method testing() in the HumanClass, should i declare them as abstract?
<?php
class HumanClass
{
private $legs;
private $hands;
public function __construct($legs, $hands)
{
$this->legs = $legs;
$this->hands = $hands;
}
public function testing()
{
}
}
class StudentClass extends HumanClass
{
private $books;
public function __construct($legs, $hands, $books)
{
parent::__construct($legs, $hands);
$this->books = $books;
}
public function testing()
{
echo "StudentClass called.";
}
}
function callClass(HumanClass $c)
{
$c->testing();
}
$example = new StudentClass(4, 2, 1);
callClass($a);
?>
Is it possible to have something like this?
echo $a->testing();
instead of having another method to call testing().
Given the code that you give, it's far from clear what the testing() function is supposed to do other than just exist for you to try things. The answer to that will also determine whether the versions in the baseclass should remain there as empty function.
There are other options, too, e.g. that the derived class first invokes the baseclass (extending), or that the baseclass doesn't contain an abstract or concrete such function but only the derived one does. Which to choose is up to the informed programmer to decide.
My question is rather simple and after checking a few bits and bobs on here I feel its best to ask a new question.
Lets say I have 2 classes
class FirstClass {
function test() {
return "info";
}
}
class SecondClass {
function test() {
return "info";
}
}
Then I have my mysqli object
$mysqli = new mysqli(host, user, password, db);
What do i need to do to be able to use the mysqli object inside the functions inside the classes.
This is my 2 thoughts so far although I haven't placed it on a site for testing yet.
class FirstClass {
global $mysqli;
function test() {
$mysqli->query("some query");
return "info";
}
}
or
class FirstClass {
function test() {
global $mysqli;
$mysqli->query("some query");
return "info";
}
}
I am pretty sure I can setup a construct if need be but I just need to know which way is the best way/only way to share the mysqli object.
Thanks
EDIT:
So I have done a hell of a load of learning and now have a lot more experience with passing info in and out.
Here is a latest working example type that I use.
namespace Page;
use mysqli;
class edit extends details{
protected $db;
//this function is actually in the details class but there is no point in demoing 2 classes
function __construct(mysqli $con){
$this->db = $con;
}
}
To expand what Kneel told you in comments and to counter the other answer
class foo {
function __construct($mysqli){
$this->mysqli = $mysqli;
}
function test() {
return $this->mysqli->query("some query");
}
}
is what it have to be.
You should create a mysqli instance somewhere outside the class and then pass it in coustructor.
You could use __construct() to initialize your MYSQLi. You can then access it around your class with $this.
class FirstClass {
public function __construct(){
$this->mysqli = new mysqli("host", "user", "password", "db");
}
function test() {
$this->mysqli->query("some query");
return "info";
}
}
If you wanted to use it in your second class too, you could construct it in the same way or extend your first class.
class SecondClass extends FirstClass {
public function __construct(){
parent::__construct();
}
function test() {
return "info";
}
}
I have an abstract class that extends classes to provide a basic orm function. All the functions it provides are protected to the class so it can decide what fields are made publicly available to outside objects. But recently, I have started working with some smaller data classes that do not require such complexity, and would benefit from having the orm editing functions publicly available and no special functions.
As the naming convention for the functions is sufficient and compact, is there a way to change the existing functions to public (without needing the same class, or an interim extends), or would I have to use the new traits feature of php to add an existing class, which contains public versions of the functions that act as an abstraction layer for the internal protected functions?
EDIT:
For the traits method, I was thinking that it would help like this:
abstract class ORMClass {
public function __construct($pk) {}
protected function __get($k) {}
protected function __set($k,$v) {}
protected function save() {}
}
trait publicORM {
public function __get($k) { return parent::__get($k); }
public function __set($k,$v) { return parent::__set($k,$v); }
public function save() { return parent::save(); }
}
class myOrm extends ORMClass {
use publicORM;
protected static $table = 'myTable';
}
so then I could use myOrm like:
$myOrm = new myOrm(1);
$myOrm->foo = 'alice'
echo $myOrm->bar;
$myOrm->save();
without needing the:
public function __get($k) { return parent::__get($k); }
public function __set($k,$v) { return parent::__set($k,$v); }
public function save() { return parent::save(); }
to be listed in the class myOrm
Since this was never answered properly, I'm adding Charles answer.
This can be done using PHP's Reflection library, built in to PHP since version 5. This particular method is fairly hacky:
<?php
abstract class BaseClass {
protected function testMe() {
echo 'I WORK!';
}
}
class ConcreteClass extends BaseClass {
// Class Code
}
$method = new ReflectionMethod('BaseClass', 'testMe');
$method->setAccessible(true);
$method->invoke(new ConcreteClass()); // Prints 'I WORK!'
And here is the better method using an interim abstract class that extends the base class but uses public methods:
<?php
abstract class BaseClass {
protected function testMe() {
echo 'I WORK!';
}
}
abstract class PublicBaseClass extends BaseClass {
public function testMe() {
parent::testMe();
}
}
class ConcreteClass extends PublicBaseClass {
// Class Code
}
$obj = new ConcreteClass();
$obj->testMe();
So currently my class DATABASE uses a singleton for a connection and is called in the constructor of my class SQL. I have 4 other classes that extend class SQL for access to its methods. The problem is, the children instantiate each other in some cases so I'm afraid I'm creating multiple class SQL objects because they call their parent constructor by default, aka class SQL. I read about dependency injection, but no clear how to implement it in my situation so this is what I was thinking.
Have all classes extend class DATABASE and make class SQL methods static.
But then I would have to call the singleton connection in class DATABASE, on its own class as so.
class DATABASE {
function __construct() {
self::getInstance();
/// or DATABASE::getInstance ( im not quite positive which way )
}
public static function getInstance() {
if (self::$instance == false) {
self::$instance = new DATABASEMANAGER();
}
return self::$instance;
}
}
I figure this way, since all classes extend class DATABASE, and instantiate each other, I know I am not creating multiple objects.
I hope this makes sense and I can elaborate more if you need me to, but does this make since as an approach to my problem?
I guess you building your class other way around, this approach is more consistent in my opinion.
class DATABASE extends DATABASEMANAGER
{
static $instance;
private function __construct()
{
parent::__construct();
}
public static function getInstance()
{
if (empty(self::$instance))
{
self::$instance = new self();
}
return self::$instance;
}
}
Usage:
class Blog
{
public function __construct()
{
$this->database = DATABASE::getInstance();
}
public function getRecord($id)
{
$result = $this->database->query("SELECT * FROM blog WHERE id='{$id}'");
//or
$result = DATABASE::getInstance()->query("SELECT * FROM blog WHERE id='{$id}'");
//other actions...
}
}