更好地管理功能之间的“消息”?

问题描述:

I my framework I have some functions that when done they can add some messages to a queue for reporting.

Example: I have a function that takes a path of a photo and

  • if the image is not .jpg it converts it to .jpg
  • if the image is greater than 500kB it reduces its size

I have a global $msgQueue=array(); and whenever all the logic of the page is done, in my template I echo to the users all the reports (that the functions could add during the exectuion).

In that case 2 messages would be added to $msgQueue:

  • The image was PNG and has been converted to JPG
  • The image was 2000x1000 and now is 1000x500

But this kind of behaviour I think it's not standard. If I want share with someone one of my function (in this case is checkImage($path)) It can't work because the functions needs that global array to put their report msgs.

Is there a standard approach to solve this so I can share my functions with someone else and don't worry about this dependence?

我的框架我有一些功能,完成后可以将一些消息添加到队列中进行报告。 p >

示例:我有一个功能,它采用照片的路径和 p>

  • 如果图像不是.jpg,则将其转换为。 jpg li>
  • 如果图像大于500kB则缩小尺寸 li> ul>

    我有一个全局 $ msgQueue = array( ); code>并且每当页面的所有逻辑都完成后,在我的模板中,我向用户回复所有报告(函数可以在exectuion期间添加)。 p>

    在这种情况下,2条消息将添加到$ msgQueue: p>

    • 图像为PNG并已转换为JPG
    • 图像是2000x1000,现在是1000x500 li> ul>

      但是这种行为我觉得它不标准。 如果我想与某人分享我的一个函数(在这种情况下是 checkImage($ path) code>)它无法工作,因为函数需要全局数组来放置它们的报告信息。 p>

      是否有一种标准方法可以解决这个问题,以便我可以与其他人分享我的功能而不担心这种依赖性? p> div>

My suggestion would be to use a class, something like:

class Report(){
    public $msgQueue;

    function addReport($string){ 
         array_push($this->msgQueue, $string);  //store new report
    }

    function showReports(){
         //loop over the message queue
         ...
    }
}

Benefits:

  1. You could have different kind of reports using the same class, separating process from errors for example, $processes = new Report and $errors = new Report

  2. No need to declare vars as globals, the class preserves the value of its property $msgQueue you would only need to $processes->addReport("Resizing image to XXX")

  3. The benefits of OOP, having a logical structure, etc.

I don't really think there is a standard approach. What I do is this:

  • Give each library (Image, File, etc..) its own message array.

  • Use a Message library that has its own message array as well as an array of "sources" that can be built/added to via Message::addSource($class, $propertyName). (I add a message source right after I make an instance of a library, such as Image).

    • When Message::render() is executed, it combines each source's messages with the Message class's own message then renders them.

Doing it that way allows each library to be independent of others while still being able have both a per-instance and global message array.

Is there a standard approach to solve this?

Yes, its called OOP :) (see amosrivera's answer for that).

But if OOP is not an option (but you should seriously consider it nonetheless), then refactoring the functions to accept a messageQueue argument (and passing it by reference) might work.

// passing $messageQueue by reference by prepending &
function checkImage( $path, array &$messageQueue = null )
{
    /* do image checking */
    $result = /* the result of the image checking */;

    // if $messageQueue argument is provided
    if( $messageQueue !== null )
    {
        // add the message to the queue
        $messageQueue[] = 'Image checking done';
    }

    return $result; // false or true perhaps.
}

Usage:

$messageQueue = array();

if( checkImage( $somePath, $messageQueue ) )
{
    echo 'checking image succeeded';
}
else
{
    echo 'checking image failed';
}

var_dump( $messageQueue );

// would output something like:
Array(1) (
    'Image checking done'
)