Filepath of File Where SRO Method was Called - php

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.

Related

Include vs Extend for data access

This is a design question that has irked me because deep down I know I'm doing it wrong. This is not necessarily just a PHP problem, but I'm working on a PHP project now so that's where I'm coming from.
I'll just give you the scenario:
I have a JSON generation class that is used by a data access script. Basically it's the go-to URL for a website that instantiates the JSONGen class, which in turn looks at a static file and pulls the data that was requested, and sends it back as a JSON object. The file that contains the raw data has it all in array format to allow for easier reading and updating (so one doesn't have to sift through raw JSON data and risk syntax error, etc).
My question is in the accessing of that file.
What I did was to place a require([json file]) outside the class definition. Everything in the [json file] is assigned to one $JSON object.
In the class constructor, I do:
global $JSON;
$this->JSON = $JSON;
(Where $this->JSON is a private class variable).
This gives me access to the JSON from anywhere in the class, which is lovely.
It feels hacky, but I can't find anything anywhere that addresses this specific type of approach.
The problem is that once somebody decides to move the class or whatever, the only way they have of understanding the dependency of this file is in that there's a require statement in the header. Is that just how things work? Or is there a better way to do this?
Should I use extend and put the JSON into a class (THAT sounds really stupid to me), or continue forward with my include? Or should I never, ever include a file in a class like this and rather pass it to the constructor or some other access method?
This specific instance is a small project, and it just doesn't make sense to set up a DB for it. We can add to the file, modify the config, and the whole site updates.... so please don't tell me to switch to a DB- I'm looking for strategies for this specific problem in a more general sense.
Thanks!
Probably going to get downvoted for this one but here it goes...
class JSON_Response {
public static $JSON;
// don't let people make one of these it gives the illusion that there can be more then one
protected function __construct(){}
}
then in your file
JSON_Response::$JSON = $json;
and access if from anywhere as JSON_Response::$JSON;
and if there is anything that you commonly do to the json object (check a flag or something) you can just add a static method to the JSON_Response class.

Is there a way to call a method of a class instance in one line?

