Php 使大型加工作业变小

Php 使大型加工作业变小,php,zend-framework,recursion,iteration,Php,Zend Framework,Recursion,Iteration,这是我在寻找解决方案时使用的代码 public function indexAction() { //id3 options $options = array("version" => 3.0, "encoding" => Zend_Media_Id3_Encoding::ISO88591, "compat" => true); //path to collection $path = APPLICATI

这是我在寻找解决方案时使用的代码

 public function indexAction()
    {
        //id3 options
        $options = array("version" => 3.0, "encoding" => Zend_Media_Id3_Encoding::ISO88591, "compat" => true);
        //path to collection
        $path = APPLICATION_PATH . '/../public/Media/Music/';//Currently Approx 2000 files
        //inner iterator
        $dir = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS);
        //iterator
        $iterator = new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::SELF_FIRST);
        foreach ($iterator as $file) {
            if (!$file->isDir() && $file->getExtension() === 'mp3') {
                //real path to mp3 file
                $filePath = $file->getRealPath();
                Zend_Debug::dump($filePath);//current results: accepted path no errors
                $id3 = new Zend_Media_Id3v2($filePath, $options);
                foreach ($id3->getFramesByIdentifier("T*") as $frame) {
                    $data[$frame->identifier] = $frame->text;
                }
                Zend_Debug::dump($data);//currently can scan the whole collection without timing out, but APIC data not being processed.
            }
        }
    }
问题:处理多个目录中mp3文件的文件系统。将id3标签数据提取到数据库(3个表),并将封面图像从标签提取到单独的文件中

我可以处理实际提取和数据处理。我的问题是输出

由于Zend Framework 1.x处理输出缓冲的方式,很难输出文件正在处理的指示符。在旧式PHP脚本中,没有输出缓冲,您可以在循环的每次迭代中打印出一点html,并显示一些进度指示

我希望能够处理每个相册的目录,输出结果,然后继续到下一个相册的目录。仅要求用户对某些错误进行干预

任何帮助都将不胜感激

Javascript不是我正在寻找的解决方案。我觉得这在PHP和ZF1MVC的结构中应该是可能的

我这样做主要是为了我自己的启发,这似乎是学习一些重要概念的一个很好的方法

[编辑]
好的,关于如何将其分解成更小的块的一些想法如何。处理一个块,提交,处理下一个块,诸如此类的事情。进出采埃孚

[编辑]

我开始意识到我想要完成的事情有问题。输出缓冲似乎不仅仅发生在ZF中,从ZF到浏览器,它无处不在。嗯…

我不熟悉Zend框架的工作原理。我会给你一个一般性的建议。当处理的流程进行了大量迭代,并且可能需要很长时间时,通常建议将长流程移到后台流程中。或者,在与web相关的应用程序中,转入cron作业

如果您想使用的过程是针对单个站点的,那么您可以在cronjob中实现类似的内容(注意:粗略的伪代码):


