Replicating Codeigniters load function - php

I have recently been playing around with Codeigniter to see what I can learn from it. I came across the load function and was wondering if anyone knows how its done. Basically, it looks something like:
$this->load->model('Model_name');
$this->Model_name->some_function();
Now load is obviously a class and an instance is created and called load. And load includes the class "Model_name" and creates an instance of it. But the part I cant work out, is how does the load class create a "class variable" named "Model_name" to be used as in the second line of the code? And how would I actually go about implementing this in php.
Thanks.

What the class basicly does is remembering all the created objects ($this for instance) and then assign the newly created class by reference as a variable in those classes.
function Load($className)
{
$newClass = new $className();
foreach($this->objects as &$object) //objects is array with created objects
$object->$className = $newClass;
}
however, it does a lot more stuff in the background than that. You know you can just open 'loader.php' and then read what it does, right?

This kind of things work with interpreted languages like PHP. Though it can be very confusing to picture this, specially if you are experienced with strict languages such as C++, C# etc.
The idea is, there are PHP functions that can execute PHP code and the result will be visible elsewhere in the script.

Related

Filepath of File Where SRO Method was Called

I have a class:
Class General
{
...
}
And I am accessing a method, like this, from another file:
General::the_method($params);
Is there a way to determine, from WITHIN the class, the filepath of WHERE the method was called? Not the filepath of the General class, but of the separate function, prbably many folders away, that has called the method?
I've tried ReflectionClass::getFileName(), however it seems this only works on fully instantiated objects (ie, if I'd done $general = new General, which I don't want to do). I figured it wouldn't work given the description of the functionality but I thought I'd give it a try. No dice, sadly.
So: is this possible?
EDIT: We are trying to accomplish this WITHOUT a second parameter passed to the function.

How to find out which objects on a page use a certain class

I have an old site to bring up to standard but I have to approach things in a certain way due to timing issues and certain restrictions preventing my urge to restructure the whole site properly from the bottom up.
Most of the work involves updating various include files.
So, these include files are called into a page which uses a class to generate an object, as usual,
The Problem:
There are lots of pages and they are not consistently coded (thanks to sub-standard previous developers on the site), so sometimes the class I want to use is in an object called $database, sometimes on other pages the object is called $dataBase, $connection, etc. etc.
There are several includes that I am working on and I feel that having to create a new object for each include on each page is extremely inefficient, hence this question:
Can I find out from PHP which, if any, object variables use a certain class?
An illustration:
Page index.php
require "class.sausages.inc.php";
$hotdog = new sausages();
$hotdog->somefunction();
//etc. etc.
include "some_file_i_need_to_work_on.php";
include "/folder/some_other_file_I_work_on.php";
//etc. etc.
Page index2.php
require "class.sausages.inc.php";
$hotdogs = new sausages();
$hotdogs->someOtherfunction();
//etc. etc.
include "some_file_I_need_to_work_on_3.php";
include "/folder/some_other_file_I_work_on.php";
//etc. etc.
So I need to work on the includes and so for each include file I do not know for sure the $name of the variable object created in the includes parent file. All I have is that it uses the class sausages.
Solution attempts
I read how to check if object of a class already exists in PHP? which has pretty much the same issue but the solution marked here is to generate a global, which I'm feeling is another layer and to be honest I'm not quite comfortable with it as an efficient solution.
What I am trying to avoid is a situation where each include on a particular page has to generate its own object, all from the same class (usually) established in the parent page.
As there's no guarentee in one include if another include is included, I don't think I can generate an object that the includes can all use collectively, or if I can, how can I do that?
What I would Like
I want to be able to find a way to establish in PHP:
has any object been generated using this class?
yes? Use that object in this include.
no? generate a new object from the class file.
Is this possible?
Notes:
There are about a dozen include files,
There are a lot of parent pages (50+). I think editing each one would be inefficient (but this will be done at a future point)
Some parent pages contain some include files, some contain others. There's no guarentee which includes are included in which files ( as far as I can tell so far).
Most but not all parent pages have already established a class object.
PHP 5.6.16
as per:
http://php.net/manual/en/internals2.opcodes.instanceof.php
You can check if certain variable is an instance of certain class:
if ($hotdog instanceof sausages){
// use $hotdog
}
else {
// create and use $hotdog
}
But it will not tell you anything about other variables.
You can also use this:
http://php.net/manual/en/function.get-defined-vars.php
to get a list of all defined vars into an array. You can then loop through the array to see if there are any instances of the class that you are interested in.
foreach (get_defined_vars() as $var)
{
if ( $var instanceof sausage) {
// use this var
}
}
This solution will do what you want, however you should note that it is probably safer to create a new object. When you use an already instantiated object inside an include, you have no idea what other operations have been performed with that object. THe sausage may have very well be fried by the time you start using it and it may not do exactly what you want.
You should also look into a singleton pattern .
Using this pattern you can always get an instance of the same class and be sure that there is only one instance created across the app.
To go back to your old app, say that you want to make sure there is only one instance of sausages class across the app.
define a singleton method inside the sausages class
search/replace all the occurances of new sausages with sausages::singleton()
inside the include, you can then safely use $hotdogs = sausages::singleton();
This will make much cleaner code than trying to detect wether there are any global instances of sausages.
For conclusion; I ended up taking Karolis' answer and generating a search system for the correct object variable, without needing to instigate a new one if one is already defined:
At the top of each of my includes:
foreach (get_defined_vars() as $varKey => $variable) {
if(is_object($variable) && $variable instanceof sausages) {
$$varKey = $variable;
}
}
//$$varKey = this is the instance object.
Obviously code for if no instanceof is set is not detailed here, but this code works for me so far.