I work with a tiny framework, its main object is available for its childs (controllers, models, views) via
mainobject::instance()
Wiki of the framework recommends to add in desired controller method
$mainobject = mainobject::instance()
So it’s become available for models through the single variable. I am in doubt if this is really handy, to define that variable in every single model’s method to get for example global config variable.
class MyAnotherModel extends FrameworksModel
{
…
my_method() {
global $mainobject;
…
if ($mainobject->config['something_here'];
$mainobject->controller->othermodel->othermodelsarray['somestring'];
}
}
Anyway this is a huge string and I’d rather prefer to make it a bit larger calling an instance then to write two strings each time. I mean, write
mainobject::instance->config['goods']
mainobject::instance->controller->othermodel->othermodelsmethodgiveme('power');
But I don’t know if it is possible to implement, since controller class does not provide calling an instance as a variable. I suppose it may be possible via getter method… if there was such method. So what can I do without rewriting original mainobject class?
inb4 long strings are inconveniently to type — there is no problem since I can use abbrevs in emacs and make typing phrase short.

PHP workaround to extend classes of the same name?

I know extending a class with the same name is not possible, but I was curious if anyone knew of a way to load a class then rename it, so i can later extend it with the original name. Hopefully like something below:
<?php
//function to load and rename Class1 to Class2: does something like this exist?
load_and_rename_class('Class1', 'Class2');
//now i can extend the renamed class and use the original name:
class Class1 extends Class2{
}
?>
EDIT:
Well, I understand that this would be terrible practice in a basic OOP environment where there are large libraries of class files. But i'm using the CakePHP MVC framework and it would make great sense to be able to extend plugin classes in this way since the framework follows a well established naming convention (Model names, view names, controller names, url routes (http://site.com/users), etc).
As of now, to extend a CakePHP plugin (eg: Users plugin) you have to extend all the model, view, and controller classes each with different names by adding a prefix (like AppUsers) then do some more coding to rename the variable names, then you have to code the renamed url routes, etc. etc. to ultimately get back to a 'Users' name convention.
Since the MVC framework code is well organized it would easily make sense in the code if something like the above is able to be implemented.
I'm trying to work out why this would be necessary. I can only think of the following example:
In a context that you have no control over, an object is initialised:
// A class you can't change
class ImmutableClass {
private function __construct() {
$this->myObject = new AnotherImmutableClass();
}
}
$immutable = new ImmutableClass();
// And now you want to call a custom, currently non existing method on myObject
// Because for some reason you need the context that this instance provides
$immutable->myObject->yourCustomMethod();
And so now you want to add methods to AnotherImmutableClass without editing either Immutable class.
This is absolutely impossible.
All you can do from that context is to wrap that object in a decorator, or run a helper function, passing the object.
// Helper function
doSomethingToMyObject($immutable->myObject);
// Or decorator method
$myDecoratedObject = new objectDecorator($immutable->myObject);
$myDecoratedObject->doSomethingToMyObject();
Sorry if I got the wrong end of the stick.
For more information on decorators see this question:
how to implement a decorator in PHP?.
I happen to understand why you would want to do this, and have come up with a way to accomplish what the end goal is. For everyone else, this is an example of what the author may be dealing with...
Through out a CakePHP application you may have references to helper classes (as an example > $this->Form->input();)
Then at some point you may want to add something to that input() function, but still use the Form class name, because it is through out your application. At the same time though you don't want to rewrite the entire Form class, and instead just update small pieces of it. So given that requirement, the way to accomplish it is this...
You do have to copy the existing class out of the Cake core, but you do NOT make any changes to it, and then when ever you upgrade cake you simply make an exact copy to this new directory. (For example copy lib/Cake/View/Helper/FormHelper.php to app/View/Helper/CakeFormHelper.php)
You can then add a new file called app/View/Helper/FormHelper.php and have that FormHelper extend CakeFormHelper, ie.
App::uses('CakeFormHelper', 'View/Helper');
FormHelper extends CakeFormHelper {
// over write the individual pieces of the class here
}

Replicating Codeigniters load function

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.

Is there anyway to get the order of the OOP method being called?

For example lets say I have a set of classes and methods to do so:
$obj->method1()->method2();
Is there anyway for method1() to know with in itself that its the first method being called or for method2 to know that its the last?
Some more details
I just want to be able to build a set of these calls so that it either returns an instance of itself if the call to the method isnt at the end of the chain or return something different if its at the end.
For example
$obj->method1()->method2(); #Here method 2 will return lets say a string.
$obj->method1()->method2()->method3(); #Since method2 isnt at the end of the chain, it should return an instance of itself (or another object) here so that the chain could continue.
EDIT: anyone whoz trying to do this - it is a bad design pattern.
This does seem to be a duplicate. Refer to this question for more answers.
Not out of the box, not even with a Stack trace.
I guess you could put something together using constants or global variables:
Don't try this at home!
$GLOBALS["chain"] = array();
$obj->method1()->method2(); // method1 adds member to $GLOBALS["chain"],
// array_push($GLOBALS["chain"], __FUNCTION__);
// method2 does the same...
print_r($GLOBALS["chain"]);
That would give you the full chain - not yet which one is the last one, to do that, you would have to pass a flag to method2().
But it would be horribly hacky and pollute your code.
Is there a specific reason you need this for?
All you could do is find out which methods have been called so far, by setting some kind of global state in the class. But you can't find out what methods are being called after a method, and you wouldn't be able to tell the difference between methods in one chain and methods in another:
$obj->m1()->m2();
$obj->m3(); // You would think that m1() and m2() came before this in the same chain
You would need to have a method at the end of each chain to clear the global state in the class.
Since it seems you need to see which method comes next in a chain, this won't work for you.
I would say that this is a really bad design pattern, at least for PHP (and every other language I've worked in). Each method should do one thing only. If you need a method to either return a string or an object depending on what you need it for later, you are doing something wrong.
Granted, I have done something like this before. It was a meta-information class for images submitted by users -- you could set it up like this:
$meta = new ImageMeta();
$meta->first_name("foo")->last_name("bar")->email("baz")->id("guid");
But, if you did this:
$meta->first_name();
it would return a string. The default value for the first parameter was NULL, and if the method got NULL, it returned a string. Otherwise it set (and escaped) an internal value and returned $this.
At first I thought it was kind of cool, but it turned out to be a mistake. I hate using that class now. Just make one method/function do one thing only and you will be much happier.
I don't think this is possible, no -- at least, I've never seen anything about this.
(Out of curiosity : why would you need that ? Maybe it would be possible to use onther solution to solve your actual problem ?)
The only way this is possible is to let the methods save some global state.
If both methods are in the same class, you could add a variable to the class and let each class set a unique value.
But the question is if this is desirable. This kind of behavior is often not very smart in the long run.

Categories