0

I am attempting to create a controller that can detect if it is called from another controller in the application.

If it called directly via the URL, however, I need to know so I can perform some other actions.

i.e.

cheese/modulename calling potato/modulename is different to someone accessing site/cheese/modulename via URL - and I need to be able to pick up on this and act accordingly.

I am aware of:

 $this->router->class

but it will not work as I may have the same named class in another module (HMVC pattern as an FYI) that may want to call this controller (cheese/modulename calling potato/modulename as an example would return 'modulename' - so I can't use that as a check to see if it was called by itself.)

I basically need a check for:

controller was called via another controller = true / false

can anyone tell me how (or if I am being thick!)

I am doing this in the __construct() just in case your solution will have a problem with that (can't see why but you never know!)

EDIT

Thank you to Mohammad Walid for his answer.

For clarity the structure is

CLIENTS
    MODELS
    CONTROLLERS
        - Client
        - Api
    VIEWS
JOBS
    MODELS
    CONTROLLERS
        - Jobs
        - Api
    VIEWS

I will be calling the API from Client - but may also call it from another API (possibly) That may be In another Module

For Example the CLIENTS Api might get called from the JOBS Api Controller (I have no intention of doing this at present but it may be a possibility under different scenarios I haven't forseen and want to make it future-proof so I don't have a massive refactoring job in the future.)

GrahamTheDev
  • 22,724
  • 2
  • 32
  • 64
  • I think we have some grammar or punctuation issues here. What you're saying seems very unclear. – Sparky Jun 19 '14 at 17:33
  • editted - let me know if that is any clearer – GrahamTheDev Jun 19 '14 at 17:37
  • 1
    I guess you can put in a check for segments. `if($this->uri->segment(1) === 'potato'){ //called from URL }else{ //assume another class called this }` – MonkeyZeus Jun 19 '14 at 17:39
  • That is one approach - however I am trying to encapsulate this in a helper - if I can avoid it I don't want to have to write the correct URL segment for each controller as there are about 600 of them - but a good suggestion! Is there a way to get the URL segment of the controller that called it (if there was one?) – GrahamTheDev Jun 19 '14 at 17:41
  • I wish I had a more streamlined idea but I *think* that you might be limited by the capabilities of PHP and not just CodeIgniter. I consider myself a fairly advance PHP developer but hopefully some true PHP guru can provide better insight :) – MonkeyZeus Jun 19 '14 at 17:49
  • 1
    Might be useful: **http://stackoverflow.com/questions/2110732/how-to-get-name-of-calling-function-method-in-php** which links to **http://stackoverflow.com/questions/190421/caller-function-in-php-5/190426#190426** – MonkeyZeus Jun 19 '14 at 17:51
  • Thanks @MonkeyZeus - however using that `debug_backtrace();` doesn't seem like good practice in a production environment (I have however committed that to memory as a great function that I have actually never come across ><!) I think you are indeed correct and that the only way I could possibly implement this is to check via URL -> if URL == this methods URL then it is called directly would seem to work??!!?? – GrahamTheDev Jun 19 '14 at 18:45
  • In the words of my colleague: "*definitely maybe yes...but I'm not positive.*" It will be up to you to test this out and I think you have a very nice testing bed considering this needs to be done in 600 places, Good Luck! :) – MonkeyZeus Jun 19 '14 at 18:49
  • thanks for the help - I will have to see how I get on! – GrahamTheDev Jun 19 '14 at 18:51
  • 1
    Then in this situation, I think the only one solution is to use `debug_backtrace($options, $limit)` and to avoid memory consumption you can set the limit to `1`, however this parameter introduced in PHP 5.4.0, I hope this will help you. – Walid Ammar Jun 19 '14 at 20:20

2 Answers2

1

You can try this:

function is_called_via_url($controller_object){
  return $this->uri->segment(1) === get_class($controller_object);  
}

and in your controller:

if(is_called_via_url($this)){
  //do something
}

I'm not quite sure if passing $this as an argument in the constructor will work, but it worth try.

Reference and a hint from MonkeyZeus's comment.

Walid Ammar
  • 4,038
  • 3
  • 25
  • 48
  • Your answer is correct from the information I gave but unfortunately it won't work as the controller in question will be in the same folder as the controller that is calling it +1 and thanks for the suggestion. – GrahamTheDev Jun 19 '14 at 19:58
  • Thanks Mohammad - you were right with the logic - just avoided using URL in the end due to the above comments problem - but great suggestion and thanks again! – GrahamTheDev Jun 21 '14 at 08:13
0

From the comments there seems to be no way to do this without using debug_backtrace($options, $limit)

However the work-around I have ended up doing is to add a 'flag' within the authorisation module (which is called before all controllers)

The flag defaults to false.

If a controller from within my application calls the API page I turn this flag to true (is_application = true - I am currently just manually pasting this into the __construct of any controllers in my application that need to talk to my API)

I can then just do a simple

if(!is_application){
    //this was called directly from the URL not from within the application
}

from within the API controller.

Hopefully this will be helpful for others who are attempting this sort of thing and once again thank you to the people who took the time to comment / answer.

GrahamTheDev
  • 22,724
  • 2
  • 32
  • 64