[PHP] Zien welke functie een functie aanroept

Pagina: 1
Acties:
  • 203 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Eigenlijk een heel eenvoudige vraag: is er een mogelijkheid waarop ik, zonder het doorgeven van extra parameters, kan zien van binnen welke functie een andere functie aangeroepen wordt?

Ter verduidelijking:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function foo() {
  $calling_function = ''; // wat hier te doen?
  return 'foo wordt nu aangeroepen vanuit' . $calling_function;
}

function bar($param) {
  if ($param) {
    // do cool stuff
  }
  
  $var = foo(); // $var wordt "foo wordt nu aangeroepen vanuit bar"
}

function mil() {
  $var = foo();

  echo $var; // geeft: "foo wordt nu aangeroepen vanuit mil"
}

Na wat googlen en zoeken op php.net kwam ik erachter dat je met __FUNCTION__ de naam van een huidige functie kunt oproepen, maar daar heb ik hier niets aan, volgens mij.

Weet iemand een oplossing?

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 15:16
Bedoel je de stack trace? debug_backtrace() geeft je een heleboel info :)

Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Marcj schreef op donderdag 22 maart 2007 @ 20:02:
Bedoel je de stack trace? debug_backtrace() geeft je een heleboel info :)
Ja, maar zoals gezegd in de startpost weet ik niet hoe ik hiermee om moet gaan / denk ik niet dat dit is wat ik zoek. Ik heb het scriptje uit de startpost wat aangepast:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function foo() {
  $calling_function = debug_backtrace();
  print_r($calling_function);
  return 'foo wordt nu aangeroepen vanuit ' . $calling_function;
}

function bar($param) {
  if ($param) {
    // do cool stuff
  }
  
  $var = foo(); // $var wordt "foo wordt nu aangeroepen vanuit bar"
}

function mil() {
  $var = foo();

  echo $var; // geeft: "foo wordt nu aangeroepen vanuit mil"
}

mil();

De output hiervan is:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Array
(
    [0] => Array
        (
            [file] => C:\Program Files\Apache\Apache2\htdocs\test\backtrace.php
            [line] => 18
            [function] => foo
            [args] => Array
                (
                )

        )

    [1] => Array
        (
            [file] => C:\Program Files\Apache\Apache2\htdocs\test\backtrace.php
            [line] => 23
            [function] => mil
            [args] => Array
                (
                )

        )

)
foo wordt nu aangeroepen vanuit Array

Ik weet niet hoe ik deze output moet interpreteren: het lijkt alsof debug_backtrace alle functies opsomt die op de pagina voorkomen. Dit is echter geen oplossing voor mijn probleem; ik wil alleen de naam hebben van de functie die foo() aanroept. In dit geval run ik alleen mil() dus wil ik alleen "mil" gereturned zien... :?

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

op [0] staat de functie die debug_stacktrace aanroept (foo dus), op [1] staat de aanroepende functie (mil dus), op [2] staat de functie die de voorgaande weer aanroept, etc.. Het heet niet voor niets een stack :). Jij bent dus altijd geinteresseert in [1].

Overigens, als je dit voor andere dingen gaat gebruiken dan om debug/profile-redenen dan is je design ruk :)

[ Voor 18% gewijzigd door .oisyn op 22-03-2007 20:33 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 15:16
De eerste entry van de array is de huidige functie (met id 0), de volgende is dan de functie die de huidige functie heeft aangevraagt, etc...

Heb je dat stuk op de pagina wel goed gelezen? Het lijk me dan niet zo moeilijk... bijv:

PHP:
1
2
3
4
5
6
7
<?php 
function foo() { 
  $calling_function = debug_backtrace(); 
  $calling_function = $calling_function[1]['function']; 
  return 'foo wordt nu aangeroepen vanuit ' . $calling_function; 
}
?>

Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
.oisyn schreef op donderdag 22 maart 2007 @ 20:31:
Overigens, als je dit voor andere dingen gaat gebruiken dan om debug/profile-redenen dan is je design ruk :)
Nou zeg :'(

Het is natuurlijk eenvoudig om een argument mee te geven aan foo:
PHP:
1
2
3
4
5
6
7
8
9
10
11
function foo($calling_function) {
  return 'foo wordt nu aangeroepen vanuit' . $calling_function; 
}

function mil() {
  $var = foo('mil');

  echo $var; // geeft: "foo wordt nu aangeroepen vanuit mil"
}

mil();

Maar ik vroeg me af of het ook niet anders kon, zoals mij dus net is uitgelegd :)

Waar wilde ik het voor gebruiken:
Ik maak in mijn cms gebruik van een eigen gemaakte gettext achtige functie. Maar ik wil graag bij elke string meegeven in welke functie deze staat. In veel functies heb ik tientallen strings. Het leek me wat overbodig om telkens de functienaam als argument mee te moeten geven:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function t($key, $function) {
  $language = array(); // from database
  return $language[$function][$key];
}

