# PHP [TOC] ## PHP 內建函數 ### PHP str 1. strip_tags 清除html程式碼 ```php= <?php $mystring="<a href='http://www.webtech.tw'>WebTech</a>"; echo strip_tags($mystring); //輸出 WebTech ?> ``` 2. rtrim 可以去除最右邊的 ```php= $date_search .= " data_date LIKE '".$item["data_date"]."' OR"; $date = rtrim($date_search, 'OR'); ``` 3. str_pad 補0輸出 ```php= $month = 3; // 例如,3月 $day = 5; // 例如,5日 // 补零并输出 $formattedMonth = str_pad($month, 2, "0", STR_PAD_LEFT); $formattedDay = str_pad($day, 2, "0", STR_PAD_LEFT); ``` 4. floor 小數捨去 ```php= <?php floor(intval($buy_sell)/1000*100)/100, ``` 5. round 四捨五入 ```php= <?php round(intval($amount),2); ``` ### PHP Array 1. array_push 陣列增加 ```php= <?php $array = array(); array_push($array,"apple"); ``` 2. array_values 將索引重置 ```php= <?php $data = array_values($data); ?> ``` 3. array_search 尋找檔名在Array value的key ```php= <?php $tmp_img_sorts = explode(";",$request->tmp_img_sort); foreach ($request->file('multiple_img') as $key=>$image) { $originalName = $image->getClientOriginalName(); $filekey = array_search($originalName, $tmp_img_sorts); $multiple_imgs[$filekey]; //這邊就是陣列去尋找原本檔名的在地幾個key後然後儲存 } ``` 4. in_array 查看資料有沒有在Array的Value裡 ```php= <?php $fruits = array("apple", "banana", "orange", "grape"); // 检查数组中是否存在某个值 $searchValue = "orange"; if (in_array($searchValue, $fruits)) { echo "$searchValue 存在于数组中。"; } else { echo "$searchValue 不存在于数组中。"; } ``` 5. unset 刪除array指定key ```php= <?php unset($data[0]); ?> ``` 6. array_slice array取出一段值 ```php= <?php $a=array("red","green","blue","yellow","brown"); print_r(array_slice($a,1,2)); // 輸出 Array ( [0] => green [1] => blue ) ?> ``` 7. array_filter 陣列篩選,或是將空值過濾 ```php= <?php $search_conditions = array_filter($search_conditions); //也可以直接篩選 $numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // 過濾出偶數 $evenNumbers = array_filter($numbers, function($number) { return $number % 2 === 0; }); ``` 8. array_diff 找出兩組陣列不同差異 ```php= <?php $array1 = [1, 2, 3, 4, 5]; $array2 = [3, 4, 5, 6, 7]; $onlyInArray1 = array_diff($array1, $array2); $onlyInArray2 = array_diff($array2, $array1); print_r("Values only in Array1: "); print_r($onlyInArray1); print_r("Values only in Array2: "); print_r($onlyInArray2); Values only in Array1: Array ( [0] => 1 [1] => 2 ) Values only in Array2: Array ( [0] => 6 [1] => 7 ) ``` ## PHP 作業系統判別 ```php= <?php if (strtoupper(substr(PHP_OS, 0, 5)) === 'LINUX') { //linux }elseif(strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'){ //windows } ``` ## PHP Json轉資料 ```php= <?php // 轉成json資料 try { } catch (\Exception $e) { // dd($e); return json_encode([ 'status' => 'fail', 'msg' => '查詢失敗', 'e' => $e ]); } // json轉回php array or object json_decode(); ``` ## PHP查看版本 1. cmd指令 php -v 2. PHP裡輸出 ```php= <?php phpinfo(); echo PHP_VERSION ``` ## PHP 日期計算 ```php= <?php 給目前時間加一天、一小时 echo "今天:",date('Y-m-d H:i:s'),"<br>"; echo "明天:",date('Y-m-d H:i:s',strtotime('+1 day')); 同理,加一年、一個月、一小時、一分鐘… echo "明天:",date('Y-m-d H:i:s',strtotime('+1 day')); echo "明天:",date('Y-m-d H:i:s',strtotime('+1 hour')); echo "明天:",date('Y-m-d H:i:s',strtotime('+1 minute')); echo "明天:",date('Y-m-d H:i:s',strtotime('+1 mouth')); //這裡+1 day可以修改參數1為任何想需要的數 day也可以改成year(年),month(月),hour(小時)minute(分),second(秒)如: date('Y-m-d H:i:s',strtotime("+1 day +1 hour +1 minute"); //给指定時間加一天、一小時 echo date("Y-m-d",strtotime("+1 month",strtotime("2020-10-13"))); ?> ``` ### PHP 簡易日期區間判斷星期幾 ```php= <?php $weekarray=array("日","一","二","三","四","五","六"); $start_date = "2023-07-01"; $start_strtotime = strtotime($start_date); $end_date = "2023-08-04"; $end_strtotime = strtotime($end_date); $days = round(($end_strtotime-$start_strtotime)/3600/24); for ($i=0;$i<=$days;$i++){ $now_date = date('Y-m-d',strtotime("-$i day",$end_strtotime)); $week = $weekarray[date("w",strtotime($now_date))]; if($week == "六" || $week=="日"){ echo "$now_date 星期 $week 不開盤<br>"; }else{ echo "$now_date 星期 $week 開盤<br>"; } } ?> ``` ## PHP 計算執行程式多久 ```php= <?php $start_time = microtime(true); // 你的 PHP 程式碼 // 記錄結束時間 $end_time = microtime(true); // 計算執行時間 $execution_time = ($end_time - $start_time); // 顯示執行時間 echo "程式執行時間: {$execution_time} 秒"; ?> ``` ## PHP curl爬網頁 ### PHP curl get ```php= <?php $PostData = "a=abc&b=def"; $curl = curl_init("https://test.com/test.php?$PostData"); //檢查 curl 有無作用 if (! $curl) { die( "Cannot allocate a new PHP-CURL handle" ); } curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1); //SSL curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);//SSL curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); //這個若是沒設 , curl_exec($curl) 會直接印出來 curl_setopt ($curl, CURLOPT_HEADER, 0); // 得到回傳的HTTP頁面. $data = curl_exec($curl); echo "&data=$data"; //輸出傳回值 curl_close($curl); //關閉連線 ``` ### PHP curl post ```php= <?php $PostData = "a=abc&b=def"; $curl = curl_init("https://test.com/test.php"); //檢查 curl 有無作用 if (! $curl) { die( "Cannot allocate a new PHP-CURL handle" ); } curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1); //SSL curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);//SSL //這邊是給Header 下面只是範例 可設可不設 curl_setopt($ch, CURLOPT_HTTPHEADER, array("Authorization: Bearer {$channelAccessToken}", "Content-Type: application/json")); curl_setopt($ch, CURLOPT_HEADER, 1); //--------------------------- curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); //這個若是沒設 , curl_exec($curl) 會直接印出來 curl_setopt($curl, CURLOPT_POST,1);//設定CURLOPT_POST為1或true,表示用post傳送 curl_setopt($curl, CURLOPT_POSTFIELDS,$PostData)// PostData傳送的資料 curl_setopt ($curl, CURLOPT_HEADER, 0); // 得到回傳的HTTP頁面. $data = curl_exec($curl); echo "&data=$data"; //輸出傳回值 curl_close($curl); //關閉連線 ``` ### PHP file_get_contents file_get_contents($url); ## PHP 瀏覽器清除緩存 ```php= <?php header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1 header("Cache-Control: post-check=0, pre-check=0", false); header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); header("Pragma: no-cache"); ``` ## PHP 壓縮pdf ghostscript 1. 下載 ghostscript ```php= <?php $pdfPath = public_path('uploads/').$pdf_link; $compressedPdfPath = public_path('uploads/').$compressed_pdf_link; $ghostscriptPath = '"C:\\Program Files\\gs\\gs10.02.1\\bin\\gswin64c.exe"'; // $command = "$ghostscriptPath -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -sOutputFile={$compressedPdfPath} {$pdfPath}"; // $command = "gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -sOutputFile={$compressedPdfPath} {$pdfPath}";linux指令 $command = "$ghostscriptPath -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -r72 -sOutputFile={$compressedPdfPath} {$pdfPath}"; $output = shell_exec($command); ``` ## PHP 正規式 ### 抓取日期 ```php= <?php $pattern = '/\b\d{4}\/\d{2}\/\d{2}\b/'; preg_match($pattern, $value, $matches); if (!empty($matches)) { $data_date = str_replace("/","-",$matches[0]); break; } ``` ### 去除空白 ```php= <?php $value = preg_replace('/\s+/', "", $value); ``` ### 頭尾去除空白(特殊無法用其他" "取代掉的&nbsp;) ```php= <?php $value = preg_replace('/^\p{Z}+|\p{Z}+$/u', '', $value); ?> ``` ### 將括號內容移除 ```php= <?php $string = "這是一個(含有括號的)字串。"; $pattern = '/\([^)]*\)/'; // 正規表達式,匹配括號及其內容 $cleanedString = preg_replace($pattern, '', $string); echo $cleanedString; ``` ### 基本匹配:檢查字串中包含是否某個特定的字詞或字符 ```php= <?php $pattern = '/apple/'; $text = 'I like apples.'; if (preg_match($pattern, $text)) { echo "Match found!"; } else { echo "No match found."; } ?> ``` ### 案例不敏感匹配:執行不區分大小寫的模式匹配 ```php= <?php $pattern = '/apple/i'; $text = 'I like Apples.'; if (preg_match($pattern, $text)) { echo "Match found!"; } else { echo "No match found."; } ?> ``` ### 提取匹配:從字符串中提取匹配的部分 ```php= <?php $pattern = '/(\d{2})-(\d{2})-(\d{4})/'; $text = 'Date of birth: 05-20-1990'; if (preg_match($pattern, $text, $matches)) { echo "Day: " . $matches[1] . ", Month: " . $matches[2] . ", Year: " . $matches[3]; } else { echo "No match found."; } ?> ``` ### 替換:將匹配的部分替換為新的字符串 preg_replace ```php= <?php $pattern = '/apple/'; $text = 'I like apples.'; $replacement = 'oranges'; $new_text = preg_replace($pattern, $replacement, $text); echo $new_text; // Output: I like oranges. ?> ``` ### 字符範圍:匹配特定範圍的字符 ```php= <?php $pattern = '/[0-9]/'; // 匹配任何數字字符 $text = 'The code is 12345.'; if (preg_match($pattern, $text)) { echo "Match found!"; } else { echo "No match found."; } ?> ``` ### 字串裡提取英文 ```php= <?php $text = "Hello123World456"; $pattern = '/[A-Za-z]+/'; preg_match_all($pattern, $text, $matches); $english_words = $matches[0]; print_r($english_words); Array ( [0] => Hello [1] => World ) ?> ``` ### 字串裡提取數字 ```php= <?php $text = "Hello123World456"; $pattern = '/\d+/'; preg_match_all($pattern, $text, $matches); $numbers = $matches[0]; print_r($numbers); Array ( [0] => 123 [1] => 456 ) ?> ``` ### 獲得輸出richMenuId ```php= <?php $pattern = '/"richMenuId":"(.*?)"/'; preg_match($pattern, $output, $matches); if (isset($matches[1])) { $richMenuId = $matches[1]; echo "成功獲得 Rich Menu ID:$richMenuId<br>"; } else { echo "無法提取 Rich Menu ID。<br>"; } ?> ``` # PHP Laravel (https://hackmd.io/NWZ9E6EQQ4yUVBFX-Je8hQ) # .htaccess ## 檔案數量限制及size ```php= php_value upload_max_filesize 50M php_value post_max_size 52M php_value max_file_uploads 100 <IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{QUERY_STRING} ^public/(.+)$ RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ public/%1 [NC,R,L] RewriteRule ^(.*)$ public/$1 [L] </IfModule> ``` # phpmyadmin修改sql https://hackmd.io/kORpcygzQuKxr0AqMUu-_g # Mysql ## 大量資料減少查詢時間 原本 ```sql= select * from `news` where (`enabled`=1 or web_data_active=1) and length(`subject`)>10 and `newsid` != '20231221A001001' and (`end_datetime` is null or `end_datetime` > '2024-01-09 10:39:00') and `start_datetime` < '2023-12-21 13:49:01' and `start_datetime` < '2024-01-09 10:39:00' and `news`.`deleted_at` is null order by start_datetime desc,newsid asc LIMIT 0,1; ``` 修改後 ```sql= SELECT `news`.* FROM `news` JOIN ( SELECT `newsid` FROM `news` WHERE (`enabled` = 1 OR `web_data_active` = 1) AND LENGTH(`subject`) > 10 AND `newsid` != '20231221A001001' AND (`end_datetime` IS NULL OR `end_datetime` > '2024-01-09 10:39:00') AND `start_datetime` < '2023-12-21 13:49:01' AND `start_datetime` < '2024-01-09 10:39:00' AND `news`.`deleted_at` IS NULL ORDER BY `start_datetime` DESC, `newsid` ASC LIMIT 0, 1 ) AS subquery ON `news`.`newsid` = subquery.`newsid`; ``` ORM方式 第一種 ```php= <?php $result = News::join( DB::raw('(SELECT newsid FROM news WHERE (enabled = 1 OR web_data_active = 1) AND LENGTH(subject) > 10 AND newsid != "20231221A001001" AND (end_datetime IS NULL OR end_datetime > "2024-01-09 10:39:00") AND start_datetime < "2023-12-21 13:49:01" AND start_datetime < "2024-01-09 10:39:00" AND deleted_at IS NULL ORDER BY start_datetime DESC, newsid ASC LIMIT 0, 1) as subquery'), function ($join) { $join->on('news.newsid', '=', 'subquery.newsid'); } ) ->select('news.*') ->get(); ``` 第二種 ```php= <?php $subquery = News::select('newsid') ->where(function ($query) { $query->where('enabled', 1) ->orWhere('web_data_active', 1); }) ->where('subject', '>', 10) ->where('newsid', '!=', '20231221A001001') ->where(function ($query) { $query->whereNull('end_datetime') ->orWhere('end_datetime', '>', '2024-01-09 10:39:00'); }) ->where('start_datetime', '<', '2023-12-21 13:49:01') ->where('start_datetime', '<', '2024-01-09 10:39:00') ->whereNull('deleted_at') ->orderBy('start_datetime', 'desc') ->orderBy('newsid', 'asc') ->limit(1); $result = News::whereIn('newsid', $subquery) ->get(); ``` 原理join的是原本where得資料但只搜尋newsid可以減少查詢時間後再去on id去等於抓取那比資料 ## 大量減少查詢時間2(先抓id在where) ### 原生語法 ```sql= select * from `news` where `newsid` = ( select `newsid` from `news` where (`enabled` = ? or `web_data_active` = ?) and length(`subject`)>10 and `newsid` != ? and (`end_datetime` is null or `end_datetime` > ?) and `start_datetime` < ? and `start_datetime` >= ? and `start_datetime` < ? and `deleted_at` is null order by `start_datetime` desc limit 1 ) and `news`.`deleted_at` is null ``` ### ORM ```php= <?php $news = News::where('newsid', function ($query) use($newsid,$start_datetime,$orm) { $query->select('newsid') ->from('news') ->where(function ($subquery) { $subquery->where('enabled', 1) ->orWhere('web_data_active', 1); }) ->whereRaw('length(`subject`)>10') ->where('newsid', '!=', $newsid) ->where(function ($subquery) { $subquery->whereNull('end_datetime') ->orWhere('end_datetime', '>', date("Y-m-d H:i:00")); }) ->where('start_datetime', '<', date("Y-m-d H:i:00")) ->where('start_datetime', '>=', date("Y-m-d",strtotime("-2 day", strtotime($start_datetime)))) ->where('start_datetime', '<', $start_datetime) ->whereNull('deleted_at') ->orderByDesc('start_datetime') ->first(); }); ``` ### 在php用if的orm ```php= <?php $conditions["whereraw"][] = "(`enabled`=1 or web_data_active=1) and length(`subject`)>10"; $conditions["where"][] = array("start_datetime","<=",date("Y-m-d H:i:00")); $conditions["orwhere"][] = array( array("end_datetime","=",null), array("end_datetime",">",date("Y-m-d H:i:00")), ); $conditions["wherehas"]["tags"] = array("id","=",$tag); $news = News::select('news.*') ->whereHas('tags', function ($query) use ($tag) { $query->where('id', $tag); }) ->joinSub(function ($query) use ($conditions) { $query->select('newsid') ->from('news'); foreach($conditions as $sql_where => $sql_data){ switch ($sql_where){ case "where": foreach ($sql_data as $item) { $query->where($item[0],$item[1],$item[2]); } break; case "whereraw": foreach ($sql_data as $raw) { $query->whereRaw($raw); } break; case "orwhere": foreach ($sql_data as $item) { $query->where(function ($query)use($item) { foreach($item as $sql_key=>$array){ if($sql_key==0){ $query->where($array[0],$array[1],$array[2]); }else{ $query->orwhere($array[0],$array[1],$array[2]); } } }); } break; } } $query->orderByDesc('start_datetime'); $query->limit(12); }, 'subquery', function ($join) { $join->on('news.newsid', '=', 'subquery.newsid'); }); ``` ## 搜尋重覆資料且多筆資料只留id最小資料其他列出來(可用於刪除) ```sql= SELECT a.* FROM stock_daily_price a JOIN ( SELECT stock_id, stock_name, closing_price, stock_price_change, opening_price, highest_price, lowest_price, MIN(id) AS min_id FROM stock_daily_price WHERE updated_at LIKE '2023-12-01%' GROUP BY stock_id, stock_name, closing_price, stock_price_change, opening_price, highest_price, lowest_price HAVING COUNT(*) >= 2 ) b ON a.stock_id = b.stock_id AND a.stock_name = b.stock_name AND a.closing_price = b.closing_price AND a.stock_price_change = b.stock_price_change AND a.opening_price = b.opening_price AND a.highest_price = b.highest_price AND a.lowest_price = b.lowest_price AND a.id != b.min_id WHERE a.updated_at LIKE '2023-12-01%'; ``` ## 搜尋重覆資料兩個相同條件 ```sql= SELECT * FROM daily_tvstock WHERE updated_at LIKE '2023-12-01%' GROUP BY stock_id,hit_count -- 列出所有你想要檢查重複的欄位 HAVING COUNT(*) >= 2; ``` ## 刪除相同重覆資料兩筆兩個相同條件且留id小的 ```sql= DELETE t1 FROM daily_tvstock t1 JOIN daily_tvstock t2 ON t1.stock_id = t2.stock_id AND t1.hit_count = t2.hit_count AND t1.id > t2.id WHERE t1.updated_at LIKE '2023-12-01%' AND t2.updated_at LIKE '2023-12-01%'; ``` ## CONCAT_WS 用來將多個字串值連接起來,並使用指定的分隔符進行分隔 ```sql= where用 concat_ws(\'\', name,city, sub_area, address) like "%'.$search_txt.'%" ' selesect用 CONCAT_WS(separator, string1, string2, string3, ...) 1. separator:分隔符,用來將不同的字串值分隔開來。 2. string1, string2, string3, ...:要連接的字串值。 SELECT CONCAT_WS(', ', first_name, last_name) AS full_name FROM users; +--------------+ | full_name | +--------------+ | John, Doe | | Jane, Smith | | Alice, Brown | +--------------+ ``` ### in,exists 适用于左边大表,右边小表。 https://www.zhihu.com/question/388019803/answer/3167172828 假如有order和user兩張表,其中order表有10000條數據,而user表有100條數據。 這時如果想查一下,所有有效的用戶下過的訂單清單。 可以使用in關鍵字實作: select * from order where user_id in (select id from user where status=1) 也可以使用exists關鍵字實作: select * from order where exists (select 1 from user where order.user_id = user.id and status=1) 前面提到的這種業務場景,使用in關鍵字去實現業務需求,更加適合。 為什麼呢? 因為如果sql語句中包含了in關鍵字,則它會優先執行in裡面的子查詢語句, 然後再執行in外面的語句。 如果in裡面的資料量很少,作為條件查詢速度更快。 而如果sql語句中包含了exists關鍵字,它優先執行exists左邊的語句(即主查詢語句)。 然後把它當作條件,去跟右邊的語句配對。 如果符合上,則可以查詢出資料。 如果匹配不上,資料就被過濾掉了。 這個需求中,order表有10000條數據,而user表有100個數據。 order表是大表,user表是小表。 如果order表在左邊,用in關鍵字表現較好。 exists 適用於左邊小表,右邊大表。 不管是用in,還是exists關鍵字,其核心想法都是用小表驅動大表。 # javascript ## <script defer src="{{ asset(mix('js/page/search_model.js'), true) }}" ></script>> script defer: 這是一個 HTML <script> 標籤的屬性,defer 屬性的作用是告訴瀏覽器在解析完 HTML 文件後才執行這個 JavaScript 檔案,這樣可以確保 DOM(文件物件模型)已經建立完畢。 src="{{ asset(mix('js/page/search_model.js'), true) }}": 這部分是試圖動態生成 JavaScript 檔案的 URL。在 Laravel 框架中,asset 函式用於生成資源的 URL,而 mix 函式則通常用於為資源加上版本號(cache busting),以防止瀏覽器緩存舊版本。最後的 true 參數表示生成絕對 URL。 ## history.replaceState 修改歷史標籤,但不會將瀏覽器重定向到新的URL ```javascript= history.replaceState(stateObj, title, url); ``` 這個方法用於修改歷史標籤,但不會將瀏覽器重定向到新的URL。 stateObj: 表示一個JavaScript對象,與新的狀態有關,可以是null。 title: 用於新的狀態的標題,現代瀏覽器通常忽略這個參數,因此可以傳入空字符串。 url: 新的URL。 在你的代碼中,你使用了 history.replaceState 來替換當前的URL,並且將URL設置為 {{url("/program-post/img")}} + "/" + extractedString。這樣的代碼片段看起來像是在修改URL,使其包含 "/program-post/img" 和 extractedString。 請確保 {{url("/program-post/img")}} 和 extractedString 的值都是正確的並且不包含空格或非法字符,以確保生成的URL是有效的。 ## 擷取字串 ```javascript= var img_url_now = this.slides[index].dataset.url; // 從後面尋找第一個斜線的索引 var lastIndex = img_url_now.lastIndexOf("/"); var dotIndex = img_url_now.lastIndexOf("."); // 擷取字串 var extractedString = img_url_now.substring(lastIndex+1,dotIndex); ``` # jQuery ## 增加屬性attr $('#search_choose_form').attr('action',search_route); ## 移除屬性removeAttr $('#search_input').removeAttr('name'); ## 增加css $('#search_input').css('display','none'); ## 從某個class底下去尋找index ```javascript= $('.schedule').eq($('#week').val()-1).find('tbody tr').eq(index).addClass('highlight-row'); //查看name在第幾個index $(document).on("change", 'input[name^="images"]', function (e) { var inputIndex = $('input[name^="images"]').index(this); var width = $("#rich_menu_select_block").find(".div_block:eq("+inputIndex+")").css('width'); var height = $("#rich_menu_select_block").find(".div_block:eq("+inputIndex+")").css('height') }); ``` ## jQuery Laravel url 用在juqery ```javascript= $("#submit").attr("data-refresh-url","{!! url('/liveendyoutubeschedule?week="+week+"') !!}"); ``` ## jQuery 程式觸發change事件 ```javascript= $('#data_key').val(key).trigger('change'); //觸發change事件 ``` ## jQuery name onchange ```javascript= $('select[name^="rich_menu_type"]').change(function() { var selectedIndex = $('select[name^="rich_menu_type"]').index(this); console.log("Index: " + selectedIndex); }); ``` ## jQuery id onchange ```javascript= $('#data_key').on('change', function() { $(this).find(":selected").val(); $.each( p_data["data"],function(key,array){ $('#list_id').append($('<option>', {value:array["id"], text:array["title"]})); }); }); ``` ## jQuery 最後一行為清除url的get資料 ```javascript= localStorage.removeItem('countdownSeconds'); localStorage.setItem('countdownSeconds', 30); history.replaceState({}, document.title, window.location.pathname); ``` ## jQuery input file 修改檔案 ```htmlembedded= <input type="file" class="form-control" id="multiple_img" name="multiple_img[]" multiple> <script> $(document).ready(function() { $('#multiple_img').change(function() { var files = $('#multiple_img')[0].files; var dataTransfer = new DataTransfer(); if (files.length > 0) { var newFiles = []; for (var i = 0; i < files.length; i++) { if (i !== 0) { dataTransfer.items.add(files[i]); } } } // $('#multiple_img_copy')[0].files = newFiles; $('#multiple_img')[0].files = dataTransfer.files; }); }); </script> ``` ## jQuery input file兩邊同時傳 ```javascript= $('.container').on('click', '.select-save-block-image-trigger', function() { var triggerType = $(this).data('trigger-type'); // 執行相關的邏輯,基於 triggerType(A 或 B) if (triggerType === 'A') { var fileInputs = $("input[name='images_a[]']"); var fileTemps = $("input[name='images_temp_a[]']"); } else if (triggerType === 'B') { var fileInputs = $("input[name='images_b[]']"); var fileTemps = $("input[name='images_temp_b[]']") } console.log(fileInputs); fileInputs.each(function(index, element) { var fileValue = $(this).val(); if (fileValue) { var fileInput = element; // 获取原生 DOM 元素 var file = fileInput.files[index]; // 获取文件 var fileList = new DataTransfer(); fileList.items.add(file); // 设置到相应的目标文件输入元素(例如,fileTemps) fileTemps.eq(index).prop('files', fileList.files); } }); }); ``` ## jQuery file預覽 ```html= <input type="file" class="form-control" id="multiple_img" name="multiple_img[]" multiple> <table class="table table-bordered" id="imagePreviewContainer"> <tbody> <tbody> </table> ``` ```javascript= <script> $(document).ready(function() { $('#multiple_img').change(function() { readURL(this); }); }); function readURL(input) { $('#imagePreviewContainer tbody').empty(); var table = ` <tr class="active"> <th style="width:10px;">排序</th> <th style="width:40px;">圖片</th> </tr>`; if (input.files && input.files.length > 0) { for (let i = 0; i < input.files.length; i++) { const reader = new FileReader(); // reader.readAsDataURL(input.files[i]); const objectURL = URL.createObjectURL(input.files[i]); var sort = i+1; table += ` <tr id="item-${i}"> <td>${sort}</td> <td> <div><img src = "${objectURL}" style="width:200px;"></img></div> </td> </tr>`; } $('#imagePreviewContainer tbody').append(table); } } </script> ``` ## jQuery input <0正規式 ```javascript= $("#skip_time").on("input", function() { // 获取输入框的值 var inputValue = $(this).val(); // 使用正则表达式检查是否为负数 var regex = /^-\d+(\.\d+)?$/; if (regex.test(inputValue)) { // 如果是负数,将其改成0 $(this).val("0"); } }); ``` ## jQuery checkbox 多個name使用 ```javascript= //if簡寫 id ? id = true : id = false; //日期差 var date = new Date(checkin_date).getTime()-new Date(checkout_date).getTime(); var days = Math.abs(date)/(24*3600*1000); // js 計算月日 var start_date = new Date(checkin_date).getTime()-new Date(order_date).getTime(); var start_day = Math.abs(start_date)/(24*3600*1000); //指定日期加幾天 date = new Date (new Date(checkin_date).setDate(new Date(checkin_date).getDate() + i)); getYearMonthDay(date,'/'); //將年月日放進來進行字串整理 function getYearMonthDay(date,symbol){ year = date.getFullYear() month = date.getMonth()+1; day = date.getDate() if (day < 10) { day = '0' + day; } if (month < 10) { month = '0' + month; } r //判斷有沒有進行勾選 $('#' + id).is(":checked") jQuery <1.9 $('#inputId').attr('readonly', true); jQuery 1.9+ $('#inputId').prop('readonly', true); 存資料 $('#checkin_district').val( 123 ); // 多個id或name用相同的event事件用法 $(document).on('input', '#order_name, #order_phone_number, #order_email', function() { }); //取得data-key的資料 多個name使用 <select name="time_of_room" data-key="{{ $key }}" style="width: 180px"> $(document).on('change', 'select[name="time_of_room"]', function(key,value) { key = $(this).attr("data-key"); $('#time_of_room_'+key).prop('checked', true); }); //name checked $('input[name="time_of_meal_'+key+'"]')[key].checked = true //選下拉選單第一個 $('select[name="time_of_restaurant"]').val($('select[name="time_of_restaurant"] option:first').val()); ``` ## jQuery 連點submit問題 ```php= <input type="hidden" class="form-control" id="lastClickTime" name="lastClickTime" value="0"> <button type="submit" class="btn btn-info pull-right _submit_" data-function="form_check();" data-form-id="form" data-refresh-url="{{ url('/analyster/video') }}">提交</button> <script type="text/javascript"> function form_check() { var lastClickTime = $("#lastClickTime").val(); var currentTime = new Date().getTime(); var clickInterval = 2000; // 1秒 $("#lastClickTime").val(new Date().getTime()); if (currentTime - lastClickTime > clickInterval) { if (!analyster_yt_different()) { return false; } return true; } return false; } </script> ``` ## jQuery 按鈕開關 ```php= <style> .tr-odd{background-color: #ccc;} .tr-hover{background-color: #0fa;} .btn-switch { color: whitesmoke; width: 6rem; height: 2.5rem; margin:.1rem; padding: .1rem; background: #555; border: 2px solid #ccc; border-radius: 2rem; transition: .3s; box-shadow: inset 1px 1px 5px #333, .1rem .2rem .5rem #999; } .btn-switch-ball { color: whitesmoke; width: 2rem; height: 2rem; background: #777; border: inset .1rem rgba(153, 153, 153, 0.43); border-radius: 50%; box-sizing: border-box; cursor: pointer; transition: .3s; box-shadow: 1px 1px 5px #000; } .on .btn-switch { background: #777; } .on .btn-switch-ball { background: #999; /* outset .1rem rgba(153, 153, 153, 0.43) */ box-shadow: -1px 1px 5px #000; margin-left: calc(100% - 2rem); } </style> @foreach ($pager as $item) @if($item['enable']==1) <button class="btn-switch"> <div class="btn-switch-ball" data-id="{{ $item['id'] }}">開</div> </button> @else <button class="btn-switch on"> <div class="btn-switch-ball" data-id="{{ $item['id'] }}">關</div> </button> @endif @endforeach <script> $(document).ready(function () { $('.btn-switch-ball').on('click', function () { var $this = $(this); var enable = 0; var message = ""; var dataId = $this.data('id'); if ($this.parent().hasClass('on')) { message = "確定要進行啟用嗎?"; enable = 1; } else { message = "確定要進行關閉嗎?"; enable = 0; } if(confirm(message)){ $this.parent().toggleClass('on'); if(enable==1){ $this.html("開"); }else{ $this.html("關"); } $.ajax({ data: { id: dataId, enable: enable, }, type: 'POST', dataType: 'JSON', url: "{{url('/analyster/analyster_enable')}}", success: function (response) { console.log(response); alert(response.msg); },error: function(response) { alert(response.msg); } }); } }); }); $('tr').hover(function() { $(this).addClass('tr-hover'); }, function() { $(this).removeClass('tr-hover'); }); }); ``` ajax打的資料 ```php= <?php public function analyster_enable(Request $request){ $AnalystVideo = AnalystVideo::find($request->id); $AnalystVideoGcp = AnalystVideo::on('azure_mysql')->find($request->id); switch ($request->enable){ case 0: $AnalystVideo->enable = 0; $AnalystVideoGcp->enable = 0; break; case 1: $AnalystVideo->enable = 1; $AnalystVideoGcp->enable = 1; break; default: $AnalystVideo->enable = 0; $AnalystVideoGcp->enable = 0; } if(!$AnalystVideo->save()){ return $this->retJson(503, '啟用修改失敗!'); } $AnalystVideoGcp->save(); return $this->retJson(200, '操作成功!'); } ``` ## jQuery 抓youtube 的影片長度 ```html= //這一塊用來隱藏iframe youtube的資料,因要抓影片長度資料就會顯示 <div id="player_div" hidden> // player會進行刪除後再新增,若不這樣會影響抓資料的問題 <div id="player"></div> </div> <input type="text" class="form-control" name="video_id" id="video_id" value="@if(isset($item)){{ $item->video_id }}@endif"> <input type="hidden" class="form-control" id="video_duration" name="video_duration" value="0"> <button type="button" id="form_button" class="btn btn-info pull-right">提交</button> <button type="submit" id="submit" style="display: none;"> ```javascript= <script src="https://www.youtube.com/iframe_api"></script> $('#form_button').on('click', function() { event.preventDefault(); // 阻止默认的提交行为 var videoId = extractYouTubeVideoId($('#video_id').val()); onYouTubeIframeAPIReady(videoId).then(function() { onPlayerReady(function(videoDuration) { // 手动触发表单提交 $("#submit").click(); }); }); }); $(document).ready(function() { $('#youtube').on('input', function() { $("#player_div").hide(); $("#player_div").html(""); $("#video_duration").val(0); $("#player_div").append(`<div id="player"></div>`); var videoId = extractYouTubeVideoId($('#youtube').val()); if(videoId){ onYouTubeIframeAPIReady(videoId); setTimeout(function() { console.log($("#video_duration").val()); if ($("#video_duration").val() > 0) { console.log('影片有秒數,不進行移除'); } else { console.log('影片沒有秒數,移除 iframe'); $("#player_div").show(); $("#player_div").html(""); $("#player_div").append(`<font color="red">影片不存在或未公開!</font>`); } }, 1000); } }); function onYouTubeIframeAPIReady(video_id) { return new Promise(function(resolve, reject) { player = new YT.Player('player', { height: '360', width: '640', videoId: video_id, events: { 'onReady': function() { resolve(); onPlayerReady(); }, 'onError': function(errEvent) { console.log(errEvent); var errCode = errEvent.data; if(errCode == 100) { alert('Video Not Found'); } } } }); }); } function onPlayerReady() { try { $("#player_div").show(); console.log(player); var videoDuration = player.getDuration(); // 获取视频长度,单位为秒 var videoTitle = player.getVideoData().title; console.log("视频標題:", videoTitle, "秒"); console.log("视频長度:", videoDuration, "秒"); $("#video_duration").val(videoDuration); player.pauseVideo(); // 暂停播放 player.mute(); // 静音 player.setVolume(0); // 设置音量为 0 } catch (error) { // 在這裡加入錯誤處理的邏輯 console.error("發生錯誤:", error); // 在這裡加入其他處理錯誤的邏輯 $("#player_div").html(""); // 清空 player_div } } function extractYouTubeVideoId(link) { var videoId = ''; var regex = /(?:https?:\/\/)?(?:www\.)?youtube\.com\/watch\?.*v=([a-zA-Z0-9_-]{11})/; var match = link.match(regex); if (match && match[1]) { videoId = match[1]; return videoId; } else { return link; } } }); ``` ## jQuery sortable 表格行拖曳 ### 第一種圖片上傳或修改時調整順序 subject_item.blade.php ```php= <?php <html lang="en"> <head> <meta charset="UTF-8"> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script> </head> <input type="file" class="form-control" id="multiple_img" name="multiple_img[]" multiple> <input type="hidden" class="form-control" id="tmp_img_sort" name="tmp_img_sort" value="@if(isset($item)){{ $item->multiple_img }}@endif" > <table class="table table-bordered" id="imagePreviewContainer"> <p class="table-remark" @if(!isset($item))style="display: none;"@endif><font color="red">*拖曳圖片即可進行排序,拖曳排序完成後需按「提交」按鈕,才會進行儲存這次的排序內容。</font></p> <tbody> @if(isset($item->multiple_imgs)) <tr class="active"> <th style="width:50px;">排序</th> <th>圖片</th> </tr> @foreach ($item->multiple_imgs as $key=>$url) <tr id="item-{{$key}}" class="draggable"> <td>{{ $key+1 }}</td> <td> <div><a target="_blank" href="{{ asset("storage/{$url}?".date('YmdHis')) }}"><img src = "{{ asset("storage/{$url}?".date('YmdHis')) }}" style="width:200px;"></img></a></div> </td> </tr> @endforeach @endif </tbody> </table> ``` js得部分 ```javascirpt= $(document).ready(function() { $('#multiple_img').change(function() { readURL(this); var files = $('#multiple_img')[0].files; $("#tmp_img_sort").val(""); if (files.length > 0) { var array = []; $.each(files, function(index, file) { var fileName = file.name; array.push(`${fileName}`); }); $('#tmp_img_sort').val(array.join(';')); }else{ $(".multiple-img-remark").show(); } }); $( "tbody" ).sortable({ items: 'tr.draggable', axis: 'y', update: function (event, ui) { var serializedString = $(this).sortable('serialize'); var idArray = serializedString.split('&').map(function(pair) { return pair.split('=')[1]; }); // 使用分號拆分成每個鍵值對 var tmp_img_sort = $('#tmp_img_sort').val().split(';'); // 使用 map 方法創建包含索引和值的新陣列 var indexedArray = $.map(tmp_img_sort, function(value, index) { return { index: idArray.indexOf(index.toString()), value: value }; }); // 使用 sort 方法,根據每個元素的索引進行排序 indexedArray.sort(function(a, b) { return a.index - b.index; }); // 提取排序後的值 var sortedValues = $.map(indexedArray, function(item) { return item.value; }); $("#tmp_img_sort").val(sortedValues.join(';')); updateFirstColumn(); } }); $( "#sortable" ).disableSelection(); )}; // 更新表格的第一列数据 function updateFirstColumn() { // 获取所有行的第一列 var firstColumnCells = $("tbody tr td:first-child"); // 遍历排序后的索引,更新第一列的文本 $("tbody tr").each(function (index, row) { var newIndex = $(row).index(); var newText = newIndex+1; // 你可以根据需要修改这里的逻辑 $(firstColumnCells[index]).text(newText); if(index>0){ var newId = "item-" + (index-1); $(row).attr("id", newId); } }); } $( "#sortable" ).disableSelection(); function readURL(input) { $(".table-remark").hide(); $('#imagePreviewContainer tbody').empty(); var table = ` <tr class="active"> <th style="width:50px;">排序</th> <th>圖片</th> </tr>`; if (input.files && input.files.length > 0) { $(".table-remark").show(); for (let i = 0; i < input.files.length; i++) { const reader = new FileReader(); // reader.readAsDataURL(input.files[i]); const objectURL = URL.createObjectURL(input.files[i]); var sort = i+1; table += ` <tr id="item-${i}" class="draggable"> <td>${sort}</td> <td> <div><img src = "${objectURL}" style="width:200px;"></img></div> </td> </tr>`; } $('#imagePreviewContainer tbody').append(table); } } ``` SubjectDateController.php ```php= <?php $tmp_img_sorts = explode(";",$request->tmp_img_sort); $SubjectDate = SubjectDate::find($id); if ($request->hasFile('multiple_img')) { $multiple_imgs = array(); foreach ($request->file('multiple_img') as $key=>$image) { $originalName = $image->getClientOriginalName(); $extension = $image->getClientOriginalExtension(); $size = $image->getSize(); $mime = $image->getMimeType(); $filekey = array_search($originalName, $tmp_img_sorts); $fileName = $SubjectDate->id .'_img' .($filekey+1) .'.'.$extension; $filePath_name = $image->storeAs(config('project.subject_date_dir'), $fileName, 'public'); $multiple_imgs[$filekey] = $filePath_name; } asort($multiple_imgs); $data["multiple_img"] = implode(";",$multiple_imgs); }else{ if($request->input('_method') == 'PUT'){ $data["multiple_img"] = $request->tmp_img_sort; } } ``` ### 第二種直接拖曳修改sort的部分 subject_list.blade.php ```php= <?php <table class="table table-bordered"> <tbody> <tr class="active"> <th style="width:50px;">ID</th> <th style="width:200px;">日期</th> <th style="width:400px;">主題</th> <th>簡介</th> <th style="width:200px;">上架日期</th> <th style="width:200px;">操作</th> </tr> @foreach ($data as $item) <tr id="item-{{$item->id}}" class="draggable"> <td>{{ $item->id }}</td> <td> <div>{{ $item->date }}</div> </td> <td> <div>{{ $item->subject }}</div> </td> <td> <div><pre>{!! $item->intro !!}</pre></div> </td> <td> <div>{{ $item->start_date }}</div> </td> <td> <!-- <button><a href="{{ url('/subjectdate')}}/{{$item['id']}}/editimgsort">圖片排序</a></button> --> <a class="btn btn-primary" role="button" href="{{ url('/subjectdate')}}/{{$item->id}}/edit">編輯</a> <a class="btn btn-secondary _delete_" role="button" href="#" class="_delete_" data-url="{{ url('/subjectdate')}}/{{$item->id}}" data-errmsg="確定要刪除 {{$item->subject}} 嗎?">刪除</a> </td> </tr> @endforeach </tbody> </table> ``` js的部分 ```javascirpt= $(document).ready(function() { $( "tbody" ).sortable({ items: 'tr.draggable', axis: 'y', update: function (event, ui) { var data = $(this).sortable('serialize'); // POST to server using $.post or $.ajax var csrfToken = "{{ csrf_token() }}"; $.ajax({ data: data, type: 'POST', url: '{{url('/subjectdate/group/saveorder')}}', headers: { 'X-CSRF-TOKEN': csrfToken }, success: function (response) { // updateFirstColumn(); location.href = location.href; } }); } }); $( "#sortable" ).disableSelection(); }); ``` SubjectDateController.php ```php= <?php public function saveorder(Request $request){ // $data = SubjectDate::find($request->id); // $multiple_imgs = explode(";",$data->multiple_img); // // 重新排列数组 // $sortedArray = array_map(function ($index) use ($multiple_imgs) { // return $multiple_imgs[$index]; // }, $request->item); // SubjectDate::where('id', $request->id)->update(['multiple_img' => implode(";",$sortedArray)]); // dd($request->item); $i = 0; foreach ($request->item as $index => $id) { $item = SubjectDate::where('id', $id)->first(); $item->update(array('sort'=>$index)); $i++; } } ``` ## jQuery 時間條 ```javascript= .time-bar { width: 500px; height: 20px; border: 1px solid black; position: relative; } .time-handle { width: 0; height: 0; border-left: 5px solid transparent; border-right: 5px solid transparent; position: absolute; bottom: -12px; cursor: pointer; } .start-handle { left: 0; border-bottom: 10px solid blue; } .end-handle { right: 0; border-bottom: 10px solid blue; } .time-range { position: absolute; bottom: 0px; height: 20px; background-color: green; transform-origin: left; } .time-prohibit { position: absolute; bottom: 0px; height: 20px; background-color: red; transform-origin: left; } .time-display { margin-top: 10px; } </style> <div class="form-group"> <label for="week" class="col-sm-2 control-label">*星期:</label> <div class="col-sm-3"> <select class="form-control" id="week" name="week"> <option value="1" @if(isset($item) && $item->week==1) selected="selected" @endif>一</option> <option value="2" @if(isset($item) && $item->week==2) selected="selected" @endif>二</option> <option value="3" @if(isset($item) && $item->week==3) selected="selected" @endif>三</option> <option value="4" @if(isset($item) && $item->week==4) selected="selected" @endif>四</option> <option value="5" @if(isset($item) && $item->week==5) selected="selected" @endif>五</option> <option value="6" @if(isset($item) && $item->week==6) selected="selected" @endif>六</option> <option value="7" @if(isset($item) && $item->week==7) selected="selected" @endif>日</option> </select> </div> </div> <div class="form-group"> <label for="time" class="col-sm-2 control-label">*節目時段:</label> <div class="col-sm-10 time-display"> <input type="time" class="form-control" id="start-time" name="time" value="@if(isset($item)){{ $item->time }}@endif" style="width: 140px;display: inline-block;float: none;" > <p style="display: inline-block;">~</p> <input type="time" class="form-control" id="end-time" name="end_time" value="@if(isset($item)){{ $item->end_time }}@endif" style="width: 140px; display: inline-block;float: none;" > </div> </div> <div class="form-group"> <div class="col-sm-2"> </div> <div class="col-sm-10"> <div class="time-bar"> <div class="time-handle start-handle"></div> <div class="time-handle end-handle"></div> <div class="time-range"></div> <!-- <div class="time-prohibit"></div> --> </div> </div> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"></script> <script> var item = {!! isset($item) ? json_encode($item) : "false" !!}; var week_times = {!! $week_times !!}; $(document).ready(function() { var barWidth = $('.time-bar').width(); var minuteInterval = barWidth / (23 * 60 + 59); // Calculate the width of one minute updateTimeBar(); $('#week').on('change', function() { week = $(this).find(":selected").val(); updateTimeBar(); }); // Update the time display based on the handle position function updateTimeDisplay(handle, timeField) { var handlePosition = handle.position().left; var minutes = Math.round(handlePosition / minuteInterval); var hours = Math.floor(minutes / 60); minutes = minutes % 60; var timeString = hours.toString().padStart(2, '0') + ':' + minutes.toString().padStart(2, '0'); timeField.val(timeString); } function getHandlePosition(timeString){ var hours = parseInt(timeString.split(':')[0]); var minutes = parseInt(timeString.split(':')[1]); var totalMinutes = hours * 60 + minutes; return totalMinutes * minuteInterval; } function updateTimeBar(){ $(".time-prohibit").remove(); $.each(week_times,function(key,array){ if (array["week"]==$('#week').val()){ var startTimeInterval = getHandlePosition(array["time"]); var endTimeInterval = getHandlePosition(array["end_time"]); var left_int =startTimeInterval +5 ; var width_int= endTimeInterval - startTimeInterval; var $newDiv = `<div class="time-prohibit" style="left:${left_int}px;width:${width_int}px;"></div>`; // creates a div element $('.time-bar').append($newDiv); } }); } // Update the handle position based on the time value function updateHandlePosition(handle, timeField) { var handlePosition = getHandlePosition(timeField.val()); handle.css('left', handlePosition + 'px'); $('.time-range').css('left', ($('.start-handle').position().left + 5) + 'px'); $('.time-range').css('width', ($('.end-handle').position().left - $('.start-handle').position().left) + 'px'); } // Initialize the handle positions and time display updateHandlePosition($('.start-handle'), $('#start-time')); updateHandlePosition($('.end-handle'), $('#end-time')); updateTimeDisplay($('.start-handle'), $('#start-time')); updateTimeDisplay($('.end-handle'), $('#end-time')); // Handle dragging of the start handle $('.start-handle').draggable({ axis: 'x', containment: 'parent', drag: function() { updateTimeDisplay($(this), $('#start-time')); updateHandlePosition($('.start-handle'), $('#start-time')); }, stop: function() { updateTimeDisplay($(this), $('#start-time')); } }); // Handle dragging of the end handle $('.end-handle').draggable({ axis: 'x', containment: 'parent', drag: function() { updateTimeDisplay($(this), $('#end-time')); updateHandlePosition($('.end-handle'), $('#end-time')); }, stop: function() { updateTimeDisplay($(this), $('#end-time')); } }); // Update start time field when its value changes $('#start-time').on('input', function() { updateHandlePosition($('.start-handle'), $(this)); }); // Update end time field when its value changes $('#end-time').on('input', function() { updateHandlePosition($('.end-handle'), $(this)); }); }); </script> ``` ## jQuery遇到的問題 ### jQuery submit onclick 事件觸發資料會直接送 這邊可以先利用button做onclick去觸發submit然後把submit隱藏起來就好 ```php= <button type="button" id="form_button" class="btn btn-info pull-right">提交</button> <button type="submit" id="submit" style="display: none;"> $('#form_button').on('click', function() { // 手动触发表单提交 $("#submit").click(); }); ``` ### jQuery Ajax送到controller的update 空值 create有資料 :::danger 錯誤訊息 Symfony\\Component\\HttpKernel\\Exception\\HttpException CSRF token mismatch. ::: :::danger 因Restful API修改用put但實則上ajax type只接受get和post 如果是要修改就要先type=post然後data裡面在上面_method=put就即可解決 ::: ```php= <?php @if($method=="store") <form id="form" action="{{ url('/subjectdate') }}" enctype="multipart/form-data"> @else <form id="form" action="{{ url('/subjectdate/'.$item->id) }}" enctype="multipart/form-data"> @method('PUT') @endif @csrf <input type="submit" class="btn btn-info" value="提交"> ``` ```javascript= $(document).ready(function() { $('#form').on('submit', function(e) { e.preventDefault(); // 阻止表单默认提交行为 // 使用 .serializeArray() 获取表单字段 var formData = $(this).serializeArray(); form = $('#form')[0]; var formData = new FormData(form); // 获取表单字段 var formAction = $(this).attr('action'); var type = "POST"; // 发送 AJAX 请求 $.ajax({ type: type, data: formData, url: formAction, // 替换为实际的验证路由 processData: false, contentType: false, success: function(response) { // 验证成功,执行相关操作 if(response.status=="success"){ Swal.fire({ title: '成功', text: response.message, icon: 'success', confirmButtonText: '確認', timer: 2000, // 設定計時器為 2000 毫秒(2 秒) showConfirmButton: false // 隱藏確認按鈕 }).then((result) => { // 使用 JavaScript 重新導向到新頁面 location.reload(); }); } console.log(response); }, error: function(xhr) { if (xhr.status === 422) { // 验证失败,显示错误消息 var errors = xhr.responseJSON; var errorContainer = $('#errorContainer'); errorContainer.find('ul').empty(); // 清空之前的错误消息 // 构建错误消息并显示 $.each(errors.errors, function(key, value) { errorContainer.find('ul').append('<li>' + value + '</li>'); }); errorContainer.show(); } else { // 处理其他错误 console.log('An error occurred'); } } }); }); }); ``` ### jQuery 事件沒反應換成如下 ```javascript= $(document).on("change", 'select[name^="rich_menu_type"]', function () { console.log(this); }); ``` # AJAX ## ajax包function return data 記得PHP 要將資料轉成JSON json_encode() ```javascript= function List(id){ var res = query(); console.log(res); switch(res.status) { case 'success': alert(msg); return false; break; case 'fail': alert(res.msg); return false; break; default: alert('查詢空房失敗'); return false; } } {{-- (done)查詢 --}} function SearchRoomquery() { var data = ''; $.ajax({ url: "{{ route('Front::Search') }}", type: 'GET', headers: {'X-CSRF-TOKEN': '{{ csrf_token() }}'}, async: false, dataType: 'JSON', data: { checkin_date: $('#checkin_date').val(), checkout_date: $('#checkout_date').val() $('#order_data').serialize(), }, success: function (e) { data = e; }, error: function(xhr, type) { // do nothing } }); return data; } #jQuery onclick(product.edut()) var product = { 'insert': function() { $('#save_button').text('新增'); $('#save_button').attr("onClick","product.save_insert();"); $('#order_data')[0].reset(); $('#checkin_date').attr({"min" : now_date}); $('#checkout_date').attr({"min" : now_date}); $('#checkin_date').val(now_date); },'edit': function(id) { $('h4.modal-title').html('訂單管理'); OrderListLoad(id); $('#product_info').modal('show'); } ``` ## ```php= ``` # CSS 如果col沒辦法同行有可能套件問題直接加style ```html= <div style = "display:inline-block"> </div> ``` 直接對子層下css ```html= <style> .table>tbody>tr>td>a{ color: #337ab7; text-decoration: none; } </style> ``` # npm安裝(webpack.mix.js更改) ```php= npm install ``` webpack.mix.js 更改 ```php= # 編譯開發資源 npm run dev # 或者,啟動監視模式,當資源文件更改時自動重新編譯 npm run watch ``` 在這兩個指令中,npm run dev 用於編譯開發版本,而 npm run watch 則會啟動監視模式,當檔案更改時自動重新編譯。 運行這些指令之後,Laravel Mix 將根據您的 webpack.mix.js 文件重新編譯前端資源。這樣的更改才會生效,並且生成的檔案將反映您對 webpack.mix.js 文件所做的更改。 請注意,有時可能需要清除瀏覽器緩存,或者在瀏覽器中強制刷新頁面,以確保您看到最新的前端資源。這通常可以通過在瀏覽器中按下 Ctrl + F5(Windows/Linux)或 Cmd + Shift + R(Mac)實現。