PHP Implementing Test Objects - php

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!

Related

Add a callback closure to a class constructor

I have a class that someone else wrote. It does a lot of things for me, and one thing it does for me is it makes requests to an external service.
public function makeRequest() {
...bunch of curl stuff here
}
So what I wanted to do is modify the constructor of the class so that I could pass in a function, and the function could get called after the curl stuff. I come from a javascript background so I'm definitely doing this the wrong way, but this is what I did:
private $requestLogger;
public function __construct(...other variables, $requestLogger = null) {
if ($requestLogger) {
$this->requestLogger = $requestLogger;
}
}
public function makeRequest() {
...bunch of curl stuff here
if ($this->requestLogger) {
$curlInfo = curl_getinfo($ch);
$this->requestLogger($curlInfo['url'], $curlInfo['http_code'], $request, $response);
}
}
And that when when I make a new instance, I can do it like this
$client = new ApiClient(..., function($url, $responseCode, $requestText, $responseText){
// do whatever i want here
});
However, this hasn't worked. I get this message: 500: Call to undefined method ApiClient::requestLogger()
How do I set myself up to pass a callback function to this class?
When you do: $this->requestLogger(...), PHP thinks you're trying to call a class method called requestLogger().
If you want to call a function in a class property, you can use call_user_func_array(). Something like this:
call_user_func_array($this->requestLogger, [
$curlInfo['url'],
$curlInfo['http_code'],
$request,
$response
]);
A tip, before trying to call it, make sure it contains something that's callable and not just empty:
if (is_callable($this->requestLogger)) {
call_user_func_array(...);
}

Calling php functions that have an instance as an argument

Ok so my question is, i have a Facebook call back function that I'm using. The callback function uses an instance as an argument facebookCallBack(LaravelFacebookSdk $fb)
The function works great,I'm using this in my auth controller in larvel , but now I want to reuse this function within the same controller something like $this>facebookReusableCallBack(LaravelFacebookSdk $fb)
I'm having issues ,i get this error facebookReusableCallBack() must be an instance of SammyK\LaravelFacebookSdk\LaravelFacebookSdk, none given.
here's a sample of my code:
public function facebookCallBack(LaravelFacebookSdk $fb) {
$this->facebookReusableCallBack();
}
public function facebookReusableCallBack() {
//All my code here
}
how can I reuse this function within my controller?
i've tried :
public function facebookCallBack(LaravelFacebookSdk $fb) {
$this->facebookReusableCallBack(LaravelFacebookSdk $fb);
}
but the argument doesn't get passed as an instance?
You don't need to define the type of a variable when you pass it in.
Method definition:
public function facebookReusableCallBack(LaravelFacebookSdk $fb) {
//some code
}
Execution within another method:
function myMethod() {
$var = new LaravelFacebookSdk();
$this->facebookReusableCallBack($var);
}
What you have done is define the type of the variable in your function definition (good) to force the type. However these are only needed in the definition.
So for your explicit example:
public function facebookCallBack(LaravelFacebookSdk $fb) {
$this->facebookReusableCallBack($fb);
}
Because $fb must be an instance of LaravelFacebookSdk when calling facebookCallBack it will be fine for facebookReusableCallBack.

Create methods in a php class dynamically, so to have access to $this

I have a class that executes eval statements within a (very large) loop. The eval statements are database stored code (mixed html & php) that needs to be processed. There is however is a serious performance issue because of this.
Instead of parsing the eval-statement every time in the loop, I would like to create a dynamic methods from the available eval-codes coming from the database within my class.
I thought of the following pseudocode so that the eval code is converted to a method:
class foo
{
private $test=3;
public function doloop()
{
for($i=0;$i<5;$i++)
{
$string="echo 50 * \$this->test.'<br>';";
$func="evalcode_001";
if(!isset(${$func}))
{
${$func}=create_function('',$string);
}
${$func}();
}
}
}
$obj_foo = new foo();
$obj_foo->doloop();//must output '150<br>150<br>150<br> .....'
However when running it I get the error message "Using $this when not in object context in ...". So obviously I didn't really create methods within the class.
So my question is:
How do I create a method for a class dynamically and assign code for the given method. Basically I want to be able to do:
$obj_foo->evalcode_001();
in the above example.
Help appreciated
PS I am using PHP5.4
If you can change $this->test inside string (or write extra preg_match) you can use:
<?php
class foo
{
public $test=3;
public $functions = array();
public function doloop()
{
for($i=0;$i<5;$i++)
{
$string="echo 50 * \$this->test.'<br>';";
$func="evalcode_001";
if(!isset($this->functions[$func]))
{
$string = str_replace('$this','$object', $string );
$this->functions[$func]= create_function('$object',$string);
}
$this->functions[$func]($this);
}
}
public function __call($name, $arguments) {
if (isset($this->functions[$name])) {
return $this->functions[$name]($this);
}
}
public function otherMethod() {
echo "test";
}
}
$obj_foo = new foo();
$obj_foo->doloop();//must output '150<br>150<br>150<br> .....
$obj_foo->evalcode_001();
$obj_foo->otherMethod();
However as other said I wouldn't like to use anything like that in my real script

kill method chain in php

hi i have a method chain in php somewhat like
<?php
auth::('username') -> is_logged() -> doSomething();
//execute something
?>
what i would like to do is if the user is not logged then not invoke the doSomething() function. One way is to unset $this but that would generate an error id there any other way to do it. Also i cant be using die() because it would stop the compiler and prevent codes written afterwards from executing. What is the best way to do it preferably without any warning or error and at the same time making as few changes as possible because of a large number of functions associated with the class.
Return NullObject which will provide empty implementation of doSomething
In PHP you only need to provide the magic __call() method, so any function call will pass.
class NullObject {
public function __call($name, $arguments) {
return $this;
}
}
To use it in your class:
public function is_logged() {
if ($this->user_is_logged()) {
return $this;
} else {
return new NullObject;
}
}

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

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.

Categories