PHP Debugging Classes - Print everything

I am trying to figure out a big PHP Library and it isn't that well documented. I would like to know if there is a way to print out everything about the class. For example I am using the get_class_methods() function to print out the methods of that class and it prints out an area of just that class. I would like to see all the methods within the objects within that class as well. It would be nice to see the variables and everything else. This way I can print out everything and then use the browser's search to find stuff that I need. Is this possible, or is there a method out there that already does this? I'm not that well versed in PHP so if you can give me a function that would be awesome.
PHP has a built in library called Reflection that allows you to analyze classes and objects in intricate detail.
You can get all the methods in a class like so:
<?php
$class = new ReflectionClass('Apple');
$methods = $class->getMethods();
var_dump($methods);
For class properties (member variables):
<?php
$class = new ReflectionClass('Apple');
$properties = $class->getProperties();
var_dump($properties);
A good IDE will help you navigate through the code, start debugging sessions and inspect properties values in execution time.
I felt in love with PHPStorm some years ago, and still today it's my favourite IDE. It even has a Vim plugin which emulates vim =)
There is a Structure view on that IDE, which shows the, well :), code structure of a file. This means every property and method of the opened class file. There is a Project view which is like a directory browser too.
Second recommendation will be to install ack (http://www.beyondgrep.com). PHPStorm has a really efficient searching mechanism, but sometimes you just want to search the entire subdirectories of a project for a regular expression. It's a neat tool also.
My two cents. :)

Load model into $this scope

I'm doing a learning exercise where I'm building a pretty basic MVC framework. I'm really only doing this to learn more about OOP and it's pros, cons and common pitfalls.
I'm trying to replicate a behaviour, or syntax might be more correct, similar to the very popular framework codeigniter.
That is, I want to manually be able to load a Model from inside my Controller.
Here's how I want to perform it, and subsequently use it.
$this->load->model("mymodel");
$this->mymodel->some_function();
I have my loader working, it tries to run the class and this is how the load->model code looks like
public function model($model)
{
if(file_exists(APPLICATION.'models/'.$model.'.php'))
{
include(APPLICATION.'models/'.$model.'.php');
$this->{$model} = new $model;
}
}
The problem I am having is I get a error running this code saying that the class $model (this should be transformed into mymodel in this case) doesn't exist.
How do I make it so that $model translates into mymodel so the code would perform a action as such: new mymodel;
Thanks for any help, I'm quite the novice in OOP so I might have gotten confused here but really cannot seem to figure this out :/
$this->{$model} does, however, translate into $this->mymodel.
Instead of creating a new thread, I'll add to this.
My next issue has already arisen, since it's basically a followup problem I'll add it here too.
$this->mymodel->some_function() returns the following error;
Notice: Undefined property: Home::$mymodel in C:\xampp\htdocs\application\controllers\home.php on line 16
This error shows when running $this->mymodel->some_function();
Home is the loaded controller.
Hultin

In PHP, is there a way to get all declared classes in a specific namespace?

I'd like to get the names of all classes within a specific namespace in PHP. Currently, I'm attempting to do some magic via reflection on a specific list of named classes, but I'd like to do it without knowing the names ahead of time.
I've tried calling get_declared_classes(), but for whatever reason, classes that I do have available are not showing up. I can call get_declared_classes(), not see Event in the list, then immediately call $x = new Event() without a problem. Something like the following, which I would think should cause a problem...
if (! in_array('Event', get_declared_classes())) { $x = new Event(); }
...works fine. I'm wondering if namespacing these classes and retrieving that way would help alleviate the problem. Is this possible?
EDIT: For clarification, let me add that I am not currently using namespaces, and I am not specifically trying to achieve something from the above listed code. What I want is to get the names of all classes I have declared. Despite the fact the class declarations for all of them are being hit before I call get_declared_classes(), they are not all appearing in the list. I was hoping that namespacing might help solve the problem.
EDIT2: Several people have pointed out that the classes may be autoloaded. I tested this by doing the following. echo(class_exists('Event')) returned a value of 1. echo(class_exists('Event', FALSE)) returned a value of 0. The second, optional parameter to class_exists is whether or not to autoload. So, apparently the class is being autoloaded. That answers that.
So, next question - how do I prevent this? I'm using a framework that really doesn't give me much low-level control. Is there a way to force autoloading, THEN call get_declared_classes, or for get_declared_classes to fire an autoload first?
You do not need to hard code it in the code, you can use variable name:
$class_name = 'Event';
if (!in_array($class_name, get_declared_classes())) {
$x = new $class_name();
};
See similar code in action here: codepad.org/hCLE4ToA.
Also some classes may not appear in get_declared_classes()'s result, because they may not be loaded at the time this function is called. It may be the case if they are autoloaded after you try to instantiate them. See more on autoloading classes here: php.net/autoload.
Does it answer some of your questions? Did it help?

Categories