drny20290570 2019-01-25 10:24
浏览 85
已采纳

来自被调用文件的魔术常量 - 不是动作文件

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?

  • 写回答

1条回答 默认 最新

  • douxin8610 2019-01-25 16:11
    关注

    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'] ."
    ";
    
        foreach ($trace['args'] as $key => $arguments)
        {
            foreach ($arguments as $k => $arg)
            {
                if (!is_array($arg)) {
                    $output .= 'ARGS ('. $k .'): '. $arg ."
    ";
                }
            }
        }
    
        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)

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度
  • ¥30 关于#r语言#的问题:如何对R语言中mfgarch包中构建的garch-midas模型进行样本内长期波动率预测和样本外长期波动率预测
  • ¥15 ETLCloud 处理json多层级问题
  • ¥15 matlab中使用gurobi时报错
  • ¥15 这个主板怎么能扩出一两个sata口
  • ¥15 不是,这到底错哪儿了😭
  • ¥15 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么