I took good care to create this class but I am not sure what is wrong with it. The code runs perfectly if I don't have any content inside,
class TemplateOne{
}
But once I run this code it breaks,
<?php
class TemplateOne {
//Properties
protected $_bgColor;
protected $_logoImagePath;
protected $_headerText;
protected $_leftContentHeader;
protected $_rightContentHeader;
protected $_leftContentBody;
protected $_rightContentBody;
protected $_footer;
protected $_mediaIframe;
protected $_mediaHeight = '';
protected $_mediaWidth = '';
//DB communication
public $DB;
//Constructor
public function __construct(){
//Connect database in construct and close connection in destruct
$config = array();
$config['host'] = 'localhost';
$config['user'] = 'root';
$config['pass'] = 'root';
$config['database'] = 'fanpage_application';
$this->DB = new DB($config);
//init variables
populateDataFromDataBase();
}
//Functions
public function populateDataFromDataBase() {
//Get bgcolor
$this->DB->("SELECT backgroundimage FROM template_style_data WHERE styleid='#list_level'");
$data = $this->DB->Get();
foreach($data as $key => $value)
{
echo $value['backgroundimage'];
}
}
//Getters
public function getBgColor()
{
return $this->_bgColor;
}
public function getLogoImagePath()
{
return $this->_logoImagePath;
}
public function getHeaderText()
{
return $this->_headerText;
}
public function getLeftContentHeader()
{
return $this->_leftContentHeader;
}
public function getRightContentHeader()
{
return $this->_rightContentHeader;
}
public function getLeftContentBody()
{
return $this->_leftContentBody;
}
public function getRightContentBody()
{
return $this->_rightContentBody;
}
public function getFooter()
{
return $this->_footer;
}
public function getMediaIframe()
{
return $this->_mediaIframe;
}
//Setters
public function setBgColor($bgColor)
{
$this->_bgColor = $bgColor;
}
public function setLogoImagePath($logoImagePath)
{
$this->_logoImagePath = $logoImagePath;
}
public function setHeaderText($headerText)
{
$this->_headerText = $headerText;
}
public function setLeftContentHeader($leftContentHeader)
{
$this->_leftContentHeader = $leftContentHeader;
}
public function setRightContentHeader($rightContentHeader)
{
$this->_rightContentHeader = $rightContentHeader;
}
public function setLeftContentBody($leftContentHeader)
{
$this->_leftContentBody = $leftContentHeader;
}
public function setRightContentBody($rightContentBody)
{
$this->_rightContentBody = $rightContentBody;
}
public function setFooter($footer)
{
$this->_footer = $footer;
}
public function setMediaIframe($mediaIframe)
{
$this->_mediaIframe = $mediaIframe;
}
}
?>
You are missing $this-> from your call to populateDataFromDataBase.
Where is the DB class coming from? You may have to include the correct class definition file if it is not already.
$this->DB = new DB($config);
The following is not legal syntax. You will need to actually call a function by name.
$this->DB->("SELECT backgroundimage FROM template_style_data WHERE styleid='#list_level'");
Unless you have another function in the global scope named populateDataFromDataBase which is what you want to call, you will need to add $this-> before you try to call it in your constructor.
populateDataFromDataBase();
Here is your error:
$this->DB->("SELECT backgroundimage FROM template_style_data WHERE styleid='#list_level'");
This is not valid syntax, you need to call a method after $this->DB.
As far as I'm concerned there is only one possible answer: check your PHP errors http://php.net/manual/en/function.error-reporting.php
at least (in devevlopment only, don't show errors in production):
ini_set('display_errors', 1);
error_reporting(-1);
Related
I'm writing PHPUnit Test with Mockery, (PHP v5.6.32, PHPUnit 3.7.21, Mockery dev-master) and found something which I can't understand about using Mockery::mock and Mockery::namedMocks.
My code is below, and the questions are:
Am I correct to use in LegendTest.php the Mockery::namedMock() instead of Mockery::mock() for SignalsCollection object?
Regarding to documentation about namedMock, I expect that frist argument is the Class name (SignalsCollection) and the second argument should be the extends statement (\ArrayObject) - but in my case I'm getting an error: Mockery\Exception\BadMethodCallException : Received Charts\SignalsCollection::getIterator(), but no expectations were specified, so I'm giving only one argument and this works fine. Why? What am I doing wrong? I'm confused.
Did I missed something in this test case or should I do something different to make tests better?
Signal.php:
class Signal
{
protected $id = 0;
protected $colName = '';
protected $tableName = '';
public function getId()
{
return $this->id;
}
public function setColName($colName)
{
$this->colName = $colName;
return $this;
}
public function setTableName($tableName)
{
$this->tableName = $tableName;
return $this;
}
}
SignalsCollection.php:
class SignalsCollection extends \ArrayObject
{
}
Legend.php
class Legend
{
protected $signalsCollection = null;
protected $graphModel = null;
public function __construct(SignalsCollection $signalsCollection, GraphModel $graphModel)
{
$this->signalsCollection = $signalsCollection;
$this->graphModel = $graphModel;
}
public function getSignalsCollection()
{
return $this->signalsCollection;
}
public function removeSignal(Signal $signal)
{
foreach ($this->signalsCollection as $key => $item) {
if ($item->getId() === $signal->getId()) {
$this->signalsCollection->offsetUnset($key);
break;
}
}
}
}
LegendTest.php:
class LegendTest extends \PHPUnit_Framework_TestCase
{
protected function tearDown()
{
parent::tearDown();
Mockery::close();
}
public function testRemoveSignal()
{
$testSignal = Mockery::mock('\Charts\Signal')
->shouldReceive('setColName', 'setTableName')
->andReturn(Mockery::self())
->mock();
$testSignal
->setColName('testColumnName')
->setTableName('testTableName');
$testSignalSecond = Mockery::mock('\Charts\Signal')
->shouldReceive('setId', 'setColName', 'setTableName')
->andReturn(Mockery::self())
->mock();
$testSignalSecond
->setId(1)
->setColName('testColumnName')
->setTableName('testTableName');
$signalsCollection = Mockery::namedMock('\Charts\SignalsCollection')
->shouldReceive('append', 'offsetUnset')
->andReturn(Mockery::self())
->mock();
$signalsCollection
->append($testSignal)
->append($testSignalSecond);
$legend = new Legend($signalsCollection, Mockery::mock('\Charts\GraphModel'));
$this->assertEquals($signalsCollection, $legend->getSignalsCollection());
$legend->removeSignal($testSignalSecond);
$signalsCollection->offsetUnset(1);
$this->assertEquals( $signalsCollection, $legend->getSignalsCollection() );
}
}
How would one rewrite the following ...
class crunch {
private $funcs = [];
public function set($name, $function) {
$this->funcs[$name] = $function;
}
public function call($function, $data=false) {
if (isset($this->funcs[$function]) && is_callable($this->funcs[$function])) {
return $this->funcs[$function]($data);
}
}
}
$db = 'dbhandle';
$crunch = new crunch();
$crunch->set('myfunction', function($data) {
global $db;
echo 'db = '. $db .'<br>'. json_encode( $data );
});
$crunch->call('myfunction', [123,'asd']);
... which correctly outputs ...
db = dbhandle
[123,"asd"]
... to remove the ugly global requirement when using frequently used variables/handles within dynamically added functions?
Normally, I'd define the global on construction as follows, but this understandably fails with the fatal error Uncaught Error: Using $this when not in object context ...
class crunch {
private $db;
private $funcs = [];
public function __construct($db) {
$this->db = $db;
}
public function set($name, $function) {
$this->funcs[$name] = $function;
}
public function call($function, $data=false) {
if (isset($this->funcs[$function]) && is_callable($this->funcs[$function])) {
return $this->funcs[$function]($data);
}
}
}
$db = 'dbhandle';
$crunch = new crunch($db);
$crunch->set('myfunction', function($data) {
echo 'db = '. $this->db .'<br>'. json_encode( $data );
});
$crunch->call('myfunction', [123,'asd']);
What's the cleanest way to accomplish the goal?
EDIT: As #Rajdeep points out, I could pass $db within the $crunch->set() function. But I'd like to avoid this, since each dynamic function could reference anywhere from 0-5 of these private variables, and it would be inelegant to have to call all 5 with every $crunch->set().
Instead of creating a private instance variable $db, you could simply pass this variable to the call() method. Your code should be like this:
class crunch {
private $funcs = [];
public function set($name, $function) {
$this->funcs[$name] = $function;
}
public function call($function, $data=false, $db) {
if (isset($this->funcs[$function]) && is_callable($this->funcs[$function])) {
return $this->funcs[$function]($data, $db);
}
}
}
$db = 'dbhandle';
$crunch = new crunch();
$crunch->set('myfunction', function($data, $db){
echo 'db = '. $db .'<br>'. json_encode( $data );
});
$crunch->call('myfunction', [123,'asd'], $db);
Output:
db = dbhandle
[123,"asd"]
Update(1):
In case you want to access $db as instance variable only, the solution would be like this:
class crunch {
public $db;
private $funcs = [];
public function __construct($db) {
$this->db = $db;
}
public function set($name, $function) {
$this->funcs[$name] = $function;
}
public function call($function, $data=false) {
if (isset($this->funcs[$function]) && is_callable($this->funcs[$function])) {
return $this->funcs[$function]($this, $data);
}
}
}
$db = 'dbhandle';
$crunch = new crunch($db);
$crunch->set('myfunction', function($crunch, $data) {
echo 'db = '. $crunch->db .'<br>'. json_encode( $data );
});
$crunch->call('myfunction', [123,'asd']);
Note that you have to make $db as public member variable, otherwise it would be inaccessible while calling the set() method.
I tried a code which I called a parent method in its daughter __construct and itreturns NULL,
I dont know why? I would be very happy if anyone could explain to me why.
Thanks in advance.
Here is my code
<?php
class me
{
public $arm;
public $leg;
public function __construct()
{
$this->arm = 'beautiful';
$this->leg = 'pretty';
}
public function setLeg($l)
{
$this->leg = $l;
}
public function getLeg()
{
return $this->leg;
}
}
class myBio extends me
{
public $bio;
public function __construc()
{
$this->bio = $this->setLeg();
}
public function newLeg()
{
var_dump($this->bio);
}
public function tryLeg()
{
$this->leg = $this->getLeg();
print $this->leg;
}
}
$mB = new myBio();
$mB->newLeg();
$mB->tryLeg();
?>
When I call:
$mB = new myBio();
$mB->newLeg();
, it returns
NULL,
BUT
$mB->tryLeg();
returns e string, 'pretty'.
You have a typo on this line:
$this->bio = $this->setLeg();
You're calling your setter, not your getter, and since the setter doesn't return a value you're getting null instead.
You've also misspelled construct:
public function __construc()
And you need to call the parent constructor.
<?php
class me
{
public $arm;
public $leg;
public function __construct()
{
$this->arm = 'beautiful';
$this->leg = 'pretty';
}
public function setLeg($l)
{
$this->leg = $l;
}
public function getLeg()
{
return $this->leg;
}
}
class myBio extends me
{
public $bio;
public function __construct()
{
parent::__construct();
$this->bio = $this->getLeg();
}
public function newLeg()
{
var_dump($this->bio);
}
public function tryLeg()
{
$this->leg = $this->getLeg();
print $this->leg;
}
}
$mB = new myBio();
$mB->newLeg();
$mB->tryLeg();
I have a class and two functions inside it as follows:
class MyClassName
{
protected function myFunction1()
{
// some code here
return $something;
}
public function myFunction2()
{
// some code here
return $somethingElse;
}
}
What I need to do is define a variable in myFunction1() and then use it in myFunction2(). What is the best practice to do that?
class MyClassName
{
public $var = 0;
protected function myFunction1()
{
// some code here
$this->var = ...;
return $something;
}
public function myFunction2()
{
// some code here
echo $this->var;
return $somethingElse;
}
}
Actually vars should be defined out of the function and then set a value. Then can be modified over all the script, by doing this->var
Make it a class property
class MyClassName
{
private $property;
public function __construct() {
$this->myFunction1();
}
protected function myFunction1()
{
// some code here
$this->property = 'an apple';
}
public function myFunction2()
{
// some code here
return $this->property;
}
}
Now test it:
$my_class = new MyClassName();
$something = $my_class->myFunction2();
echo $something;
I need to implement the following pattern in php:
class EventSubscriber
{
private $userCode;
public function __construct(&$userCode) { $this->userCode = &$userCode; }
public function Subscribe($eventHandler) { $userCode[] = $eventHandler; }
}
class Event
{
private $subscriber;
private $userCode = array();
public function __construct()
{
$this->subscriber = new Subscriber($this->userCode)
}
public function Subscriber() { return $this->subscriber; }
public function Fire()
{
foreach ($this->userCode as $eventHandler)
{
/* Here i need to execute $eventHandler */
}
}
}
class Button
{
private $eventClick;
public function __construct() { $this->eventClick = new Event(); }
public function EventClick() { return $this->eventClick->Subscriber(); }
public function Render()
{
if (/* Button was clicked */) $this->eventClick->Fire();
return '<input type="button" />';
}
}
class Page
{
private $button;
// THIS IS PRIVATE CLASS MEMBER !!!
private function ButtonClickedHandler($sender, $eventArgs)
{
echo "button was clicked";
}
public function __construct()
{
$this->button = new Button();
$this->button->EventClick()->Subscribe(array($this, 'ButtonClickedHandler'));
}
...
}
what is the correct way to do so.
P.S.
I was using call_user_func for that purpose and believe it or not it was able to call private class members, but after few weeks of development i've found that it stopped working. Was it a bug in my code or was it some something else that made me think that 'call_user_func' is able call private class functions, I don't know, but now I'm looking for a simple, fast and elegant method of safely calling one's private class member from other class. I'm looking to closures right now, but have problems with '$this' inside closure...
Callbacks in PHP aren't like callbacks in most other languages. Typical languages represent callbacks as pointers, whereas PHP represents them as strings. There's no "magic" between the string or array() syntax and the call. call_user_func(array($obj, 'str')) is syntactically the same as $obj->str(). If str is private, the call will fail.
You should simply make your event handler public. This has valid semantic meaning, i.e., "intended to be called from outside my class."
This implementation choice has other interesting side effects, for example:
class Food {
static function getCallback() {
return 'self::func';
}
static function func() {}
static function go() {
call_user_func(self::getCallback()); // Calls the intended function
}
}
class Barf {
static function go() {
call_user_func(Food::getCallback()); // 'self' is interpreted as 'Barf', so:
} // Error -- no function 'func' in 'Barf'
}
Anyway, if someone's interested, I've found the only possible solution via ReflectionMethod. Using this method with Php 5.3.2 gives performance penalty and is 2.3 times slower than calling class member directly, and only 1.3 times slower than call_user_func method. So in my case it is absolutely acceptable. Here's the code if someone interested:
class EventArgs {
}
class EventEraser {
private $eventIndex;
private $eventErased;
private $eventHandlers;
public function __construct($eventIndex, array &$eventHandlers) {
$this->eventIndex = $eventIndex;
$this->eventHandlers = &$eventHandlers;
}
public function RemoveEventHandler() {
if (!$this->eventErased) {
unset($this->eventHandlers[$this->eventIndex]);
$this->eventErased = true;
}
}
}
class EventSubscriber {
private $eventIndex;
private $eventHandlers;
public function __construct(array &$eventHandlers) {
$this->eventIndex = 0;
$this->eventHandlers = &$eventHandlers;
}
public function AddEventHandler(EventHandler $eventHandler) {
$this->eventHandlers[$this->eventIndex++] = $eventHandler;
}
public function AddRemovableEventHandler(EventHandler $eventHandler) {
$this->eventHandlers[$this->eventIndex] = $eventHandler;
$result = new EventEraser($this->eventIndex++, $this->eventHandlers);
return $result;
}
}
class EventHandler {
private $owner;
private $method;
public function __construct($owner, $methodName) {
$this->owner = $owner;
$this->method = new \ReflectionMethod($owner, $methodName);
$this->method->setAccessible(true);
}
public function Invoke($sender, $eventArgs) {
$this->method->invoke($this->owner, $sender, $eventArgs);
}
}
class Event {
private $unlocked = true;
private $eventReceiver;
private $eventHandlers;
private $recursionAllowed = true;
public function __construct() {
$this->eventHandlers = array();
}
public function GetUnlocked() {
return $this->unlocked;
}
public function SetUnlocked($value) {
$this->unlocked = $value;
}
public function FireEventHandlers($sender, $eventArgs) {
if ($this->unlocked) {
//защита от рекурсии
if ($this->recursionAllowed) {
$this->recursionAllowed = false;
foreach ($this->eventHandlers as $eventHandler) {
$eventHandler->Invoke($sender, $eventArgs);
}
$this->recursionAllowed = true;
}
}
}
public function Subscriber() {
if ($this->eventReceiver == null) {
$this->eventReceiver = new EventSubscriber($this->eventHandlers);
}
return $this->eventReceiver;
}
}
As time passes, there are new ways of achieving this.
Currently PSR-14 is drafted to handle this use case.
So you might find any of these interesting:
https://packagist.org/?query=psr-14