I am having problem with implementing custom session handler in php.
The code:
http://pastebin.com/9QV9f22Q
I initialize this once in my frameworks bootstrap, after I have connection with db:
require_once 'DbSession.php';
$session = new DbSession();
session_start();
But then I can't view my page. Firefox gets 302 Status with "Server not found" error. Firebug says that content is 5k long, but I can't view the page.
Log after one reload:
http://pastebin.com/JYe14nGR
I wonder why it still "loses" that created DbSession instance. Do yo have any ideas? TIA
Your code is based on a false premise: that you can return a different object from a PHP constructor. Quite the opposite: PHP entirely ignores the return value from a constructor.
Here's what's actually happening.
When your code calls:
$session = new DbSession();
the $firstTime == false check runs, meaning getInstance() gets called.
getInstance finds no existing instance, so it calls setup().
setup() calls new DbSession() again, this time passing in the argument preventing another call to getInstance(). It creates the object, registers it as the session handler, and returns it.
getInstance shoves the object in a static variable, and then returns it to the original constructor call. The original constructor call then drops the existing object on the ground and returns a brand new copy of itself.
You can fix some of this insanity by never instantiating the object outside of setup/getInstance(). Try making the constructor protected and only ever calling getInstance().
However, none of this explains why the code is malfunctioning for you. In fact, we can't explain it either. We're missing all the rest of the code, including what database adapter you're using, what ORM you're using (or even if you are using an ORM, your class and method names suggest it), what framework(s) might be involved, etc.
Try cutting all of the actual database touching from the class. Just write files on disk. Get that working first, then introduce the database layer. Chances are that your error will become obvious at that point.
Related
I'm updating a PHP framework I've written. It used to just use a default behavior for routing. For example consider a case where the request goes to domain.com/package/controller/method...
$url = ["package", "controller", "method"];
//Check if package exists...
//Check if controller exists in package...
//Check if method exists in controller...
This is all well and good, and works perfectly. However, I wanted to add some additional functionality to my router. That functionality being the ability to define custom routes, and pass an anonymous function which does whatever you want.
However, supposing that the request does not match any of the user-defined routes, I want to use the default functionality I have now to check if there are additional possible routes. That way I can update old projects with the new framework and not have them break, and additionally...I just like this default behavior because most of the time routes are not that complicated and defining routes feels like a violation of DRY to me.
The problem is that I don't want to pass the user-defined routes as an array to the object constructor. Rather, I want the user to call them as methods on the base application object similar to how laravel or express handles this.
The problem is that I want the default route checking to happen AFTER the user's defined routes have been checked not before. This quasi-code might help you understand what I mean...
class App
{
__construct
{
//Check Default Routing
}
private function get()
{
//Get Request
}
private function post()
{
//Post Request
}
private function put()
{
//Put Request
}
private function delete()
{
//Delete Request
}
}
app::get();
In the above case, the default routing would take place before the user-defined routes are called. I looked at the PHP consrtuctor/destructor page and learned about __destruct. However, after reading this question I'm a little bit unsure this would work.
PHP.net says...
The destructor method will be called as soon as there are no other
references to a particular object, or in any order during the shutdown
sequence.
The first part of that explanation sounds like exactly what I want. I.E. as soon as all of the methods have been called on the application object, we'll run the __destruct function which will check if the user-defined routes were fruitful, and if not, check if the default routing system yields any results.
The problem is that I'm not sure if this is bad practice, or simply won't work. Can I require a file, set my controller, and then call a method on that controller from within __destruct? Are there limitations that would effect the code within these controllers? Supposing that there is a problem using __destruct this way, what are my alternatives, keeping in mind I don't like either of these solutions...
Having the user call the default routing as a method at the end of their script.
Passing routes in as arrays to the constructor.
I think you're confused here. Take note of this from the PHP Manual
The destructor method will be called as soon as there are no other references to a particular object, or in any order during the shutdown sequence.
To put this a different way, there's two reasons to call a destructor
The class is being garbage collected. In other words, you've overwritten or unset all the references to the class instance. This means you can't directly call this class anymore
The PHP script has reached its end and the thread is shutting down.
In other words, there's nothing left for the class to do. But in your own statement you say this
The first part of that explanation sounds like exactly what I want. I.E. as soon as all of the methods have been called on the application object, we'll run the __destruct function which will check if the user-defined routes were fruitful, and if not, check if the default routing system yields any results.
There is no "and" here to work with. That's the point. In fact, there's very few places you would use this.
What you need is to think in layers. So you'd have a controller layer that you'd call to check the methods. In turn, that controller opens a new layer that checks user functions. That class or method should return something or throw an Exception if it fails. On failure it can then try to use default methods. This is how you need to structure your program. Trying to use a destructor to do this would likely only confuse people. Make the data flow explicit, not implicit (which is what magic methods do).
I'm afraid I'm rather new to unit testing.
I have a PHP class called "dbRecord" that I use to abstract database tables/records and am trying to apply unit testing to it. When I do so though, the mysqli object that it uses seems to break.
As an example, I have a user class (an extension of the abstract dbRecord class) that works quite nicely if I create and save a user in a shell. That would be something like this:
$u = new userClass();
$u->setEmail('foo#bar.com');
$u->save();
That works very nicely if I use it in a web site or from a php shell. It creates an object, sets the e-mail value, and then saves it in the database, assigning the auto-incrementing id field back to the $u object.
If I try to create a unit test though, it fails upon saving the record. The error is happening when it tries to use mysqli::real_escape_string, but it happens with any other member of the mysqli object (I have tested that just in case). The error I get is:
mysqli::real_escape_string(): Couldn't fetch mysqli
So I assume there's something I'm failing to understand in the scope of things when doing the unit test. Here's the full code of the test I'm running:
<?php
require_once "../dbTemplate.php";
class TestOfUserClass extends PHPUnit_Framework_TestCase {
function testAssignUserValues(){
$usr = new userClass();
$usr->setEmail('foo#bar.com');
$this->assertTrue($usr->getEmail() == 'foo#bar.com');
$usr->save();
}
}
The code that's actually throwing that exception is in the save call. Here's what it looks like:
public function save(){
if($this->_isNewRecord){
// we're creating a new record
$query = "INSERT INTO `" . $this->_mysqli->real_escape_string($this->_tableName) . "`";
...
At this point I'm rather lost as to why it's not able to use that mysqli instance. Again, this works perfectly under regular usage (either through apache on a web page or through a php shell). It's only when using the test cases that it dies. I tried it with both Simpletest and PHPUnit, with the same results.
The structure of how that mysqli object is accessed goes like this:
In my test file (test1.php), "../dbTemplate.php" is included at the top.
In dbTemplate.php:
the mysqli object is created at the top, assigned to a variable called $mysqli.
the dbRecord abstract class is then defined
in that definition's construct, $this->_mysqli is assigned the value of $mysqli.
The test file is exactly as quoted above.
Then of course, I run "phpunit test1.php"
Does anyone see what I'm doing wrong here?
You will want to instantiate your object being tested in setUp() as opposed to the testing function. If you get an exception there then that usually means the path to dbTemplate.php can't be resolved from the test folder.
Without looking at the guts of your class it's hard to explain exactly, but generally speaking if you are not using autoloading, phpunit will not be able to resolve the locations of other files that are located outside of the testing root folder. Using an autoloader in bootstrap.php, however, helps with this. See PHPUnit Bootstrap and Autoloading Classes.
I have an autoloader that is registered using spl_autoload_register():
class MyAutoLoader{
public function __construct(){
spl_autoload_register(array($this, 'loader'));
}
public function loader($className){
var_dump($className);
}
}
$al = new MyAutoLoader(); //Register the autoloader
From the var_dump(), the autoloader seems to be called on lots of things, things that are data to be inserted into a database, parameterized SQL queries and what not:
string 'name' (length=4)
string 'a:2:{s:5:"label";s:4:"Name";s:8:"required";b:1;}' (length=48)
string 'en_US' (length=5)
string 'object' (length=6)
string 'name = ?' (length=8)
These things will never be classes so should never be loaded using new or class_exists(), etc.
Under what circumstances/function calls are autoloaders called? I would like to put a stop to autoloading "classNames" that are not classes from being called, because each $className is checked using file_exist(), and having these data strings checked is pretty inefficient.
Problem resolved. I first did a back trace as suggested by Brad and dumped the traces to a file (just add a small snippet that opens a file and appends to it).
Obviously, the trace was very big, but I picked the simplest one I could find. Incidentally, that trace happened to be one that called a database (ORM) wrapper I have written to wrap around the awesome RedBean ORM library. The results from me dumping $className also validates that, because those strings are data are going into or coming out of the database.
Having said that, I have a __call() that intercepts methods to my database wrapper, does some processing, pass it to RedBean, process the result, and then sends it back to the caller.
Problem: During the processing, I am making calls to is_subclass_of() and instanceof, which will obviously ask the autoloader to try and load the class (since we don't have any class called name =? loaded, nor does it exist).
The solution was to actually make sure we have an object before calling is_subclass_of() and instanceof: if(is_object($someproperty) && is_subclass_of($someproperty)).
If $someproperty is not an object, the if immediately short-circuits and instanceof and is_subclass_of() is never called, which means the call to the autoloader is never made.
As mentioned by brad, having all sorts of things going to the autoloader to be included using require_once can be a huge security risk and at the same time, hitting the file system so many times using file_exists() is pretty inefficient too.
So, in conclusion, the autoloader is called every time you use instanceof, is_subclass_of, other class-type functions, class-exist functions and reflection methods, as Charles motioned in his answer.
So, the moral of the story is that if you plan to use a class-type function, or any of the functions mentioned above on a variable of mixed type, check it first before passing it to the class-type function.
Under what circumstances/function calls are autoloaders called?
I realize that this has ended up basically being a secondary question given the problems noted in the comments, but it's still worth answering.
Autoload functions, that being a __autoload() function in your code or callbacks registered through spl_autoload_register, are called when -- and only when -- PHP needs to access a class that has not been defined. This is done everywhere with few exceptions, such as class_exists, which have arguments that tell PHP not to call any autoloaders.
The PHP manual has a page dedicated to autoloading. I recommend reviewing it if there's any confusion.
You can use debug_backtrace or debug_print_backtrace to find out where exactly the auto-loader function is being called.
Technically it should only be called by PHP when a script references a class name that does not exist.
My code is located here: https://github.com/maniator/SmallFry
Should I make it so that that the App class does not have to use static functions but at the same time be able to set and set variables for the app from anywhere?
Or should I keep it how it is now with App::get and App::set methods?
What are the advantages and disadvantages of both?
How would I accomplish that 1st task if I was to undertake it?
Related Question
Sample code:
//DEFAULT TEMPLATE
App::set('APP_NAME', 'SmallVC');
//END DEFAULT TEMPLAT
//
//DEFAULT TEMPLATE
App::set('DEFAULT_TEMPLATE', 'default');
//END DEFAULT TEMPLATE
//DEFAULT TITLE
App::set('DEFAULT_TITLE', 'Small-VC');
//END DEFAULT TITLE
//LOGIN SEED
App::set('LOGIN_SEED', "lijfg98u5;jfd7hyf");
//END LOGIN SEED
App::set('DEFAULT_CONTROLLER', 'AppController');
if(App::get('view')){
$template_file = $cwd.'/../view/'.App::get('view').'/'.App::get('method').'.stp';
if(is_file($template_file)){
include $template_file;
}
else {
include $cwd.'/../view/missingview.stp'; //no such view error
}
}
else {
App::set('template', 'blank');
include $cwd.'/../view/missingfunction.stp'; //no such function error
}
I think you have a feeling that static is bad. What I am posting may seem fairly crazy as it is a massive change. At the very least hopefully it presents a different idea of the world.
Miško Hevery wrote static methods are a death to testability.
I like testing, so for that reason I don't use them. So, how else can we solve the problem? I like to solve it using what I think is a type of dependency injection. Martin Fowler has a good but complicated article on it here.
For each object at construction I pass the objects that are required for them to operate. From your code I would make AppController become:
class AppController
{
protected $setup;
public function __construct(array $setup = array())
{
$setup += array('App' => NULL, 'Database' => NULL);
if (!$setup['App'] instanceof App)
{
if (NULL !== $setup['App'])
{
throw new InvalidArgumentException('Not an App.');
}
$setup['App'] = new App();
}
// Same for Database.
// Avoid doing any more in the constructor if possible.
$this->setup = $setup;
}
public function otherFunction()
{
echo $this->setup['App']->get('view');
}
}
The dependancies default to values that are most likely (your default constructions in the if statements). So, normally you don't need to pass a setup. However, when you are testing or want different functionality you can pass in mocks or different classes (that derive from the right base class). You can use interfaces as an option too.
Edit The more pure form of dependency injection involves further change. It requires that you pass always pass required objects rather than letting the class default one when the object isn't passed. I have been through a similar change in my codebase of +20K LOC. Having implemented it, I see many benefits to going the whole way. Objects encapsulation is greatly improved. It makes you feel like you have real objects rather than every bit of code relying on something else.
Throwing exceptions when you don't inject all of the dependencies causes you to fix things quickly. With a good system wide exception handler set with set_exception_handler in some bootstrap code you will easily see your exceptions and can fix each one quickly. The code then becomes simpler in the AppController with the check in the constructor becoming:
if (!$setup['App'] instanceof App)
{
throw new InvalidArgumentException('Not an App.');
}
With every class you then write all objects would be constructed upon initialisation. Also, with each construction of an object you would pass down the dependencies that are required (or let the default ones you provide) be instantiated. (You will notice when you forget to do this because you will have to rewrite your code to take out dependencies before you can test it.)
It seems like a lot of work, but the classes reflect the real world closer and testing becomes a breeze. You can also see the dependencies you have in your code easily in the constructor.
Well, if it was me, I would have the end goal of injecting the App dependency into any class (or class tree) that needs it. That way in testing or reusing the code you can inject whatever you want.
Note I said reuse there. That's because it's hard to re-use code that has static calls in it. That's because it's tied to the global state so you can't really "change" the state for a subrequest (or whatever you want to do).
Now, on to the question at hand. It appears that you have a legacy codebase, which will complicate things. The way I would approach it is as follows:
Create a non-static version of the app class (name it something different for now) that does nothing but proxy its get/set calls to the real app class. So, for example:
class AppProxy {
public function set($value) {
return App::set($value);
}
}
For now, all it has to do is proxy. Once we finish getting all the code talking to the proxy instead of the static app, we'll make it actually function. But until then, this will keep the application running. That way you can take your time implementing these steps and don't need to do it all in one big sweep.
Pick a main class (one that does a lot for the application, or is important) that you easily control the instantiation of. Preferably one that you instantiate in only one place (in the bootstrap is the easiest). Change that class to use Dependency Injection via the constructor to get the "appproxy".
a. Test this!
Pick another class tree to work on, based on what you think will be most important and easiest.
a. Test!!!
If you have more calls to App::, Go to #3
Change the existing App class to be non-static.
a. Test!!!!!!!!!!
Remove the AppProxy and replace with App in the dependency injectors. If you did it right, you should only have one place to change to make this switch.
Pat yourself on the back and go get a drink, cause you're done.
The reason that I segmented it out like this is that once a step is completed (any step), you can still ship working software. So this conversion could take literally months (depending on the size of your codebase) without interrupting business as usual...
Now, once you're done, you do get some significant benefits:
Easy to test since you can just create a new App object to inject (or mock it as needed).
Side effects are easier to see since the App object is required wherever it could be changed.
It's easier to componentize libraries this way since their side effects are localized/
It's easier to override (polymorphism) the core app class if it's injected than if it's static.
I could go on, but I think it's pretty easy to find resources on why statics are generally bad. So that's the approach I would use to migrate away from a static class to an instance...
If you don't want to have static functions but global access from everywhere WITHOUT passing the object to the places where it is actually needed then you pretty much can only use one thing:
A global variable
So you are not really better of doing that. But that is the only thing i can think of that would fulfill your requirements.
If you App object is something like an application config a first possible step would be to pass it to the objects that need it:
class Login {
public function __construct() {
$this->_login_seed = App::get('LOGIN_SEED');
self::$_ms = Database::getConnection();
}
changes into:
class Login {
public function __construct(App $app) {
$this->_login_seed = $app->get('LOGIN_SEED');
self::$_ms = Database::getConnection();
}
This is probably a noob question, so please be kind.
I'm trying to implement a cache on an expensive "activity" object. In the constructor I first check the cache to see if this Activity instance already exists. If not, I do all the queries to build up the object, serialize it and save it to cache. The next time I come in, I check the cache and my object is there, so I unserialize it. Now is my problem, how do I put that object into $this, the current object? I can't just say "$this = unserialize($row[0]);" That fails with the error message, "Cannot re-assign $this in ActivityClass.php". What am I missing?
Thanks a ton!
Mike
If you don't want your construction to leave the class, you can create a factory method:
class Activity
{
public static function Create(/* your params */)
{
// construct cache and key, whatever
$obj = unserialize($cache->get($key));
if ($obj) return $obj;
return new Activity(/* params */);
}
// rest of your stuff
}
You'll have to serialize only your object's internal state, i.e. its parameters (aka "member variables"). In fact, in this instance, serialize() isn't really what you want to do; rather, you want to store your ActivityClass's data to your cache, not the serialization of the entire object. This gets tricky, though, because as you add new parameters later you need to remember to store these in your cache as well.
Alternatively, you can implement a singleton or factory pattern for your ActivityClass. Since you say you're pulling the class from the cache in the constructor, I take it that only one instance of this class is meant to exist at any given time? In this case, you should make your class a singleton, by doing the following:
Make the __construct() method private or protected.
Create a public static method (I tend to call this getInstance()) that will check your cache for the object, or instantiate a new one and then cache it.
Now instead of directly instantiating a new ActivityClass object, you instead write $foo = ActivityClass::getInstance();, which gives you either a new object or unserializes and returns your cached one.
As you noticed, you cannot just override the current object as a whole.
Instead, a possibility would be to store the data you're serializing/unserializing into a property of your object.
This way, you wouldn't serialize your whole object, but only one of its properties -- and only that single property would be overriden when unserializing.
Typically, you wouldn't serialize the connection to the database, which could be another property of your object.
Another possibility would be to not have your object deal with its own (de-)serialization.
Instead, you should :
Use an external class to instanciate your object
With that external class being responsible of either :
Loading data from cache and pushing it into your object,
Or calling the right method of your class, to load data from the database -- and, then, save that object to cache.