What is the difference between setter methods and construct methods? - php

If I have a setter and getter methods below :
<?php
class Name{
protected $first ;
public function setNameType($value) {
$this->first = $value;
}
public function getNameType() {
return $this->first;
}
}
$name = new Name;
$name->setNameType("My Name");
echo $name->getNameType();
?>
and a construct method like this
<?php
class Name{
protected $first ;
public function __construct($value) {
$this->first = $value;
}
public function getNameType() {
return $this->first;
}
}
$name = new Name("My Name");
echo $name->getNameType();
?>
Can I use the two interchangeably at all times or is there situations where one will be most prefered over the other ?

There is also some great explaination about your question: http://www.potstuck.com/2009/01/08/php-dependency-injection/

Try this website. It explains all with examples.
http://ralphschindler.com/2012/03/09/php-constructor-best-practices-and-the-prototype-pattern

Generally you would use constructors to set values if your class cannot exist or doesn't make sense without the value. If the value is allowed to be changed, than add a setter. If it should never be changed after construction, then don't add a setter.

An example code:
class Book {
public function __construct() {
$registry = RegistrySingleton::getInstance();
$this->_database = $registry->database;
// or
global $databaseConnection;
$this->_database = $database;
}
}
class Book {
private $_databaseConnection;
public function __construct() { }
public function setDatabaseConnection($databaseConnection) {
$this->_databaseConnection = $databaseConnection;
}
}
$book = new Book();
$book->setDatabase($databaseConnection);
$book = new Book($databaseConnection, $configFile);
$book = new Book();
$book->setDatabase($databaseConnection);
$book->setConfigFile($configFile);
class Container {
public static $_database;
public static function makeBook() {
$book = new Book();
$book->setDatabase(self::$_database);
// more injection...
return $book;
}
}
And then:
$book = Container::makeBook();

Related

Switch visibility in php if parameter

I'm wondering if its possible to switch the visibility in PHP. Let me demonstrate:
class One {
function __construct($id){
if(is_numeric($id)){
//Test function becomes public instead of private.
}
}
private function test(){
//This is a private function but if $id is numeric this is a public function
}
}
Is such thing even possible?
I would use an abstract class with two implementing classes: One for numeric and one for non-numeric:
abstract class One {
static function generate($id) {
return is_numeric($id) ? new OneNumeric($id) : new OneNonNumeric($id);
}
private function __construct($id) {
$this->id = $id;
}
}
class OneNumeric extends One {
private function test() {
}
}
class OneNonNumeric extends One {
public function test() {
}
}
$numeric = One::generate(5);
$non_numeric = One::generate('not a number');
$non_numeric->test(); //works
$numeric->test(); //fatal error
It can be faked up to a point with magic methods:
<?php
class One {
private $test_is_public = false;
function __construct($id){
if(is_numeric($id)){
$this->test_is_public = true;
}
}
private function test(){
echo "test() was called\n";
}
public function __call($name, $arguments){
if( $name=='test' && $this->test_is_public ){
return $this->test();
}else{
throw new LogicException("Method $name() does not exist or is not public\n");
}
}
}
echo "Test should be public:\n";
$numeric = new One('123e20');
$numeric->test();
echo "Test should be private:\n";
$non_numeric = new One('foo');
$non_numeric->test();
I haven't thought about the side effects. Probably, it's only useful as mere proof of concept.

Can you instantiate an object inside another class?

Is it possible to declare an object inside another class? The following code keeps giving me an error nexpected 'new' (T_NEW) error.
Class class1{
public function doSomething(){
$var = 3;
return true;
}
}
Class class2{
public $class1 = new class1();
public function doSomethingElse(){
if($class1->doSomething() == true){
return 10;
}else{
return 13;
}
}
}
//$obj = new class2();
I don't really want want to pass in the object through a constructor, because it's used inside other classes, so I'd have to pass it through multiple times. Is there a better method?
Use the Constructor of your class to instantiate the other class.
Class class1
{
public function doSomething()
{
$var = 3;
return true;
}
}
Class class2
{
protected $class1 = null;
public function __construct()
{
$this->class1 = new class1();
}
public function doSomethingElse()
{
if ($this->class1->doSomething() == true) {
return 10;
} else {
return 13;
}
}
}
Yes, but you have to put the initialization in construction method.
Class class2{
public $class1;
  public function __construct() {
$this->class1 = new class1();
}
// ...
}
You can only initialize scalar values and arrays, use the constructor:
class Class2 {
public $class1;
public function __construct() {
$this->class1 = new Class1();
}
...
}

Extend a Singleton with PHP 5.2.X

I have this code running on PHP 5.2.6
class Singleton {
static private $instance = false;
private $id = false;
protected function __construct() {
$this->id = uniqid();
}
static public function instance() {
if (!self :: $instance) {
self :: $instance = new self();
}
return self :: $instance;
}
public function get_id() {
return $this->id;
}
}
class Chucknorris extends Singleton {
}
echo "php version = ".phpversion()."<br>";
$singleton = Singleton::instance();
echo get_class($singleton)."<br>";
echo "singleton id = ".$singleton->get_id()."<br>";
$chucknorris = Chucknorris::instance();
echo get_class($chucknorris)."<br>";
echo "chucknorris id = ".$chucknorris->get_id()."<br>";
Here's the output
php version = 5.2.6
Singleton
singleton id = 4ea7dca7d8f23
Singleton
chucknorris id = 4ea7dca7d8f23
When I ask for an instance of Chucknorris, I always get the Singleton one. I'd like to find out a way to extend the Singleton.
I know we can use get_called_class method to do it but it comes only with PHP 5.3. Is there anyway I can extend a Singleton without redefining the design pattern in the extended classes ?
Your best bet in PHP < 5.3 is to use a Singleton Factory:
class Singleton
{
private $id = false;
public function __construct() {
$this->id = uniqid();
}
public function get_id() {
return $this->id;
}
}
class SingletonFactory
{
private static $instance_array = array();
public static function getInstance($class_name)
{
if (!isset(self::$instance_array[$class_name]))
{
self::$instance_array[$class_name] = new $class_name();
}
return self::$instance_array[$class_name];
}
}
class Chucknorris extends Singleton {}
$singleton = SingletonFactory::getInstance('Singleton');
echo get_class($singleton)."<br>";
echo "singleton id = ".$singleton->get_id()."<br>";
$chucknorris = SingletonFactory::getInstance('Chucknorris');
echo get_class($chucknorris)."<br>";
echo "chucknorris id = ".$chucknorris->get_id()."<br>";
The only downside here is that your Singleton constructor is public.. so that's a basic violation of that pattern.
Update:
Here's a version that removes the public constructor (warning: this is getting into messy/hacky/poor design territory)
class Singleton
{
private $id = false;
public function __construct() {
$back = debug_backtrace(false);
if (!isset($back[1]['class']) || $back[1]['class'] != 'SingletonFactory')
{
throw new Exception('Consturctor not available, use SingletonFactory::getInstance("CLASSNAME")');
}
$this->id = uniqid();
}
public function get_id() {
return $this->id;
}
}
class SingletonFactory
{
private static $instance_array = array();
public static function getInstance($class_name)
{
if (!isset(self::$instance_array[$class_name]))
{
self::$instance_array[$class_name] = new $class_name($class_name);
}
return self::$instance_array[$class_name];
}
}
class Chucknorris extends Singleton {}
$singleton = SingletonFactory::getInstance('Singleton');
echo get_class($singleton)."<br>";
echo "singleton id = ".$singleton->get_id()."<br>";
$chucknorris = SingletonFactory::getInstance('Chucknorris');
echo get_class($chucknorris)."<br>";
echo "chucknorris id = ".$chucknorris->get_id()."<br>";
$badchuck = new Chucknorris(); // Exception!
Why don't you simulate the get_class_function if it doesn't exist with 5.3 PHP version ?
This code may answer your question.
if (!function_exists('get_called_class')) {
function get_called_class() {
$bt = debug_backtrace();
$lines = file($bt[1]['file']);
preg_match(
'/([a-zA-Z0-9\_]+)::'.$bt[1]['function'].'/',
$lines[$bt[1]['line']-1],
$matches
);
return $matches[1];
}
}
abstract class Singleton {
private $id = false;
protected function __construct() {
$this->id = uniqid();
}
static public function instance() {
static $instances = array();
$called_class_name = get_called_class();
if (!isset($instances[$called_class_name])) {
$instances[$called_class_name] = new $called_class_name();
}
return $instances[$called_class_name];
}
public function get_id() {
return $this->id;
}
}
class Chucknorris extends Singleton {}
class Brucelee extends Singleton {}
echo "php version = ".phpversion()."<br>";
$chucknorris = Chucknorris::instance();
echo get_class($chucknorris)."<br>";
echo "chucknorris id = ".$chucknorris->get_id()."<br>";
$brucelee = Brucelee::instance();
echo get_class($brucelee)."<br>";
echo "brucelee id = ".$brucelee->get_id()."<br>";
You can redefine just the getinstance method (and the instance itself) in Chucknorris to get an instance of it instead of the parent, but I'm not exactly sure what your end goal is. Just change the extending class to:
class Chucknorris extends Singleton {
static private $instance = false;
static public function instance()
{
if (!self :: $instance) {
self :: $instance = new self();
}
return self :: $instance;
}
}
Is this what you want? And if so - what is the reason you want it? I could think of a few, but would be glad if you share you goal.
Your code will most likely work if you move static private $instance = false; to the subclass and make it protected instead of private.
You also need to replace self:: with static:: so the static var is set in the subclass.
This requires PHP 5.3 - however, this shouldn't be a problem because PHP 5.2 reached end-of-life/support (that includes security updates!) as of january 2011!

