kill method chain in php - 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;
}
}

Related

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!

Instantiate object defined as property in a PHP class as needed (lazy loading)

For the sake of simplicity, assume I have 2 classes, User and UserStatus, used in a Web application.
<?php
// library code:
class UserStatus {
protected $_status = NULL;
private function fetchDataFromDB() {
// regular DB stuff
$this->_status = ...
// result will be something like 'online', 'away', etc.
}
public function getIcon() {
global $icon_array;
if (is_null($this->_status)) {
$this->fetchDataFromDB()
}
return $icon_array[$this->_status];
}
}
class User {
protected $user_id;
public $user_name;
protected $status;
public function __construct() {}
public static function getAll() {
// some DB stuff
return $users;
}
}
// and now, in index.php:
$users = User::getAll();
// echoes the icon to use to reflect the current user status
foreach ($users as $user) {
echo <img src="$user->status->getIcon()"/>;
}
?>
In most of the HTTP request the status object will not be used so I'm looking for a way to only instantiate it as needed (call it lazy loading). How should I intercept the status->method() call and create that object on-the-fly?
An important note is that I need $user_id available in the UserStatus class, otherwise the fetchDataFromDB() method won't know to which user it should fetch the data. How should this be done?
I've looked at some interesting stuff on this matter like Fabien Potencier's What is Dependency Injection? and Pimple - a PHP 5.3 dependency injection container and also some articles about the Proxy Pattern but to implement them it looks like I have to mess a lot with the current code. Is there a simpler way?
Maybe im missing something but it seems the easiest solution in this instance would be to have your getter for Status simply create the object if it doesnt exist...
public function getStatus()
{
if(!isset($this->status))
{
// or however you creat this object..
$this->status = new UserStatus($this->user_id);
}
return $this->status;
}
public function __get($property)
{
$method = 'get'.ucfirst($property); // getStatus
if(method_exists($this, $method))
{
return $this->$method();
}
}
By using the __get magic method anytime you do $user->status it will call $user->getStatus(). Ofcourse you could also always just access it like: $user->getStatus()->getIcon() as well.
However you decide to set up accessing your properties i would recommend doing it in a consistent way across your entire model.
You could put the status class in a different file and then leverage php's autoloading mechnism:
http://php.net/manual/de/language.oop5.autoload.php
to not load that file until you access it.
There are rumors that auto loading (or actually just any kind of conditional loading) is troublesome for byte code caches and optimizers though unfortunately I don't know too much about the impact.
P.S.: The manual does not say rhis explicity at this point: You can also use spl_autoload_register() instead of just defining the magic __autoload function. This is slightly more powerful.

PHP Methods that are always called

I'm currently working on an own PHP-MVC-Framework (for experience purposes only).
My question: Is it possible to call a defined function or method, every time a class-method
has been called?
For example:
public function view($id) {
//Code ...
$this->view->render(__FUNCTION__);
}
What I want is:
public function view($id) {
//Code ...
//render-method is called automatically with functionname as parameter
}
I tried different methods ... but without success.
Would be great if someone could help me out with this.
Cheers,
Chris
You can use Magic Methods do achieve this behavior:
public function __call($func, $args) {
if(!method_exists($this, $func)) {
return;
}
// do some coding here
call_user_func_array($func,$args);
// do some coding there
}
private function view($arg1, $arg2) {
// and here
}
Remember: view function must be private/protected.
$obj->view("asdasd", "asdsad");
Should do ::__call(), then ::view() method
You could create a function as a liaison using PHP's ability to use variable values for execution purposes. for example:
function call($func,$param)
{
$this->$func($param);
$this->render($func);
}
$myObj->call('view',$id);
You can use a wrapper method. Call this method and pass everything else as a parameters.

How to chain method on a newly created object?

I would like to know whether there's a way to chain methods on a newly created object in PHP?
Something like:
class Foo {
public function xyz() { ... return $this; }
}
$my_foo = new Foo()->xyz();
Anyone know of a way to achieve this?
In PHP 5.4+, the parser's been modified so you can do something like this
(new Foo())->xyz();
Wrap the instantiation in parenthesis, and chain away.
Prior to PHP 5.4, when you're using the
new Classname();
syntax, you can't chain a method call off the instantiation. It's a limitation of PHP 5.3's syntax. Once an object is instantiated, you can chain away.
One method I've seen used to get around this is a static instantiation method of some kind.
class Foo
{
public function xyz()
{
echo "Called","\n";
return $this;
}
static public function instantiate()
{
return new self();
}
}
$a = Foo::instantiate()->xyz();
By wrapping the call to new in a static method, you can instantiate a class with method call, and you're then free to chain off that.
Define a global function like this:
function with($object){ return $object; }
You will then be able to call:
with(new Foo)->xyz();
In PHP 5.4 you can chain off a newly instantiated object:
http://docs.php.net/manual/en/migration54.new-features.php
For older versions of PHP, you can use Alan Storm's solution.
This answer is outdated - therefore want to correct it.
In PHP 5.4.x you can chain a method to a new-call. Let's take this class as example:
<?php class a {
public function __construct() { echo "Constructed\n"; }
public function foo() { echo "Foobar'd!\n"; }
}
Now, we can use this: $b = (new a())->foo();
And the output is:
Constructed
Foobar'd!
Further information may be found on the manual: http://www.php.net/manual/en/migration54.new-features.php
Well, this may be an old question but as with a lot of things in programming - eventually the answer changes.
Regarding PHP 5.3, no, you can't chain directly from the constructor. To expand on the accepted answer however, in order to properly accommodate for inheritance, you can do:
abstract class Foo
{
public static function create()
{
return new static;
}
}
class Bar extends Foo
{
public function chain1()
{
return $this;
}
public function chain2()
{
return $this;
}
}
$bar = Bar::create()->chain1()->chain2();
That will work just fine and will return you a new Bar() instance.
In PHP 5.4, however, you can simply do:
$bar = (new Bar)->chain1()->chain2();
Hopefully this helps someone stumbling across the question like I have!
It would be really helpful if they 'fix this' in a future release. I really appreciate the ability to chain (especially when populating collections):
I added a method to the base class of my framework called create() that can be chained off of. Should work with all descendant classes automatically.
class baseClass
{
...
public final static function create()
{
$class = new \ReflectionClass(get_called_class());
return $class->newInstance(func_get_args());
}
...
public function __call($method, $args)
{
$matches = array();
if (preg_match('/^(?:Add|Set)(?<prop>.+)/', $method, $matches) > 0)
{
// Magic chaining method
if (property_exists($this, $matches['prop']) && count($args) > 0)
{
$this->$matches['prop'] = $args[0];
return $this;
}
}
}
...
}
Class::create()->SetName('Kris')->SetAge(36);
Just for the sake of completeness (and for the fun of it...), since nobody seems to have mentioned the solution with the shortest (and least sophisticated) code.
For frequently used short-lived objects, especially when writing test cases, where you typically do lots of object creation, you may want to optimize for typing convenience (rather than purity), and sorta' combine Alan Storm's Foo::instantiate() factory method and Kenaniah's with() global function technique.
Simply make the factory method a global function with the same name as the class!. ;-o (Either add it as a convenience wrapper around the proper static Foo::instantiate() or just move it out there while nobody is looking.)
class Foo
{
public function xyz()
{
echo "Called","\n";
return $this;
}
}
function Foo()
{
return new Foo();
}
$a = Foo()->xyz();
NOTE:
I WOULDN'T DO THIS on production code. While kinda' sexy, this is an abuse on basic coding principles (like "principle of least surprise" (although this is actually rather intuitive syntax), or "don't repeat yourself", esp. if wrapping a real factory method with some parameters, which itself, BTW, is already an abuse of DRY...), plus PHP may change in he future to break code like this in funny ways.

Categories