一种解决方案是使用作业队列,如Gearman。Gearman是解决此类问题的一个很好的解决方案,并且很容易与Zend框架集成(http://blog.digitalstruct.com/2010/10/17/integrating-gearman-into-zend-framework/)


它将允许您创建一个工作进程来处理每个“chuck”,允许您的进程在处理作业时继续解锁,对于音乐/图像处理等长时间运行的过程非常方便,我建议使用插件

class Postpone extends Zend_Controller_Plugin_Abstract
{

    private $tail;

    private $callback;


    function __construct ($callback = array())
    {
        $this->callback = $callback;
    }


    public function setRequest (Zend_Controller_Request_Abstract $request)
    {
        /*
         * We use layout, which essentially contains some html and a placeholder for action output.
         * We put the marker into this placeholder in order to figure out "the tail" -- the part of layout that goes after placeholder.
         */
        $mark = '---cut-here--';
        $layout = $this->getLayout ();

        $layout->content = $mark;

        /*
         * Now we have it.
         */
        $this->tail = preg_replace ("/.*$mark/s", '', $layout->render ());
    }


    public function postDispatch (Zend_Controller_Request_Abstract $request)
    {
        $response = $this->getResponse ();

        $response->sendHeaders ();

        /*
         * The layout generates its output to the default section of the response.
         * This output inludes "the tail".
         * We don't need this tail shown right now, because we have callback to do.
         * So we remove it here for a while, but we'll show it later.
         */
        echo substr ($this->getResponse ()
            ->getBody ('default'), 0, - strlen ($this->tail));

        /*
         * Since we have just echoed the result, we don't need it in the response. Do we?
         */
            Zend_Controller_Front::getInstance ()->returnResponse(true);
        $response->clearBody ();

        /*
         * Now to business.
         * We execute that calculation intensive callback.
         */
        if (! empty ($this->callback) && is_callable ($this->callback))
        {
            call_user_func ($this->callback);
        }

        /*
         * We sure don't want to leave behind the tail.
         * Output it so html looks consistent.
         */
        echo $this->tail;
    }


    /**
     * Returns layout object
     */
    function getLayout ()
    {
        $layout_plugin = Zend_Controller_Front::getInstance ()->getPlugin ('Zend_Layout_Controller_Plugin_Layout');
        return $layout = $layout_plugin->getLayout ();
    }
}




class IndexController extends Zend_Controller_Action
{


    /*
     * This is a calculation intensive action
     */
    public function indexAction ()
    {
        /*
         * Zend_Layout in its current implementation accumulates whole action output inside itself.
         * This fact hampers out intention to gradually output the result.
         * What we do here is we defer execution of our intensive calculation in form of callback into the Postpone plugin.
         * The scenario is:
         * 1. Application started
         * 2. Layout is started
         * 3. Action gets executed (except callback) and its output is collected by layout.
         * 4. Layout output goes to response.
         * 5. Postpone::postDispatch outputs first part of the response (without the tail).
         * 6. Postpone::postDispatch calls the callback. Its output goes stright to browser.
         * 7. Postpone::postDispatch prints the tail.
         */
        $this->getFrontController ()
            ->registerPlugin (new Postpone (function  ()
        {
            /*
             * A calculation immigration
             * Put your actual calculations here.
             */
        echo str_repeat(" ", 5000);
        foreach (range (1, 500) as $x)
        {
            echo "<p>$x</p><br />\n";
            usleep(61500);
            flush();
        }
        }), 1000);
    }
}
类扩展Zend\u控制器\u插件\u抽象
{
私人$tail;
私用美元回拨;
函数构造($callback=array())
{
$this->callback=$callback;
}
公共函数setRequest(Zend_Controller_Request_Abstract$Request)
{
/*
*我们使用布局,它本质上包含一些html和用于操作输出的占位符。
*我们将标记放在这个占位符中是为了找出“尾部”——布局中位于占位符后面的部分。
*/
$mark='---在这里切--';
$layout=$this->getLayout();
$layout->content=$mark;
/*
*现在我们有了。
*/
$this->tail=preg_replace(“/.$mark/s)”,“”,$layout->render());
}
公共功能后调度(Zend\u控制器\u请求\u抽象$Request)
{
$response=$this->getResponse();
$response->sendHeaders();
/*
*布局将生成其输出到响应的默认部分。
*该输出包含“尾部”。
*我们现在不需要显示这个尾部,因为我们需要回调。
*因此,我们在这里删除它一段时间,但稍后将显示它。
*/
echo substr($this->getResponse()
->getBody('default'),0,-strlen($this->tail));
/*
*因为我们刚刚回应了结果,所以我们在回应中不需要它,是吗?
*/
Zend_Controller_Front::getInstance()->returnResponse(true);
$response->clearBody();
/*
*现在谈正事。
*我们执行计算密集型回调。
*/
如果(!empty($this->callback)&&is_callable($this->callback))
{
调用用户函数($this->callback);
}
/*
*我们当然不想留下尾巴。
*输出它,使html看起来一致。
*/
echo$this->tail;
}
/**
*返回布局对象
*/
函数getLayout()
{
$layout\u plugin=Zend\u Controller\u Front::getInstance()->getPlugin('Zend\u layout\u Controller\u plugin\u layout');
返回$layout=$layout_plugin->getLayout();
}
}
类IndexController扩展Zend\u控制器\u操作
{
/*
*这是一项计算密集型行动
*/
公共函数索引()
{
/*
*Zend_布局在其当前实现中将整个动作输出累积在其内部。
*这一事实阻碍了我们逐步输出结果的意图。
*我们在这里所做的是将密集计算的执行以回调的形式推迟到推迟插件中。
*情况是:
*1.申请已启动
*2.开始布局
*3.执行操作(回调除外),其输出由布局收集。
*4.布局输出转到响应。
*5.延迟::postDispatch输出响应的第一部分(没有尾部)。
*6.推迟::postDispatch调用回调。其输出直接发送到浏览器。
*7.推迟::postDispatch打印尾部。
*/
$this->getFrontController()
->registerPlugin(新的延迟(函数)()
{
/*
*移民计算
*把你的实际计算放在这里。
*/
回音str_重复(“,5000);
foreach(r
<?php

if(file_exists($logdir."current-state")){
    echo "<strong>there are background process running.</strong>";
} else {
    echo "<strong>no background process running.</strong>";
}
class Postpone extends Zend_Controller_Plugin_Abstract
{

    private $tail;

    private $callback;


    function __construct ($callback = array())
    {
        $this->callback = $callback;
    }


    public function setRequest (Zend_Controller_Request_Abstract $request)
    {
        /*
         * We use layout, which essentially contains some html and a placeholder for action output.
         * We put the marker into this placeholder in order to figure out "the tail" -- the part of layout that goes after placeholder.
         */
        $mark = '---cut-here--';
        $layout = $this->getLayout ();

        $layout->content = $mark;

        /*
         * Now we have it.
         */
        $this->tail = preg_replace ("/.*$mark/s", '', $layout->render ());
    }


    public function postDispatch (Zend_Controller_Request_Abstract $request)
    {
        $response = $this->getResponse ();

        $response->sendHeaders ();

        /*
         * The layout generates its output to the default section of the response.
         * This output inludes "the tail".
         * We don't need this tail shown right now, because we have callback to do.
         * So we remove it here for a while, but we'll show it later.
         */
        echo substr ($this->getResponse ()
            ->getBody ('default'), 0, - strlen ($this->tail));

        /*
         * Since we have just echoed the result, we don't need it in the response. Do we?
         */
            Zend_Controller_Front::getInstance ()->returnResponse(true);
        $response->clearBody ();

        /*
         * Now to business.
         * We execute that calculation intensive callback.
         */
        if (! empty ($this->callback) && is_callable ($this->callback))
        {
            call_user_func ($this->callback);
        }

        /*
         * We sure don't want to leave behind the tail.
         * Output it so html looks consistent.
         */
        echo $this->tail;
    }


    /**
     * Returns layout object
     */
    function getLayout ()
    {
        $layout_plugin = Zend_Controller_Front::getInstance ()->getPlugin ('Zend_Layout_Controller_Plugin_Layout');
        return $layout = $layout_plugin->getLayout ();
    }
}




class IndexController extends Zend_Controller_Action
{


    /*
     * This is a calculation intensive action
     */
    public function indexAction ()
    {
        /*
         * Zend_Layout in its current implementation accumulates whole action output inside itself.
         * This fact hampers out intention to gradually output the result.
         * What we do here is we defer execution of our intensive calculation in form of callback into the Postpone plugin.
         * The scenario is:
         * 1. Application started
         * 2. Layout is started
         * 3. Action gets executed (except callback) and its output is collected by layout.
         * 4. Layout output goes to response.
         * 5. Postpone::postDispatch outputs first part of the response (without the tail).
         * 6. Postpone::postDispatch calls the callback. Its output goes stright to browser.
         * 7. Postpone::postDispatch prints the tail.
         */
        $this->getFrontController ()
            ->registerPlugin (new Postpone (function  ()
        {
            /*
             * A calculation immigration
             * Put your actual calculations here.
             */
        echo str_repeat(" ", 5000);
        foreach (range (1, 500) as $x)
        {
            echo "<p>$x</p><br />\n";
            usleep(61500);
            flush();
        }
        }), 1000);
    }
}