Php Class - How can I make a Class know parent value

<?php
class FirstClass{
public static $second;
public static $result = 'not this =/';
public function __construct(){
$this->result = 'ok';
$this->second = new SecondClass();
}
public function show(){
echo $this->second->value;
}
}
class SecondClass extends FirstClass{
public $value;
public function __construct(){
$this->value = parent::$result; //Make it get "ok" here
}
}
$temp = new FirstClass();
$temp->show(); //It will show: "not this =/"
?>
How can I make it to print "ok"?
I mean, the SecondClass should know what FirstClass set as result, see?
Replace $this->result = 'ok'; with self::$result = 'ok'; in FirstClass constructor.
Btw, the code is terrible. You're mixing static and instance variables, and extend classes but don't use benefits extension provides.
you need to reference the static as self::$result in the first class.
Below should do what you want...
<?php
class FirstClass{
public static $second;
public static $result = 'not this =/';
public function __construct(){
self::$result = 'ok';
$this->second = new SecondClass();
}
public function show(){
echo $this->second->value;
}
}
class SecondClass extends FirstClass{
public $value;
public function __construct(){
$this->value = parent::$result; //Make it get "ok" here
}
}
$temp = new FirstClass();
$temp->show(); //It will show: "not this =/"
?>

Refactoring To Remove Static Methods Code Smell

I have the current basic structure for each domain object that I need to create:
class Model_Company extends LP_Model
{
protected static $_gatewayName = 'Model_Table_Company';
protected static $_gateway;
protected static $_class;
public static function init()
{
if(self::$_gateway == null)
{
self::$_gateway = new self::$_gatewayName();
self::$_class = get_class();
}
}
public static function get()
{
self::init();
$param = func_get_arg(0);
if($param instanceof Zend_Db_Table_Row_Abstract)
{
$row = $param;
}
elseif(is_numeric($param))
{
$row = self::$_gateway->find($param)->current();
}
return new self::$_class($row);
}
public static function getCollection()
{
self::init();
$param = func_get_arg(0);
if($param instanceof Zend_Db_Table_Rowset_Abstract)
{
$rowset = $param;
}
elseif(!$param)
{
$rowset = self::$_gateway->fetchAll();
}
$array = array ();
foreach ($rowset as $row)
{
$array[] = new self::$_class($row);
}
return $array;
}
}
I initially tried to refactor the static methods into the parent LP_Model class only to learn finally what "late static binding" means in the php world.
I'm just wondering if anyone has suggestions on how to refactor this code so that I don't have to redeclare the same three functions in every domain object that I create?
How about this:
<?php
abstract class Model_Abstract
{
protected $_gatewayName = null;
protected $_gateway = null;
protected function _init()
{
$this->_gateway = new $this->_gatewayName();
}
protected function __construct($row = null)
{
$this->_init();
if ($row) {
$this->_data = $row;
}
}
public static function getAbstract($class, $param)
{
$model = new $class();
if($param instanceof Zend_Db_Table_Row_Abstract)
{
$row = $param;
}
elseif(is_numeric($param))
{
$row = $model->_gateway->find($param)->current();
}
return new $class($row);
}
public static function getAbstractCollection($class, $param = null)
{
$model = new $class();
if($param instanceof Zend_Db_Table_Rowset_Abstract)
{
$rowset = $param;
}
elseif($param === null)
{
$rowset = $model->_gateway->fetchAll();
}
$array = array ();
foreach ($rowset as $row)
{
$array[] = new $class($row);
}
return $array;
}
abstract public static function get($param);
abstract public static function getCollection($param = null);
}
class Model_Company extends Model_Abstract
{
protected $_gatewayName = 'Model_Table_Company';
public static function get($param) {
return self::getAbstract(__CLASS__, $param);
}
public static function getCollection($param = null) {
return self::getAbstractCollection(__CLASS__, $param);
}
}
class Model_Table_Company extends Zend_Db_Table_Abstract
{
protected $_name = 'company';
}
$model = Model_Company::get(1);
print "Got an object of type ".get_class($model)."\n";
$models = Model_Company::getCollection();
print "Got ".count($models)." objects of type ".get_class($models[0])."\n";
?>
Unfortunately, to make the functions easy to call, you have to duplicate get() and getCollection() in each subclass. The other option is to call the function in the parent class:
$model = Model_Abstract::getAbstract('Model_Company', 1);
print "Got an object of type ".get_class($model)."\n";
$models = Model_Abstract::getAbstractCollection('Model_Company');
print "Got ".count($models)." objects of type ".get_class($models[0])."\n";
You can rename the base class and its function names if you want to go that route. But the point is that you must name the child class in one place or the other: either make a boilerplate function in the child class as in my first example, or else name the class in a string as in my second example.

Categories