CodeIgniter, How to modify buffered output before

2019-08-30 01:50发布

I would like to alter the output throughout my Codeigniter-based website.

Quite simply I would like to do

$output = str_replace(
    array('ā','ē','ī','ō','ū','Ā','Ē','Ī','Ō','Ū'),
    array('a','e','i','o','u','A','E','I','O','U'),
    $output
)

In the event that the user prefers so.

By reading questions and answers here, I found a link that could help..

https://www.codeigniter.com/user_guide//general/controllers.html#processing-output

..but it only works controller by controller and that would be repetition of content.

Is there a way to make a hook instead?

Thanks in advance!

3条回答
来,给爷笑一个
2楼-- · 2019-08-30 02:15

Right, so you can write a replace value in an extension of the loader class and save it as MY_Loader.php in application/core. Here is an example:

<?php

class MY_Loader extends CI_Loader
{
    public function __construct()
    {
        parent::__construct();
    }

    function view($template, $view, $vars = array(), $return = FALSE, $absolute = false)
    {
        /* This seems inferior, but it's the easiest solution
         * if $view is an array then the function is being called with the default CI params, ie:
         * $this->load->view('some_view', $data)
         */
        if(is_array($view)){
            $vars = $view;
            $view = $template;
            $template = false;
        }

        if($template == false){
            parent::view($view, $vars, $return);
        }else{
            if($absolute === true)
            {
                $template_path =  'templates/' . $template . '/' . $view . EXT;

                if(!file_exists('application/views/'.$template_path))
                {
                    show_error('The requested absolute view does not exist: ' . $template_path);
                }

                $template = 'templates/'.$template.'/';
                $view_path = false;
            }
            else
            {
                $template = 'templates/'.$template.'/';
                $template_path = $template . 'template' . EXT;

                if(!file_exists('application/views/'.$template_path))
                {
                    show_error('The requested template does not exist: ' . $template_path);
                }

                $view_path = $template . $view . EXT;

                if(!file_exists('application/views/'.$view_path))
                {
                    show_error('The requested view does not exist: ' . $view_path);
                }
            }

            $template_vars = array();
            $template_vars['tpl_title'] = 'Title Not Defined';
            $template_vars['tpl_meta'] = array();
            $template_vars['tpl_link'] = array();
            $template_vars['tpl_script'] = array();
            $template_vars['tpl_view'] = $view . EXT;

            foreach($vars as $key => $val)
            {
                $template_vars[$key] = $val;
            }

            //$vars = array_merge($vars, $template_vars);

            //include_once($template.'/template_functions' . EXT);

            return $this->_ci_load(array('_ci_view' => $template_path, '_ci_vars' => $this->_ci_object_to_array($template_vars), '_ci_return' => $return));
        }
    }

    // --------------------------------------------------------------------

    /**
     * Loader
     *
     * This function is used to load views and files.
     * Variables are prefixed with _ci_ to avoid symbol collision with
     * variables made available to view files
     *
     * @access  private
     * @param   array
     * @return  void
     */
    function _ci_load($_ci_data)
    {
        if(substr($_ci_data['_ci_view'], 0, 12) != './templates/'){
            parent::_ci_load($_ci_data);
        }else{
            // Set the default data variables
            foreach (array('_ci_view', '_ci_vars', '_ci_path', '_ci_return') as $_ci_val)
            {
                $$_ci_val = ( ! isset($_ci_data[$_ci_val])) ? FALSE : $_ci_data[$_ci_val];
            }

            // Set the path to the requested file
            if ($_ci_path == '')
            {
                $_ci_ext = pathinfo($_ci_view, PATHINFO_EXTENSION);
                $_ci_file = ($_ci_ext == '') ? $_ci_view.EXT : $_ci_view;
                $_ci_path = $_ci_file;
            }
            else
            {
                $_ci_x = explode('/', $_ci_path);
                $_ci_file = end($_ci_x);
            }

            if ( ! file_exists($_ci_path))
            {
                show_error('Unable to load the requested file: '.$_ci_file);
            }

            // This allows anything loaded using $this->load (views, files, etc.)
            // to become accessible from within the Controller and Model functions.
            // Only needed when running PHP 5

            if ($this->_ci_is_instance())
            {
                $_ci_CI =& get_instance();
                foreach (get_object_vars($_ci_CI) as $_ci_key => $_ci_var)
                {
                    if ( ! isset($this->$_ci_key))
                    {
                        $this->$_ci_key =& $_ci_CI->$_ci_key;
                    }
                }
            }

            /*
             * Extract and cache variables
             *
             * You can either set variables using the dedicated $this->load_vars()
             * function or via the second parameter of this function. We'll merge
             * the two types and cache them so that views that are embedded within
             * other views can have access to these variables.
             */ 
            if (is_array($_ci_vars))
            {
                $this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars);
            }
            extract($this->_ci_cached_vars);

            /*
             * Buffer the output
             *
             * We buffer the output for two reasons:
             * 1. Speed. You get a significant speed boost.
             * 2. So that the final rendered template can be
             * post-processed by the output class.  Why do we
             * need post processing?  For one thing, in order to
             * show the elapsed page load time.  Unless we
             * can intercept the content right before it's sent to
             * the browser and then stop the timer it won't be accurate.
             */
            ob_start();

            // If the PHP installation does not support short tags we'll
            // do a little string replacement, changing the short tags
            // to standard PHP echo statements.


        $content = file_get_contents($_ci_path);

        $content = str_replace(
            array('ā','ē','ī','ō','ū','Ā','Ē','Ī','Ō','Ū'),
            array('a','e','i','o','u','A','E','I','O','U'),
            $content
        );

        if ((bool) @ini_get('short_open_tag') === FALSE AND config_item('rewrite_short_tags') == TRUE)
        {
            echo eval('?>'.preg_replace("/;*\s*\?>/", "; ?>", str_replace('<?=', '<?php echo ', '.$content)));
        }
        else
        {
            echo eval('?>'.$content.'<?php'); // include() vs include_once() allows for multiple views with the same name
        }

            log_message('debug', 'File loaded: '.$_ci_path);

            // Return the file data if requested
            if ($_ci_return === TRUE)
            {       
                $buffer = ob_get_contents();
                @ob_end_clean();
                return $buffer;
            }

            /*
             * Flush the buffer... or buff the flusher?
             *
             * In order to permit views to be nested within
             * other views, we need to flush the content back out whenever
             * we are beyond the first level of output buffering so that
             * it can be seen and included properly by the first included
             * template and any subsequent ones. Oy!
             *
             */ 
            if (ob_get_level() > $this->_ci_ob_level + 1)
            {
                ob_end_flush();
            }
            else
            {
                // PHP 4 requires that we use a global
                global $OUT;
                $OUT->append_output(ob_get_contents());
                @ob_end_clean();
            }
        }
    }
}

You may not need all of this, but I just copied it from an archived projects. Notice in the _ci_load() function you can affect the output before it is evaluated (normally an include as indicated by the comments but changed to string for your case). I have not tested this so it's not intended to be a solution as much as it is a general reminder that you can extend core classes and modify output in one place.

Of course, it might be easier to do in the output class itself: https://www.codeigniter.com/user_guide/libraries/output.html

查看更多
太酷不给撩
3楼-- · 2019-08-30 02:17

In the application/Libraries file you can make a php file in which you can write something like this:

    <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

     class Letterconverter {

        public function convert($value) {

            $before= array('ā','ē','ī','ō','ū','Ā','Ē','Ī','Ō','Ū');
            $after =array('a','e','i','o','u','A','E','I','O','U');
            $value = str_replace($before, $after, $value);
            return $value;
       }
    }

Then you can call it from wherever you want as a library.

查看更多
一纸荒年 Trace。
4楼-- · 2019-08-30 02:27

If your intention is to replace accented characters then i suggest you take a look at wordpress remove_accents function here.

2) take a look at codeigniter hooks, there is display_override hook

$hook['display_override'] = array(
  'class'    => 'MyClass',
  'function' => 'Myfunction',
  'filename' => 'Myclass.php',
  'filepath' => 'hooks',
  'params'   => array()
);

3) once you define a function/class for this hook, you could get output string there

$this->CI =& get_instance();
$out = $this->CI->output->get_output();

and then you can change the output as you like...

查看更多
登录 后发表回答