Modifications in object __destruct() not saved PHP [duplicate] - php

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Pass reference to $this in constructor PHP
I'm working on a simple PHP framework as a learning project. I've got a request object with a method called _execute(). In that method I (among other things) create an object called pageController, call a method on it, and remove the object using the following code:
$controller = new $this->_controllerName($this);
call_user_func(array($controller, $this->_methodName));
unset($controller);
As you can see I pass the current object to the constructor of the new pageController. My constructor is as follows:
public function __construct(Request $request) {
parent::__construct($request);
// More stuff
}
The parent's controller is like this:
public function __construct(Request $request) {
$this->_request = $request;
}
This all works fine, but there is a problem with my destructor. In the pageController I've also got two other methods:
public function __destruct() {
$this->_render();
}
public function _render($templateName = 'default') {
$this->_request->_response->_body = $this->_template->_render();
}
My _render() method works great if I call it from within another method in pageController: I can then get the response body from the initial request object using $this->_response->_body. When I call the _render() method from my destructor though, the changes are not changed in the request object. When I call print_r() right after the call to _render(), the changes are somehow visible...
Summarized: Any changes I make to the _request property in the destructor are somehow not changed in the initial request object, which references to the same, since objects are (almost) always not copied but referenced. What am I doing wrong?
Note: I asked a similar question before here, but that questions was not specific enough (because I didn't fully understand the problem then and thanks to some bad testing by myself). I figured I should ask a new, specific, direct question so someone can hopefully help me out.

What PHP version are you using? I was not able to duplicate your issue on 5.3.6 with the following code:
class Foo {
public function __construct(Bar $bar) {
$this->bar = $bar;
}
public function __destruct() {
$this->bar->value = 'set by Foo::__destruct';
}
}
class Bar {
public function __construct() {
$this->value = 'set by Bar::__construct';
}
}
$bar = new Bar();
$foo = new Foo($bar);
print $bar->value . PHP_EOL; // => 'set by Bar::__construct'
unset($foo);
print $bar->value . PHP_EOL; // => 'set by Foo::__destruct'
Is that along the same lines as what you are attempting to do. If it is... it sounds like maybe some other part of you application logic is interfering.

Related

What is a Constructor in PHP Used For?

Before anyone says anything. I've been to many articles, and I just can't wrap my head around the purpose of a constructor.
I've found an example on a site. Here's the code:
<?php
class dogtag {
public $Words;
}
class dog {
public $Name;
public $DogTag;
public function bark() {
print "Woof!\n";
}
public function __construct($DogName) {
print "Creating $DogName\n";
$this->Name = $DogName;
$this->DogTag = new dogtag;
$this->DogTag->Words = "My name is $DogName. If you find me, please call 555-1234";
}
}
class poodle extends dog {
public function bark() {
print "Yip!\n";
}
}
$poppy = new poodle("Poppy");
print $poppy->DogTag->Words . "\n";
?>
It echoes out the following:
Creating Poppy My name is Poppy. If you find me, please call 555-1234
May someone please explain this code to me like I'm 5. I just don't get it.
A constructor is used to do any initial process required once a new class object was initiated. Ok so that was pretty fancy right? Lets break down what that means with an example. Lets first make a class, and inside that class put some variables, some functions, and a constructor! (It's easier for me to explain the concept behind a constructor with a simpler class. babysteps.)
<?php
class myInfo
{
protected $limit;
public function __construct($limit = 10)
{
$this->limit = $limit;
}
public function awesomesauce() {
//...some random code...
}
}
$variable = new myInfo();//initiating an instance of class myInfo
?>
The code $variable = new myInfo(); is initiating an object of type myInfo. When that initiation happened, the php code knows that right away, the constructor function public function __construct($limit = 10) has to be called. In this case, the value of $limit is made to be 10. However, if I later on do the following code:
$variableTwo = new myInfo(20);
The variable passed inside the parenthesis would be passed directly into the constructor function.
So depending on the specific situation I could either pass no variables when creating an instance of type myInfo, in which case the constructor function would use the default value of ($limit = 10) or I could pass a value. If php did not have the ability to use constructors, I would literally have to manually change that variable with a new line of code every time I initiated a new object of class myInfo. Now this is just a simple example. Imagine if you need to not only initiate values, but run functions that work with API's somewhere else on your server. You can definitely see the benefit of having this happen automatically instead of being forced to write multiple lines of code every single time an object is initiated.
Let me know if that helped.

how to call two method with single line in php?

I have seen in Laravel calling multiple method in the single line, example:
DB::get('test')->toJson();
I have a cool class and view method in that class.
$this->call->view('welcome')->anotherMethod();
I would like to call another method also? Where should I make that method?
DB::get() seems to be a method returning an object, where you can call other functions (I think a result object of a database query). If you want to call multiple functions on one object in one line, you have to return $this in your functions, e.g.:
class View {
public static function factory {
// The question is: How useful is this factory function. In fact: useless in
// the current state, but it can be extended in any way
return new self;
}
public function one() {
// do something
return $this;
}
public function two() {
// do something
return $this;
}
}
Then you can do:
$class = new View();
$class->one()->two();
// it's also possible to use the `factory` function
// you should think about, how useful this approach is in your application
$class = View::factory()->one()->two();
That's how you can do it in php, if laravel has some helpers for that, i can't say :)

PHP Implementing Test Objects

I'm currently creating an object in PHP that is declared on page load. The purpose of the Object is to check the connection between the client and a remote service via a function called 'checkHeartbeat'. This function will be called intermittently to see if the connection exists via AJAX.
I am trying to implement a testing parameter to alter the connection to results without querying the remote service:
fail
succeed
fail after x attempts
succeed after x attempts
The parameter is currently passed through via the URL which is picked up by the construct function of the object and placed into a variable via $_GET. Each time the checkHeartbeat function is called by AJAX it currently checks if the 'test' variable is set.
My aim is the eliminate this check on each call of checkHeartbeat however I am unsure the best method to do this. The AJAX Query will always call 'checkHeartbeat' and so I have been looking into extending/altering this function.
I attempted to re-define the object of $heartbeat within the construct to be the test object and therefore overwrite the checkHeartbeat function however this doesn't work and only returns that the connection is live. This is my re-factored code below as a demonstration of the desired outcome.
class heartbeat {
public function __construct() {
if(isset($_GET['test'])) {
$heartbeat = new testHeartbeat;
}
}
public function checkHeartbeat() {
echo 'Live connection works!';
}
}
class testHeartbeat {
public function checkHeartbeat() {
echo 'Test connection works!';
}
}
$heartbeat = new heartbeat;
$heartbeat->checkHeartbeat();
Looking into PHP objects further I have attempted to look at using Object Interfaces to define a separate function however I'm not sure how this would work and if it would still work by just calling the one function.
$heartbeat->checkHeartbeat();
My query is, what is the best method to change the 'checkHeartbeat' function to not check if the test parameter has been set on each AJAX call and only do this on the initial construct of the object. If the test parameter has been passed the checkHeartbeat will only return the test status OR will instantly make the call to the remote service if no test parameter has been set.
I mock this up playing around and does the work.
I am sure there is a better way, actually cleaner.
I did not found a way to modify the public variable instantiation inside the same object.
Hope this helps:
class heartbeat {
public $foo;
public function __construct()
{
$this->checkTest();
return $this->foo;
}
public function checkTest()
{
if(isset($_GET['test']))
{
$this->foo = 'true';
}
else
{
$this->foo = 'false';
}
}
public function __toString()
{
return $this->foo;
}
public function checkHeartbeat() {
echo 'Live connection works!';
}
}
class testHeartbeat {
public function checkHeartbeat() {
echo 'Test connection works!';
}
}
new heartbeat()=='true' ? $heartbeat = new testHeartbeat() : $heartbeat = new heartbeat();
$heartbeat->checkHeartbeat();
Bb!

Calling a method outside class statically, passing other method's output as parameter

I have a class like this:
class myClass {
public static function load()
{
return new self();
}
public function myMethod1 ()
{
return 'content';
}
public function myMethod2 ($content)
{
return 'modified '.$content;
}
}
Somewhere in my script, I have to call myMethod2 using myMethod1's output as parameter.
The way I currently do that, is:
echo myClass::load()->myMethod2(myClass::load()->myMethod1()); // modified content
It works, but I'm pretty confident there is a more appropriate way... So my questions:
Is there a proper way of passing method's output as other method's parameter in a class loaded "statically"?
Besides that, there is a more elegant code structure to accomplish the same "task"?
Thanks!
(This is my first question in StackOverflow, I apologize for mistakes, eventually)

Method Chaining and Class Inheritance

I think I have more or less managed to get a grasp on OOP/Inheritance, and the basics of method chaining I think I understood as well. However I am still confused about how to actually use some of it.
I wanted to do something that I've seen when working with Magento before:
In Magento, I've seen some sort of "selector-function" used in method chaining. It's a little hard to put into words, but it was something along the lines of:
$categoryName = Mage::getModel('catalog/category')->load($categoryId)->getName();
It's the load($categoryId) part that interests me, as in, a function that selects some instance of something and allows me to run a function on that specific instance.
Now, I am writing a module that allows me to configure certain promotions on our website. Seeing as we'll have many different promotions and I want them to be easily configurable and modifiable, I wanted to do something similar.
So, if I wanted to be able to do something like this:
$prm = new Promotion();
$prm->addPromo('xmasPromo');
$prm->addPromo('nyPromo');
$prm->getPromo('xmasPromo')->setName('Promotion for Xmas!');
$prm->getPromo('nyPromo')->setName('Promotion for New Years!');
echo $prm->getPromo('xmasPromo')->getName(); // returns: Promotion for Xmas!
echo $prm->getPromo('nyPromo')->getName(); // returns: Promotion for New Years!
How would the class definition for that have to look like?
This may be much more simple or much more complicated than I anticipate. In either case, thanks a lot!
Edit:
So I did some testing around with the info deceze gave me, but I'm still confused.
Bad naming and putting 2 classes in 1 file aside, here's what I did:
class file:
class Promotion {
private $__arr = array();
public function addPromo($name) {
$this->__arr[$name] = new Promo();
}
public function getPromo($name) {
$this->__arr[$name];
}
}
class Promo {
private $name;
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $name;
}
}
and the run file:
require_once 'class.php';
error_reporting(E_ALL);
$prm = new Promotion();
$prm->addPromo('xmasPromo');
$prm->addPromo('nyPromo');
$prm->getPromo('xmasPromo')->setName('Promotion for Xmas!');
$prm->getPromo('nyPromo')->setName('Promotion for New Years!');
echo 'X: '.$prm->getPromo('xmasPromo')->getName(); // returns: Promotion for Xmas!
echo "\n";
echo 'N: '.$prm->getPromo('nyPromo')->getName(); // returns: Promotion for New Years!
This gives me Fatal error: Call to a member function setName() on a non-object in /var/www/test/index.php on line 11.
But why? Shouldn't getPromo() give me back the object?
Thanks again..
Thanks to the great guys here, it works now. In case anyone were to pass by here with the same or a similar question, here's the final, working code:
Classes:
class Promotion {
private $__arr = array();
public function addPromo($name) {
$this->__arr[$name] = new Promo();
}
public function getPromo($name) {
return $this->__arr[$name];
}
}
class Promo {
private $name;
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
Test file:
require_once 'class.php';
error_reporting(E_ALL);
$prm = new Promotion();
$prm->addPromo('xmasPromo');
$prm->addPromo('nyPromo');
$prm->getPromo('xmasPromo')->setName('Promotion for Xmas!');
$prm->getPromo('nyPromo')->setName('Promotion for New Years!');
echo 'X: '.$prm->getPromo('xmasPromo')->getName(); // returns: Promotion for Xmas!
echo "\n";
echo 'N: '.$prm->getPromo('nyPromo')->getName(); // returns: Promotion for New Years!
Method chaining is really simple, all it does is use one particular element of PHP's syntax:
When a function returns an object, you can directly continue with -> after that function.
The longhand version can be:
$bar = $foo->bar();
$baz = $bar->baz();
echo $baz;
$foo->bar() returns an object ($bar) which has a method baz(), and that method returns some value ($baz). This can be written in shorthand like so:
echo $foo->bar()->baz();
$foo->bar() still returns an object which has a method baz(), so you can directly call it without assigning it to an intermediate variable. Maybe this makes it more obvious:
echo ( $foo->bar() )->baz();
You're calling the baz() method on whatever $foo->bar() returns.
$prm->getPromo('xmasPromo')->setName('Promotion for Xmas!');
As such, in your above case, all you need to do is to return an object which has the method setName from getPromo. I would assume getPromo is supposed to return some object of, say, the Promo class. If the Promo class has a method setName, you're all set.
If you want to chain methods you just need to always return the object like this
class Chain {
public function firstChain() {
//do something
return $this;
}
public function secondChain() {
//do some stuff
return $this;
}
}
Than when you have an instance of the class you do like this:
$obj = new Chain();
$obj->fistChain()->secondChain();

Categories