function mil() {
  if ($stuff) {
    return t('do cool stuff', 'mil');
  }
  else {
    return ($uncool) ? t('do uncool stuff', 'mil') : t('do nothing', 'mil');
  }
  return t('no stuff executed', 'mil');
}

Ik werd een beetje moedeloos van het idee dat ik op honderden plaatsen in mijn code de functienaam moet tikken. Het leek mij makkelijker als t() zou kunnen uitlezen welke functie een string wil hebben:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function t($key) {
  $calling_function = debug_backtrace(); 
  $calling_function = $calling_function[1]['function'];

  $language = array(); // van database
  return $language[$calling_function][$key];
}

function mil() {
  if ($stuff) {
    return t('do cool stuff');
  }
  else {
    return ($uncool) ? t('do uncool stuff') : t('do nothing');
  }
  return t('no stuff executed');
}

Los van het feit dat zo'n design ruk is ( ;) ), denk ik dat het een erg hoge last op de resources legt, en het kleine voordeel dat ik daarmee behaal staat niet in verhouding tot dit nadeel. Als iemand een ander idee heeft, hoor ik dat graag!

[ Voor 5% gewijzigd door Reveller op 22-03-2007 20:55 ]

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 15:16
Ik ben alleen benieuwd waarom je de functienaam nodig bent bij het vertalen van stukken tekst?

Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Marcj schreef op donderdag 22 maart 2007 @ 20:57:
Ik ben alleen benieuwd waarom je de functienaam nodig bent bij het vertalen van stukken tekst?
Ik onderhoud het product zelf, en voor mij geeft de functienaam een context aan voor de string. Als je een string goed wil vertalen, is een context altijd goed, want anders ga je maar letterlijk vertalen en dat kan als een tang op een varken slaan :)

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

  • SchizoDuckie
  • Registratie: April 2001
  • Laatst online: 18-02 23:12

SchizoDuckie

Kwaak

Je ontwerp is gigantisch flawed.

Je gaat toch niet de vertaling van een stukje tekst rechstreeks aan je code knopen :?

Maak gewoon een unieke key aan die beschrijft wat voor textje er moet komen:
DO_COOL_STUFF
DO_SOME_OTHER_SHIT
SHIT_BE_DONE

weet ik veel, wat je zelf maar wil hebben.
Dan kan je t() functie nog altijd blijven, en een globale var uitlezen waarin je de translate language definieert, die de keyword opzoekt uit je translate array / tabel en klaar :?

Stop uploading passwords to Github!


Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
@SchizoDuckie: dat is precies hoe ik het tot nu toe heb aangepakt:
PHP:
1
2
3
4
5
6
7
8
9
$t = array(
  'USER_EMAIL_TAKEN'        => 'The e-mail address %email is already taken.',
  'USER_EMAIL_DENIED'       => 'The e-mail address %email has been denied access.',
  'USER_EMAIL_ENTER'        => 'You must enter an e-mail address.',
  'USER_EMAIL_INVALID'      => 'The e-mail address %email is not valid.',
  'USER_EMAIL_SENDER'       => 'Email sender',
  'USER_EMAIL_SUBJECT'      => 'Email subject',
  // etc
);

Maar het leek me handig om de vertaling van de tekst te koppelen aan de functie waarin de tekst voorkomt, om zo een stukje context mee te geven. Maar ik sta een beetje alleen in de overtuiging dat dit handig is, merk ik :+

Ik kreeg het idee overigens van MyReact, wat op eenzelfde manier lijkt te werken. Zie myreact\global\non-www\plugins\locale\en_US\LC_MESSAGES\admin.po.php:
PHP:
1
2
3
4
5
6
7
$messages = array(
  "admin::lookup_user::fuzzy_search" => "Fuzzy search",
  "admin::global_search::global_search" => "Global Search",
  "admin::lookup_user::special_users_header" => "Special users",
  "admin::lookup_users::special_users" => "Special users"
  // etc
);

Ik lees de eerste regel als class: admin; method -> lookup_user; key -> fuzzy_search. Ik was wel enthousiast over deze werkwijze :)

[ Voor 28% gewijzigd door Reveller op 22-03-2007 23:14 ]

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 02:21

Janoz

Moderator Devschuur®

!litemod

Wat je in react ziet is (afaik) geen rechtstreekse koppeling met de code, maar gewoon een extra partitionering in de labels. Als je hiervoor je stacktrace gaat gebruiken kan ik het niet anders dan eens zijn met .oisyn.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 15:16
Waar je je in vergist is dat daar de opdeling te maken heeft met verschillende delen van het programma (deel: admin, subdeel: users opzoeken, key: fuzzy_search etc...) en niet direct met de functienamen van een programma. Zo kun je wel verschil in context maken als je iets wil zoeken binnen het admin gedeelte of gewoon op het forum.

edit: wat janoz dus ook zegt...

[ Voor 6% gewijzigd door Marcj op 23-03-2007 09:53 ]

Pagina: 1