0

I have this function in my class:

logMagic($mode)
{
    # mode
    # 1 = all, 2 = dir, 3 = file etc.

    # this is wrapped inside a switch statement
    # for eases sake here's the case 1: code
    $log['dir'] = 'DIRECTORY: '. __DIR__;
    $log['file'] = 'FILE: '. __FILE__;
    $log['meth'] = 'METHOD: '. __METHOD__;
    $log['fnc'] = 'FUNCTION: '. __FUNCTION__;
    $log['ns'] = 'NAMESPACE: '. __NAMESPACE__;
    $log['cl'] = 'CLASS: '. __CLASS__;

    return $log;
}

This is in a foo.php file. I then have a bar.php file where I call and init the class to use this function:

require_once 'foo.php';

$logger = new \Logger('trey.log', 'var/logs');
$logger->logMagic($logger::ALL);

My problem with this is, this will output (in a log file):

DIRECTORY: /var/www/dir
FILE: /var/www/dir/foo.php
METHOD: Logger::logMagic
FUNCTION: logMagic
NAMESPACE:
CLASS: Logger

My expected output was that it would return

DIRECTORY: /var/www/dir
FILE: /var/www/dir/bar.php
METHOD:
FUNCTION:
NAMESPACE:
CLASS:

Reading the docs does clarify this to me that this is normal.

Is there any way I can use magic constants from fileb.php in filea.php, without passing params to the function?

treyBake
  • 6,440
  • 6
  • 26
  • 57
  • Could https://stackoverflow.com/questions/40897981/is-there-any-way-to-carry-down-a-php-magic-constant-as-a-function-default provide some help? – Nico Haase Jan 25 '19 at 10:28
  • 2
    Possible duplicate of [PHP get line number from logging event](https://stackoverflow.com/questions/3215447/php-get-line-number-from-logging-event) – Nico Haase Jan 25 '19 at 10:30
  • @NicoHaase that doth be a dupe! I just didn't use the right words in the search engine to come across it, will close/remove mine :) thank you :) – treyBake Jan 25 '19 at 10:32
  • @NicoHaase though, it kinda is a solution, maybe not a full one. `debug_backtrace` will print an array etc. however, my function uses modes, so user can say $logger::METHOD to just get the method - using debug_backtrace will give them way more than the method – treyBake Jan 25 '19 at 10:34
  • As `debug_backtrace` returns an array, you have tou evaluate it. But I think that accessing just the first element (which should be the one calling the logger?) might do the job? Otherwise, you could mix both worlds: take some lines from the trace, and some stuff you know better than the trace – Nico Haase Jan 25 '19 at 10:38
  • @NicoHaase hmm I'll do some digging and see what I can come up with, if it's the case of mixing, I'll mark as dupe and be :) – treyBake Jan 25 '19 at 10:39
  • Additionally, share your answer. I don't think that the other question has a real **good** answer that contains all steps – Nico Haase Jan 25 '19 at 10:43
  • 1
    @NicoHaase yeah, think I'll see what I can conjur and I'll post an answer when I have something solid :) – treyBake Jan 25 '19 at 10:43
  • @NicoHaase I kinda worked around it, though.. I'm not sure it's an answer to my original question - suggestions? o.O – treyBake Jan 25 '19 at 15:30
  • If it solves your original problem, it's worth being shared – Nico Haase Jan 25 '19 at 15:35
  • @NicoHaase Ok, I'll take your word on it ;) – treyBake Jan 25 '19 at 15:37
  • @NicoHaase answered - though, I still feel like it's not overly-relevant but lemme know what you think – treyBake Jan 25 '19 at 16:11

1 Answers1

0

Thanks to the pos dupe link I managed to do some digging to really get what I want. It seems with debug_backtrace() it well.. traces back through each function call. E.g.

fileA.php

class Bar
{
    public function foo()
    {
        echo '<pre>'. print_r(debug_backtrace(), 1) .'</pre>';
        return 'hi';
    } 
}

fileB.php

require_once 'fileA.php';

$bar = new \Bar();
echo $bar->foo();

This outputs:

Array
(
    [0] => Array
    (
        [file] => /var/www/testing/test/fileB.php
        [line] => 5
        [function] => foo
        [class] => Bar
        [object] => Bar Object ()
        [type] => ->
        [args] => Array ()
    )
)

hi

This is for the most part, perfect. However, this doesn't gurantee results as the array increases per stack.

E.g. FileC.php calls function in FileB.php which in turn, calls a function in FileA.php

However, I noted with use of the function that the most desirable one is the end element in the array. With that in mind, I've set up a few functions to mimic functionality of the magic constants, without using any magic.

Set up for use of functions:

$trace = debug_backtrace();
$call = end($trace);

Directory (__DIR__):

# $trace = $call['file']
protected function getDir($trace)
{
    $arr = explode('/', $trace);
    $file = end($arr);

    $directory = [];
    $i = 0;

    foreach ($arr as $data)
    {
        if ($data !== $file) {
            $directory[] = isset($output) ? $output[$i - 1] . '/' . $data : $data;
            $i++;
        }
    }

    return 'DIRECTORY: '. implode('/', $directory);
}

File (__FILE__)::

# $trace = $call['file']
protected function getFile($trace)
{
    $arr = explode('/', $trace);
    $file = end($arr);

    return 'FILE: '. $file;
}

Function/Method (__FUNCTION__ || __METHOD__)::

# $trace = $call
protected function getFunction($trace)
{
    $output = 'FUNCTION: '. $trace['function'] ."\n";

    foreach ($trace['args'] as $key => $arguments)
    {
        foreach ($arguments as $k => $arg)
        {
            if (!is_array($arg)) {
                $output .= 'ARGS ('. $k .'): '. $arg ."\n";
            }
        }
    }

    return $output;
}

Namespace (__NAMESPACE__):

# $trace = $call['class']
protected function getNamespace($trace)
{
    $arr = explode('\\', $trace);
    $class = end($arr);

    $namespace = [];
    $i = 0;

    foreach ($arr as $data)
    {
        if ($data !== $class) {
            $namespace[] = isset($output) ? $output[$i - 1] . '/' . $data : $data;
            $i++;
        }
    }

    return 'NAMESPACE: '. implode('\\', $namespace);
}

Class (__CLASS__):

# $trace = $call['class']
protected function logClass($trace)
{
    if (strpos($trace, '\\') !== false) {
        $arr = explode('\\', $trace);
        $class = end($arr);
    } else {
        $class = $trace;
    }

    $return = 'CLASS: '. $class;
}

Missing Magic Constants:

  • __LINE__
  • __TRAIT__

Line is accessible (as you'll see from print_r($call, 1)) but I wasn't in need/interested. Trait is more or less the same as __NAMESPACE__ in my uses, so again, it wasn't interested in creating a function for it.

Notes:

  • This is part of a class I made that makes use of the protected function via public accessible functions - please ignore :)

  • These functions could be cleaned up (e.g. instead of $trace = $call['file'], use $file as param)

treyBake
  • 6,440
  • 6
  • 26
  • 57