I have a class with static methods, and I would like to intercept method calls before the methods are called.
So if I call
$model = DataMapper::getById(12345);
then I want some method in DataMapper to be called before this method is called, and then optionally this intercepting method can subsequently call self::getById(12345). Is there a way to do this?
I am implementing Memcache on my server, so that is why I want to intercept method calls. I don't want the static methods to query the database if models are already cached, and I also don't want to have to modify hundreds of different mapper methods, redundantly, to support memcache.
I am running PHP 5.2.6.
This'd do the job:
Triggering __call() in PHP even when method exists
Just declare your static methods as protected so they're inaccessible outside the class and get the __callStatic() magic method to invoke them.
Edit: oops, you'll be needing 5.3 to do it...
This is one example where you might want to consider ditching static methods in favor of polymorphism. If your data-mapper was an interface then you could have two implementations, one for the database and one for memcache:
interface DataMapper {
public function getById($id);
// other data mapper methods
}
class DataMapper_DB implements DataMapper {
public function getById($id) {
// retrieve from db
}
// other methods
}
class DataMapper_Memcache implements DataMapper {
private $db;
public function __construct(DataMapper_DB $db, $host, ...) {
$this->db = $db;
// other set up
}
public function getById($id) {
// if in memcache return that
// else
$record = $this->db->getById($id);
// add record to memcache
return $record
}
//other methods
}
I just came up with a way to intercept method calls in PHP - Check it out.
It's just a basic example, and classes that want to be interceptible have to "opt in" - you can't interfere with the behavior of classes that don't implement the two magic methods.
I don't know if this meets your needs - but this pattern can be implemented without code generation or runtime bytecode hacks, and that's gotta be a plus ;-)
I guess you could have created some magic with runkit, but you would need to compile the extension from cvs, since the latest version does not support 5.2.x
Example:
<?php
/* Orig code */
class DataMapper {
static public function getById($value) {
echo "I'm " . __CLASS__ . "\n";
}
}
/* New Cache Mapper */
class DataMapper_Cache {
static public function getById($value) {
echo "I'm " . __CLASS__ . "\n";
}
}
// Running before rename and adopt
DataMapper::getById(12345);
// Do the renaming and adopt
runkit_method_rename('DataMapper', 'getById', 'getById_old');
runkit_class_adopt('DataMapper','DataMapper_Cache');
// Run the same code..
DataMapper::getById(12345);
?>
Output:
I'm DataMapper
I'm DataMapper_Cache
Related
I'm a bit lost here because I want to do something that is very easy in Java but seems a bit complicated in PHP.
We are building an SDK for our product and in Java, we have this one class that must not (!) be instantiated by the user (i.e. the coder), since there are several constraints regarding it's integrity. So we've built that as a nested class "X" inside of the "XFactory" and you will get an instance of X by calling XFactory.buildMeMyX(); - Easy...
Now PHP does not support nested classes at all, and I wonder how to apply the same here. In Java, X's constructor is hidden (private), so only XFactory can call it.
In PHP, it looks like I will have to make __construct() public and move the nested class X out of XFactory. Hence, the user will be able to create an instance without the Factory.
Now - I COULD move the factory functionality to X itself and move all the stuff there, but this would kind of break the design of the SDK. Is there a useful way to do such things in PHP after all?
For PHP 5.x you already described your options, there are no private/protected classes or inner classes at all, so there is no further way to restrict instantiation.
However, with PHP 7 this is going to change.
There are still no nested classes (although we might get them in the future, see: https://stackoverflow.com/a/31454435/664108), but you could instantiate an anonymous class and only provide the consumer with its interface like this:
class XFactory
{
public function buildMeMyX()
{
return new class() implements XInterface {
public function doWhatEverAnXCanDo()
{
// X X X
}
// ...
};
}
}
interface XInterface
{
function doWhatEverAnXCanDo();
}
As the others have said, there currently is no clean way to implement this behavior in PHP. In my opinion, the only valid use case for private constructors are factories inside the class that implement that factories.
Whenever you try to get around that use case it gets messy. No one should ever try to invent clever ways to bypass PHP's language limiations.
I just violated that rule by myself just to prove it is indeed possible. But please refrain from using that in production, or better: using it anywhere. I will try to find some bulletproof arguments for that suggestion and edit the answer afterwards.
<?php
class Dependency {}
class SomeClass {
protected $dep;
private function __construct(Dependency $dep)
{
$this->dep = $dep;
}
public function doSomething()
{
var_dump($this->dep);
echo "Doing Stuff and even having dependencies";
}
}
class SomeClassFactory {
public function buildSomeClass()
{
return $this->instantiateSomeClassWith(new Dependency);
}
protected function instantiateSomeClassWith()
{
$reflectionClass = new ReflectionClass('SomeClass');
$someClass = $reflectionClass->newInstanceWithoutConstructor();
$constructor = $reflectionClass->getConstructor();
$constructorClosure = $constructor->getClosure($someClass);
call_user_func_array($constructorClosure, func_get_args());
return $someClass;
}
}
$factory = new SomeClassFactory();
$someClass = $factory->buildSomeClass();
$someClass->doSomething();
?>
Output: object(Dependency)#2 (0) { } Doing Stuff and even having dependencies
The theory is simple. The constructor of the class that will be built via the Factory is made private. We make use of reflection within the factory to create an instance of the class without invoking the constructor.
Once we have an instance, we grab the closure of the constructor and invoke it via call_user_func_array(). That way you can make use of Dependency Injection just as you would if the constructor was public.
As I said before. That way is a single smell. By creating an object without invoking it's constructor, there is no real way to validate an objects state upon creation
This is a proof of concept, but the concept sucks.
There is no native way to do so, yet. However, if you really want to "enforce" that your class is only created from your factory class, there is a little "hackish" way to do so limiting the instantiation by inistantiating class.
class X
{
function __construct()
{
new Y();
}
}
class Y
{
function __construct()
{
$trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 2);
if (!isset($trace[1]['object']) || !($trace[1]['object'] instanceof X)) {
throw new \RuntimeException('This is a private class');
}
}
}
new X(); // All is fine
new Y(); // Exception
Please note that there is no "real" way to protect the class from being instantiated from elsewhere even using this approach - it still can be done via reflection by bypassing the constructor, or simply modifying your source.
Assuming that I have to create a class that takes some text do some processing and return it ... with no dependency and it's a stateless class..
I'd like to know would be better to create a stateless class without constructor or just create a static class (in php it's just Static methods)
class like this:
class ClassName
{
public function processText($text)
{
// Some code
$text = $this->moreProcessing($text);
return $text;
}
protected function moreProcessing($text)
{
return $text;
}
}
and this:
class ClassName
{
public static function processText($text)
{
// Some code
$text = static::moreProcessing($text);
return $text;
}
protected static function moreProcessing($text)
{
return $text;
}
}
I Know that dependency injection into the class where these classes are used would be better but assume that I just won't have dependency injection..
My question is mainly would it be better to create static class for the simple example above?
Practically you will see no difference whatsoever.
It's only in the syntax, and the ability of a constructor to perform stuff automatically, though you still have to create instances to invoke the constructor, which in this case is not far off calling some equivalent static member function.
However, non-static member functions are supposed to affect internal state so, if you have no state, static member functions seem more conventional, and will be slightly less surprising to users of the class.
The best approach, though, is to stick your functions in a namespace. Classes are for data and functions operating on that data... even static ones.
I want to write a module (framework specific), that would wrap and extend Facebook PHP-sdk (https://github.com/facebook/php-sdk/). My problem is - how to organize classes, in a nice way.
So getting into details - Facebook PHP-sdk consists of two classes:
BaseFacebook - abstract class with all the stuff sdk does
Facebook - extends BaseFacebook, and implements parent abstract persistance-related methods with default session usage
Now I have some functionality to add:
Facebook class substitution, integrated with framework session class
shorthand methods, that run api calls, I use mostly (through BaseFacebook::api()),
authorization methods, so i don't have to rewrite this logic every time,
configuration, sucked up from framework classes, insted of passed as params
caching, integrated with framework cache module
I know something has gone very wrong, because I have too much inheritance that doesn't look very normal. Wrapping everything in one "complex extension" class also seems too much. I think I should have few working togheter classes - but i get into problems like: if cache class doesn't really extend and override BaseFacebook::api() method - shorthand and authentication classes won't be able to use the caching.
Maybe some kind of a pattern would be right in here? How would you organize these classes and their dependencies?
EDIT 04.07.2012
Bits of code, related to the topic:
This is how the base class of Facebook PHP-sdk:
abstract class BaseFacebook {
// ... some methods
public function api(/* polymorphic */)
{
// ... method, that makes api calls
}
public function getUser()
{
// ... tries to get user id from session
}
// ... other methods
abstract protected function setPersistentData($key, $value);
abstract protected function getPersistentData($key, $default = false);
// ... few more abstract methods
}
Normaly Facebook class extends it, and impelements those abstract methods. I replaced it with my substitude - Facebook_Session class:
class Facebook_Session extends BaseFacebook {
protected function setPersistentData($key, $value)
{
// ... method body
}
protected function getPersistentData($key, $default = false)
{
// ... method body
}
// ... implementation of other abstract functions from BaseFacebook
}
Ok, then I extend this more with shorthand methods and configuration variables:
class Facebook_Custom extends Facebook_Session {
public function __construct()
{
// ... call parent's constructor with parameters from framework config
}
public function api_batch()
{
// ... a wrapper for parent's api() method
return $this->api('/?batch=' . json_encode($calls), 'POST');
}
public function redirect_to_auth_dialog()
{
// method body
}
// ... more methods like this, for common queries / authorization
}
I'm not sure, if this isn't too much for a single class ( authorization / shorthand methods / configuration). Then there comes another extending layer - cache:
class Facebook_Cache extends Facebook_Custom {
public function api()
{
$cache_file_identifier = $this->getUser();
if(/* cache_file_identifier is not null
and found a valid file with cached query result */)
{
// return the result
}
else
{
try {
// call Facebook_Custom::api, cache and return the result
} catch(FacebookApiException $e) {
// if Access Token is expired force refreshing it
parent::redirect_to_auth_dialog();
}
}
}
// .. some other stuff related to caching
}
Now this pretty much works. New instance of Facebook_Cache gives me all the functionality. Shorthand methods from Facebook_Custom use caching, because Facebook_Cache overwrited api() method. But here is what is bothering me:
I think it's too much inheritance.
It's all very tight coupled - like look how i had to specify 'Facebook_Custom::api' instead of 'parent:api', to avoid api() method loop on Facebook_Cache class extending.
Overall mess and ugliness.
So again, this works but I'm just asking about patterns / ways of doing this in a cleaner and smarter way.
Auxiliary features such as caching are usually implemented as a decorator (which I see you already mentioned in another comment). Decorators work best with interfaces, so I would begin by creating one:
interface FacebookService {
public function api();
public function getUser();
}
Keep it simple, don't add anything you don't need externally (such as setPersistentData). Then wrap the existing BaseFacebook class in your new interface:
class FacebookAdapter implements FacebookService {
private $fb;
function __construct(BaseFacebook $fb) {
$this->fb = $fb;
}
public function api() {
// retain variable arguments
return call_user_func_array(array($fb, 'api'), func_get_args());
}
public function getUser() {
return $fb->getUser();
}
}
Now it's easy to write a caching decorator:
class CachingFacebookService implements FacebookService {
private $fb;
function __construct(FacebookService $fb) {
$this->fb = $fb;
}
public function api() {
// put caching logic here and maybe call $fb->api
}
public function getUser() {
return $fb->getUser();
}
}
And then:
$baseFb = new Facebook_Session();
$fb = new FacebookAdapter($baseFb);
$cachingFb = new CachingFacebookService($fb);
Both $fb and $cachingFb expose the same FacebookService interface -- so you can choose whether you want caching or not, and the rest of the code won't change at all.
As for your Facebook_Custom class, it is just a bunch of helper methods right now; you should factor it into one or more independent classes that wrap FacebookService and provide specific functionality. Some example use cases:
$x = new FacebookAuthWrapper($fb);
$x->redirect_to_auth_dialog();
$x = new FacebookBatchWrapper($fb);
$x->api_batch(...);
It is indeed too much inheritance. Looks like a job for Facade design pattern. Use composition instead of inheritance to have more flexibility. Delegate any methods you use to appropriate objects.
For example if any of the underlying classes changes, you can just change your methods to adapt to the changes, and you won't have to worry about overriding any of the parent methods.
Generally yes, it is not a good idea to assign multiple responsibilities to one class. Here, the responsibility of the class would be to represent an external API.
I have done some thing like that for yahoo sdk let me put it, give it a try :)
Lets assume Facebook is the class in sdk you are using for all end method calls.
You can create a new class(as your frame work allows) and assign a variable of the class to the instance of the Facebook Class .
Use __call() for all methods of Facebook and put your custome ones in the wrapper class.
for all undefined methods it wrapper it will go to Facebook Class and there is no inheritance involved at all.
It worked for me . Hope it helps :)
Class MyWrapper
{
protected $facebook;
public function __construct()
{
$this->facebook = new FaceBook();
}
public function __call($method,$args)
{
return $this->facebook->$method($args);
}
///define Your methods //////////
///////////////////////////////////
}
$t = new MyWrap;
$t->api(); // Whatever !!!!
edited :
You don't need to create multiple wrapper for more than one classes following can be done,you just need to take care at the method call time, have to suffix the variable name holding instance of the wrapped class.
Class MyWrapper
{
protected $facebook;
protected $facebookCache;
public function __construct()
{
$this->facebook = new FaceBook();
$this->facebookCache = new FacebookCache();
}
public function __call($method,$args)
{
$method = explode('_',$method);
$instance_name = $method[0];
$method_name = $method[1];
return $this->$instance_name->$method_name($args);
}
///define Your methods //////////
///////////////////////////////////
}
$t = new MyWrap;
$t->facebook_api(); // Whatever !!!!
$t->facebookCache_cache();
i think repository design pattern will be better in this situation. although i am not from php but as per oops it should solve your issue..
I've encountered an architectural issue with my application. I've rolled my own (very basic) MVC, and one of my models is a database object: class MySQLDatabase { }
There's a number of places in which I'd want to use my database object, without creating duplicate instances. Inside my controller, I have declared public $db; and within the __construct { } I have $this->db = new MySQLDatabase;
Question:
How do I use $db within my other classes--they're all instantiated within the controller's __construct { } as well... would I declare global $db at the top of all my classes that require database connectivity?
I'm used to global variables being declared in the global scope as regular variables, and then using the global keyword to reference the global scope... I'm not sure if that applies to variables declared within a class (my controller.)
I would stay away from using globals or the Singleton pattern (which is essentially a global anyway), and try and find some alternatives. Additionally you are talking about a database connection, by using the Singleton pattern you are saying that there will never be more than one database connection, whilst that is generally true in smaller applications, as they grow larger you won't be able to accomodate multiple connections.
Once you make something global then you lose the automatic contraints of where it can be used/modified. Using MVC a view shouldn't be used for anything other than to display data, by using a global/singleton it is up to the developer to not make use of the globals. Whereas with a different design they don't have that option.
You mentioned you've created your own MVC framework, so I imagine the classes you want to use it in are your models? Correct me if they are anywhere else.
If your models extend from a common base class then you could pass your database object to that class as a static variable which can be assigned to any new instances in the construct or using a factory method in the factory method.
This isn't to say that globals or singletons should be avoided at all costs, but definitely try consider the alternatives that could lead to a neater design.
Here's some reading on the Singleton pattern if you're interested:
Patterns I Hate #1: Singleton
Why Singletons are Evil
Singleton Considered Stupid
Use your singletons wisely
There are many more out there...
If I understand correctly you have a single controller that instantiates the database object and it also takes care of instantiating other classes. If so, you could implement some form of dependency injection either passing the db object in the constructor of the other classes or creating a setter method.
A good blog article on the subject:
http://www.potstuck.com/2009/01/08/php-dependency-injection/
I Think you going about this the wrong way, you should not be performaing quesries to the database from you controller.
this means that the below is invalid.
class ControllerIndex extends Controller
{
public function index()
{
$this->db->selectAll("table");
}
}
There should be a layer that separates your controller from your database interface, this is where a Model comes in.
You should have a models folder that contain classes for actions taken such as users,posts,logging etc.
class Users_Model extends Model
{
public function getUser($id)
{
}
}
The model class should be part of your system core, and should extend your Database Class, this way within your main controller you should be loading the models via the ModelLoader class.
for example:
class ModelLoader
{
private $models = array();
public function __get($model)
{
//load (/application/models/?.php) and initiate it here
//Storing it in models array above
}
}
Then in your main controller:
class Controller
{
private $model;
public function __construct()
{
$this->model = new ModelLoader;
}
}
this way your bringing your loader into scope for the child controller:
class Controller_index extends Controller
{
public function index()
{
$user = $this->model->users->getUser(22);
}
}
Hope this helps!
I think what you need here is a singleton for you Database object :)
See here for more details : http://en.wikipedia.org/wiki/Singleton_pattern
Edit with sample singleton for php :
<?php
class UniqueObject {
private $_uniq = null;
//private cause you don't want to instanciate the classic way
private function __construct() {
//...
}
//check if unique object exists or not, then return it
public static function uniq() {
if(!self::$_uniq)
self::$_uniq = new UniqueObject();
return self::$_uniq;
}
}
//call your unique object whenever you need it
UniqueObject::uniq();
?>
(it's late, i hope i didn't do any mistake :))
Don't use singletons. It's much better to explicitly pass around data. For example:
abstract class Controller {
private static $conn; // could be an array for multiple connections
final protected function getDBConnection() {
if (!$this->conn) {
$this->conn = new DBConnection();
}
return $this->conn;
}
abstract public function process(Request $r);
}
class HomePageController extends Controller {
public function process(Request $r) {
$results = $this->getDBConnection()->query('SELECT stuff FROM foo;');
// do stuff with $results
}
}
You could also have an explicit model object you pass around, e.g. the one that represents the user, but that may be overkill for your project.
You'll need to use a singleton pattern. They give examples in the php docs
<?php
class Example
{
// Hold an instance of the class
private static $instance;
// A private constructor; prevents direct creation of object
private function __construct()
{
echo 'I am constructed';
}
// The singleton method
public static function singleton()
{
if (!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
// Example method
public function bark()
{
echo 'Woof!';
}
// Prevent users to clone the instance
public function __clone()
{
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
}
?>
http://php.net/manual/en/language.oop5.patterns.php
How is it done?
I have a Model class that is the parent to many sub-classes, and that Model depends on a database connection and a caching mechanism.
Now, this is where it starts getting troublesome: I have no control over how each object gets instantiated or used, but I have control over methods that get used by the sub-classes.
Currently I have resorted to using static methods and properties for dependency injection, as such:
class Model
{
private static $database_adapter;
private static $cache_adapter;
public static function setDatabaseAdapter(IDatabaseAdapter $databaseAdapter)
{
self::$databaseAdapter = $databaseAdapter;
}
public static function setCacheAdapter(ICacheAdapter $cacheAdapter)
{
self::$cacheAdapter = $cacheAdapter;
}
}
Which has worked out well, but it feels dirty (it creates a global state for all Models).
I have considered the factory pattern, but that removes the control of the instantiation from the sub-classes (how do I instantiate an object with a variable number of parameters in it's constructor?).
Now I am at a loss. Any help would be appreciated.
As far as I know this is a perfectly acceptable alternative. Another possibility suggested by Sebastian Bergmann, the creator of PHPUnit, is to have a $testing static property. You can read his recent article regarding the Testing of Singletons. It sounds like you have similar issues.
You're solution would be fine for setting default adapters, but I'd add a way for the individual models to have a different adapter. Consider this:
abstract class Model {
protected $_database_adapter;
protected $_default_database_adapter;
public function getDatabaseAdapter() {
if(!$this->_database_adapter) {
if(self::$_default_database_adapter) {
$this->_database_adapter = self::$_default_database_adapter;
} else {
throw new Exception("No adapter set yet");
}
}
return $this->_database_adapter;
}
public function setDatabaseAdapter(IDatabaseAdapter $databaseAdapter) {
$this->_database_adapter = $databaseAdapter;
}
public static function setDefaultDatabaseAdapter(IDatabaseAdapter $databaseAdapter) {
self::$_default_database_adapter = $databaseAdapter;
}
}
Of course you could extract all static methods/properties into a Registry, Container or anything else as central.
For example, perhaps you don't want to collect data from the same database host over your whole application. Then your original script would look like the following:
Model::setDatabaseAdapter($default);
$my_model->query('....');
Model::setDatabaseAdapter($another_adapter);
$my_other_model->query('....');
Model::setDatabaseAdapter($default);
which is awfully alike:
mysql_select_db('default_db');
mysql_query('...');
mysql_select_db('other_db');
mysql_query('...');
mysql_select_db('default_db');