Asked  7 Months ago    Answers:  5   Viewed   30 times

Why can't I do this in PHP? Where Database is a singleton class and getInstance() returns a PDO object.

<?php

class AnExample
{
    protected static $db = Database::getInstance();

    public static function doSomeQuery()
    {
        $stmt = static::$db->query("SELECT * FROM blah");
        return $stmt->fetch();
    }
}

Like any other PHP static variable, static properties may only be initialized using a literal or constant; expressions are not allowed. So while you may initialize a static property to an integer or array (for instance), you may not initialize it to another variable, to a function return value, or to an object.

http://php.net/manual/en/language.oop5.static.php

Why?!

 Answers

95

http://php.net/language.oop5.properties

Class member variables are called "properties". You may also see them referred to using other terms such as "attributes" or "fields", but for the purposes of this reference we will use "properties". They are defined by using one of the keywords public, protected, or private, followed by a normal variable declaration. This declaration may include an initialization, but this initialization must be a constant value--that is, it must be able to be evaluated at compile time and must not depend on run-time information in order to be evaluated.

The important part is

that is, it must be able to be evaluated at compile time

Expressions were evaluated at runtime, so it isn't possible to use expression to initialize properties: They are simply not evaluatable yet.

Wednesday, March 31, 2021
 
Freddie
answered 7 Months ago
85

Use the built in call_user_func(). It may be necessary to use call_user_func_array()

function work($a, $c) {
  $a = filter($a)
  if(!is_callable($c) || !call_user_func($c, $a)) {
    return 0; // throw error
  } else {
    return 1; // return success
  }
}

This is safer than just doing $c($a) a.k.a passed_callback(passed_argument) because checking to see if the function actually exists is done for you, though some have commented on performance degradation over $c($a).

Saturday, May 29, 2021
 
DMTintner
answered 5 Months ago
63

In response to the "comment-discussion" that this question (and perhaps answer) has ignited, a recap of my opinion, and the general consensus (don't skimp on equipment/server load, when that means doubling the man-hours and maintainability is more important than speed, save for a few specific cases).

You say you hate frameworks and that devs who use frameworks they didn't develop themselves sell maintainance contracts. How exactly does that work? Code using an open source, documented FW can be maintained by anyone who knows the FW. Your code can be maintained by you.
Besides, PHP frameworks are (well, the main ones at least) OPEN SOURCE. I know that, coming from a VB.NET background, you might suspect there is a catch to this, but there really isn't. They all have github repo's, the source is freely available to copy, and edit (in accordance to the license, which, on the whole is quite liberal anyway). Basically, you have full control.
And don't go thinking it's all second-grade code: Apple (including major parts of their OSX kernel), Microsoft, Google... they are all using open-source software and frameworks. Not only because it's easy, and faster to develop, but also because of the notion of proven technology.

Besides: performance is your goal, and -given that you loathe frameworks-, why not consider learning assembly? That way, you can avoid having an idiotic compiler compile your code to something that isn't as efficient as, perhaps, it could have been.
And of course, you don't use an IDE for this, you'd either go for Emacs or butterflies, right?

Emacs butterfly
(source: andreas-wilm.com)

An alternative approach would be to use a framework that offers advanced caching featrures...

Maintainability should be at the most important thing to you, while writing code:

'Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.' — Brian Kernighan

Servers are zombie-slaves: they don't complain, and it's not illegal to whip them. Developers, though some project-managers seem to forget this, are neither zombies or slaves: they can't work 2 weeks on end, and whipping devs is illegal, still. Even Steve Ballmer knows that... Developers, Developers, Developers. Microsoft's Server OS's are resource intensive, as is MSSQL, and pretty much all their software, but look into their server OS. There are many features that only serve to reduce the maintainance hours your system requires. I'm no MS fan-boy, but I fully understand that descision. They can't beat Linux on price ('cause it's free), but they can lure in companies by selling a system, that will cut their sys-admin costs in half. (though, ATM, they haven't acchieved this, and IMO, they never will)


This question is one of many dupes, a bad fit for SO, and will be closed. However, before it gets closed/deleted, I'd like to point a couple of things out to you:

First things first:

As I'm currently working on an e-commerce website, I'd like to know if it's really useful to use a singleton pattern on my PDO connections

No, it never is.

injection PHP is not capable of persisting an objects' state in between requests. The server receives a request. The script is parsed, the DB connection is established, queries are performed, the response is sent back and the connection is closed. Over and over again.
Connections can't be serialized, they can't be stored in any way, shape or form, so:
By coding well, you can use injection and at the same time ensure that you only connect to the DB once per request.
Statics are globals in drag, now: would you use globals if you might as well pass an argument? Giving you the benefit of the doubt, I assume your answer is no.
The few remaining benefits of singletons that remain, then, are not worth the effort it takes to write decent, working, unit-tests for your singleton-using code.

Why:

my architecture is made in a way that each script only needs one connection.

Then your code isn't very scalable. I know this is a blanket statement, and a terrible cliché, but it just is the case here. Just like your presumtion that each script only needs one connection might be true right now, but who's to say that will always be the case?
Refactoring the DB, adding support for another adapter, testing (as mentioned before) become increasingly difficult, as you'll write code and, without noticing it, that new code will be adapted to maintain the singleton.
This means that you'll write code to preserve what was, because you're working around its problems, a bad design decision.

Think of it like this:
You build a house, and decide to build a concrete pilar into the corridor, because that's where you'll hang your coat-hangers anyway, and you'll never change that. But Singleton implies that you're writing OO code. The whole point is that you can re-use code. Now: do you honestly think that you'll be able to sell your house just as easily if it had an immovable coat-hanger, as it would be if that thing wouldn't be there? of course not!

And I'm quite sure that it's only useful when you have to call an instance twice or more.

If that's so: use another pattern, or take a leaf out of the Symfony book, and make the connection available to whatever object needs it using a container (dependency injection component is worth a google search).

Testing:

It's all been explained before, but testing singleton code is a nightmare. Learn to use injection.

Saturday, July 31, 2021
 
Exoon
answered 3 Months ago
32

PHP 5.6 will allow to import functions with the use keyword:

namespace foobar {
    function baz() {
        echo 'foo.bar.baz';
    }
}

namespace {
    use function foobarbaz;
    baz();
}

See the RFC for more information: https://wiki.php.net/rfc/use_function

Thursday, August 12, 2021
 
buymypies
answered 3 Months ago
98

Checkout

<?

class ErrorHandling{

  private static $instance;
  private static $_appMode;  // not initialised in returned instance
  private $_errorConfig;

 private function __construct(array $config, $appMode = null){

   $this->_errorConfig = $config;

   if(isset($appMode)){
       self::$_appMode = $appMode;
   }else{
         self::$_appMode = APPMODE;
   }  
 }

 private final function  __clone(){}

 public static function getInstance(array $config, $appMode = null){
     if(! (self::$instance instanceof self)){
         self::$instance = new ErrorHandling($config, $appMode);
     } 
     return self::$instance;
 }

 public static function getAppMode() {
    return self::$_appMode;
 }
} 

$e = ErrorHandling::getInstance(array('dev' => true), -255);
var_dump($e, ErrorHandling::getAppMode());

Is that your want?

Your could read here about difference between static and self- late static binding

Friday, September 3, 2021
 
CyberJunkie
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :