--- tags: ci4, 即時 --- # 如何讓CodeIgniter4能即時輸出 2022/05/08 CI4的回應請求都是等全部任務都完成後再一次輸出 有時希望能看到即時進度狀況的情況下會很不方便 因此本為來解決這個問題 分成兩種狀況,CLI、網頁(後台與前台) ## CLI CLI有兩種方法可以即時輸出 1. (推薦)透過CLI::print() / CLI::write() 直接輸出 CLI::print與CLI::write差別插在CLI::print不會換行,CLI::write會換行 1. 透過ob_end_flush()將緩衝區的資料送出去 ```php= <?php namespace App\Controllers\CLI; use CodeIgniter\Controller; use CodeIgniter\CLI\CLI; class demo extends Controller { public function test() { echo '方法一:'; for ($i = 0; $i < 10; $i++) { CLI::print($i . ' '); sleep(1); } CLI::print('方法二:'); for ($i = 0; $i < 10; $i++) { echo $i . ' '; $this->output(); sleep(1); } } function output() { while (ob_get_level() > 0) ob_end_flush(); } } ```  ## 網頁後台 如果不使用CI4的話, 可透過ob_flush(); flush();將當前緩衝區資料輸出 依照參考[1]的執行結果 ![[開發與維護/網站前端/attachments/動畫 1.gif]] 但套用到CI4就還是會等全部任務都完成後再一次輸出, 所以要進行調整 GOOGLE爬文沒找不到相關資料, 透過一陣子的自己摸索亂試中於試出來了~ 但我不清楚為啥這樣可以... 所以發文 [iT邦幫忙](https://ithelp.ithome.com.tw/questions/10208446) 詢問 ```php namespace App\Controllers; use App\Controllers\BaseController; class demo extends BaseController { public function index() { $this->response->send(); // 送出預設表頭 ob_end_flush(); // 從緩衝區輸出並結束當前緩衝區 flush(); // 顯示到畫面 for ($i = 0; $i < 10; $i++) { echo $i . ' '; ob_flush(); // 從緩衝區輸出 flush(); // 顯示到畫面 sleep(1); } return $this->response->setJSON(''); } } ``` 第一個$this->response->send();主要是送出表頭用 ob_end_flush(); : 從緩衝區輸出並結束當前緩衝區,避免因當前被CI4設定過的換衝區影響,導致還是全部工作完成才一次輸出 return $this->response->setJSON(''); 透過空字串的setJson(),使開發模式下不會產生多餘的debug資訊 結果  ## 網頁前台 網頁前台的部分就直接參考參考連結[1] ```html <!DOCTYPE html> <html> <head> <title></title> <meta charset="utf-8"> </head> <body> <div><button id="ontimeoutputBtn">及時輸出</button></div> <div id="ontimeoutputArea" style="border: 1px solid red"></div> </body> <script src="//ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script type="text/javascript"> // readyState總共有5個狀態值,分別為0~4 // 0 未初始化狀態:此時,已經建立了一個XMLHttpRequest物件 // 1 準備傳送狀態:此時,已經呼叫了XMLHttpRequest物件的open方法,並且XMLHttpRequest物件已經準備好將一個請求傳送到伺服器端 // 2 已經發送狀態:此時,已經通過send方法把一個請求傳送到伺服器端,但是還沒有收到一個響應 // 3 正在接收狀態:此時,已經接收到HTTP響應頭部資訊,但是訊息體部分還沒有完全接收到 // 4 完成響應狀態:此時,已經完成了HTTP響應的接收 $('#ontimeoutputBtn').click(function(){ $.ajax({ // url :'demo.php', url: 'https://soc.localhost.tw:8007/demo/index', type:'get' ,data:{} ,success:function(res){ console.log('這裡用jq提供的方法處理'); console.log(res); } ,xhr:function(){//返回一個更強大的XMLHttpRequest的物件 if (window.XMLHttpRequest) { //主流瀏覽器提供了XMLHttpRequest物件 var xhr = new XMLHttpRequest(); }else if (window.ActiveXObject) { //低版本的IE瀏覽器沒有提供XMLHttpRequest物件 //所以必須使用IE瀏覽器的特定實現ActiveXObject var xhr = new ActiveXObject("Microsoft.XMLHTTP"); } //繫結事件 xhr.onreadystatechange = function () { if (xhr.readyState === 4 && xhr.status === 200) { //獲取成功後執行操作 //資料在xhr.responseText //這裡使用js原生的處理方式 // console.log('success'); } if(xhr.readyState === 3){ var html = "<p style='border:1px solid red;'>"+xhr.responseText+"</p>"; $('#ontimeoutputArea').html(html); } } return xhr; } }); }); </script> </html> ``` ## 參考連結 - [1]PHP+jquery ajax 實現實時的輸出顯示 https://www.796t.com/content/1542836826.html - [2]解決 CodeIgniter 4 Command line 輸出緩衝/不即時的問題 (ob_start / ob_end_flush) http://blog.changyy.org/2020/06/php-codeigniter-4-command-line-obstart.html
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up