PHP? imagemagick ? gd ????? ??? ?? ???? ?????.
Jul 25, 2016 am 08:52 AM
分享一個(gè)php實(shí)現(xiàn)的縮略圖類,支持imagemagick及gd庫兩種處理的縮略圖生成類,功能包括按區(qū)域裁剪圖片、添加水印、包括水印功能、透明度等,需要的朋友參考下。
php實(shí)現(xiàn)同時(shí)支持imagemagick及gd庫的縮略圖生成類與用法。 一、功能: 1、按比例縮小/放大 2、填充背景色 3、按區(qū)域裁剪 4、添加水印,包括水印的位置,透明度等 使用imagemagick/GD庫實(shí)現(xiàn),imagemagick地址:www.imagemagick.org 先安裝imagemagick,安裝方法: http://bbs.it-home.org/php/25871.html 二、實(shí)現(xiàn)方法: 1,PicThumb.class.php類文件: <?php /** 縮略圖生成類,支持imagemagick及gd庫兩種處理 * Date: 2013-07-15 * Author: fdipzone * Ver: 1.2 * * Func: * public set_config: 設(shè)置參數(shù) * public create_thumb: 生成縮略圖 * private fit: 縮略圖片 * private crop: 裁剪圖片 * private gd_fit: GD庫縮略圖片 * private gd_crop: GD庫裁剪圖片 * private get_size: 獲取要轉(zhuǎn)換的size * private get_crop_offset: 獲取裁圖的偏移量 * private add_watermark: 添加水印 * private check_handler: 判斷處理程序是否已安裝 * private create_dirs: 創(chuàng)建目錄 * private exists: 判斷參數(shù)是否存在 * private to_log: 記錄log * private hex2rgb: hex顏色轉(zhuǎn)rgb顏色 * private get_file_ext: 獲取圖片類型 * * ver: 1.1 增加GD庫處理 * ver: 1.2 增加width,height錯(cuò)誤參數(shù)處理 * 增加當(dāng)圖片colorspace不為RGB時(shí)作轉(zhuǎn)RGB處理 * 修正使用crop保存為gif時(shí)出現(xiàn)透明無效區(qū)域問題,使用+repage參數(shù),刪除透明無效區(qū)域即可 * * tips:建議使用imagemagick * GD庫不支持透明度水印,如果必須使用透明水印,請(qǐng)將水印圖片做成有透明度。 * GD庫輸出gif如加透明水印,會(huì)有問題。 */ class PicThumb{ // class start private $_log = null; // log file private $_handler = null; // 進(jìn)行圖片處理的程序,imagemagick/gd庫 private $_type = 'fit'; // fit or crop private $_source = null; // 原圖路徑 private $_dest = null; // 縮略圖路徑 private $_watermark = null; // 水印圖片 private $_opacity = 75; // 水印圖片透明度,gd庫不支持 private $_gravity = 'SouthEast'; // 水印擺放位置 NorthWest, North, NorthEast, West, Center, East, SouthWest, South, SouthEast private $_geometry = '+10+10'; // 水印定位,gd庫不支持 private $_croppos = 'TL'; // 截圖的位置 TL TM TR ML MM MR BL BM BR private $_bgcolor = null; // 填充的背景色 private $_quality = 90; // 生成的圖片質(zhì)量 private $_width = null; // 指定區(qū)域?qū)挾? private $_height = null; // 指定區(qū)域高度 // 初始化 public function __construct($logfile=''){ if($logfile!=''){ $this->_log = $logfile; } } // 設(shè)置參數(shù) public function set_config($param=array()){ $this->_handler = $this->exists($param, 'handler')? strtolower($param['handler']) : null; $this->_type = $this->exists($param, 'type')? strtolower($param['type']) : 'fit'; $this->_watermark = $this->exists($param, 'watermark')? $param['watermark'] : null; $this->_opacity = $this->exists($param, 'opacity')? $param['opacity'] : 75; $this->_gravity = $this->exists($param, 'gravity')? $param['gravity'] : 'SouthEast'; $this->_geometry = $this->exists($param, 'geometry')? $param['geometry'] : '+10+10'; $this->_croppos = $this->exists($param, 'croppos')? $param['croppos'] : 'TL'; $this->_bgcolor = $this->exists($param, 'bgcolor')? $param['bgcolor'] : null; $this->_quality = $this->exists($param, 'quality')? $param['quality'] : 90; $this->_width = $this->exists($param, 'width')? $param['width'] : null; $this->_height = $this->exists($param, 'height')? $param['height'] : null; } /** 創(chuàng)建縮略圖 * @param String $source 原圖 * @param String $dest 目標(biāo)圖 * @return boolean */ public function create_thumb($source, $dest){ // 檢查使用的handler是否已安裝 if(!$this->check_handler()){ $this->to_log('handler not installed'); return false; } // 判斷區(qū)域?qū)捀呤欠裾_ if(!is_numeric($this->_width) || !is_numeric($this->_height) || $this->_width<=0 || $this->_height<=0){ $this->to_log('width or height invalid'); return false; } // 判斷源文件是否存在 if(!file_exists($source)){ $this->to_log($source.' not exists'); return false; } // 創(chuàng)建目標(biāo)文件路徑 if(!$this->create_dirs($dest)){ $this->to_log(dirname($dest).' create fail'); return false; } $this->_source = $source; // 源文件 $this->_dest = $dest; // 目標(biāo)文件 // 處理圖片 switch($this->_type){ case 'fit': if($this->_handler=='imagemagick'){ return $this->fit(); }else{ return $this->gd_fit(); } break; case 'crop': if($this->_handler=='imagemagick'){ return $this->crop(); }else{ return $this->gd_crop(); } break; default: $this->to_log($this->_type.' not fit and crop'); return false; } } /** 按比例壓縮或拉伸圖片 * @return boolean */ private function fit(){ // 判斷是否填充背景 $bgcolor = ($this->_bgcolor!=null)? sprintf(" -background '%s' -gravity center -extent '%sx%s' ", $this->_bgcolor, $this->_width, $this->_height) : ""; // 判斷是否要轉(zhuǎn)為RGB $source_info = getimagesize($this->_source); $colorspace = (!isset($source_info['channels']) || $source_info['channels']!=3)? ' -colorspace RGB ' : ''; // 命令行 $cmd = sprintf("convert -resize '%sx%s' '%s' %s -quality %s %s '%s'", $this->_width, $this->_height, $this->_source, $bgcolor, $this->_quality, $colorspace, $this->_dest); // 記錄執(zhí)行的命令 $this->to_log($cmd); // 執(zhí)行命令 exec($cmd); // 添加水印 $this->add_watermark($this->_dest); return is_file($this->_dest)? true : false; } /** 裁剪圖片 * @return boolean */ private function crop(){ // 獲取生成的圖片尺寸 list($pic_w, $pic_h) = $this->get_size(); // 獲取截圖的偏移量 list($offset_w, $offset_h) = $this->get_crop_offset($pic_w, $pic_h); // 判斷是否要轉(zhuǎn)為RGB $source_info = getimagesize($this->_source); $colorspace = (!isset($source_info['channels']) || $source_info['channels']!=3)? ' -colorspace RGB ' : ''; // 命令行 $cmd = sprintf("convert -resize '%sx%s' '%s' -quality %s %s -crop %sx%s+%s+%s +repage '%s'", $pic_w, $pic_h, $this->_source, $this->_quality, $colorspace, $this->_width, $this->_height, $offset_w, $offset_h, $this->_dest); // 記錄執(zhí)行的命令 $this->to_log($cmd); // 執(zhí)行命令 exec($cmd); // 添加水印 $this->add_watermark($this->_dest); return is_file($this->_dest)? true : false; } /** GD庫按比例壓縮或拉伸圖片 * @return boolean */ private function gd_fit(){ // 獲取生成的圖片尺寸 list($pic_w, $pic_h) = $this->get_size(); list($owidth, $oheight, $otype) = getimagesize($this->_source); switch($otype){ case 1: $source_img = imagecreatefromgif($this->_source); break; case 2: $source_img = imagecreatefromjpeg($this->_source); break; case 3: $source_img = imagecreatefrompng($this->_source); break; default: return false; } // 按比例縮略/拉伸圖片 $new_img = imagecreatetruecolor($pic_w, $pic_h); imagecopyresampled($new_img, $source_img, 0, 0, 0, 0, $pic_w, $pic_h, $owidth, $oheight); // 判斷是否填充背景 if($this->_bgcolor!=null){ $bg_img = imagecreatetruecolor($this->_width, $this->_height); $rgb = $this->hex2rgb($this->_bgcolor); $bgcolor =imagecolorallocate($bg_img, $rgb['r'], $rgb['g'], $rgb['b']); imagefill($bg_img, 0, 0, $bgcolor); imagecopy($bg_img, $new_img, (int)(($this->_width-$pic_w)/2), (int)(($this->_height-$pic_h)/2), 0, 0, $pic_w, $pic_h); $new_img = $bg_img; } // 獲取目標(biāo)圖片的類型 $dest_ext = $this->get_file_ext($this->_dest); // 生成圖片 switch($dest_ext){ case 1: imagegif($new_img, $this->_dest, $this->_quality); break; case 2: imagejpeg($new_img, $this->_dest, $this->_quality); break; case 3: imagepng($new_img, $this->_dest, (int)(($this->_quality-1)/10)); break; } if(isset($source_img)){ imagedestroy($source_img); } if(isset($new_img)){ imagedestroy($new_img); } // 添加水印 $this->add_watermark($this->_dest); return is_file($this->_dest)? true : false; } /** GD庫裁剪圖片 * @return boolean */ private function gd_crop(){ // 獲取生成的圖片尺寸 list($pic_w, $pic_h) = $this->get_size(); // 獲取截圖的偏移量 list($offset_w, $offset_h) = $this->get_crop_offset($pic_w, $pic_h); list($owidth, $oheight, $otype) = getimagesize($this->_source); switch($otype){ case 1: $source_img = imagecreatefromgif($this->_source); break; case 2: $source_img = imagecreatefromjpeg($this->_source); break; case 3: $source_img = imagecreatefrompng($this->_source); break; default: return false; } // 按比例縮略/拉伸圖片 $tmp_img = imagecreatetruecolor($pic_w, $pic_h); imagecopyresampled($tmp_img, $source_img, 0, 0, 0, 0, $pic_w, $pic_h, $owidth, $oheight); // 裁剪圖片 $new_img = imagecreatetruecolor($this->_width, $this->_height); imagecopyresampled($new_img, $tmp_img, 0, 0, $offset_w, $offset_h, $this->_width, $this->_height, $this->_width, $this->_height); // 獲取目標(biāo)圖片的類型 $dest_ext = $this->get_file_ext($this->_dest); // 生成圖片 switch($dest_ext){ case 1: imagegif($new_img, $this->_dest, $this->_quality); break; case 2: imagejpeg($new_img, $this->_dest, $this->_quality); break; case 3: imagepng($new_img, $this->_dest, (int)(($this->_quality-1)/10)); break; } if(isset($source_img)){ imagedestroy($source_img); } if(isset($tmp_img)){ imagedestroy($tmp_img); } if(isset($new_img)){ imagedestroy($new_img); } // 添加水印 $this->add_watermark($this->_dest); return is_file($this->_dest)? true : false; } /** 獲取目標(biāo)圖生成的size * @return Array $width, $height */ private function get_size(){ list($owidth, $oheight) = getimagesize($this->_source); $width = (int)($this->_width); $height = (int)($this->_height); switch($this->_type){ case 'fit': $pic_w = $width; $pic_h = (int)($pic_w*$oheight/$owidth); if($pic_h>$height){ $pic_h = $height; $pic_w = (int)($pic_h*$owidth/$oheight); } break; case 'crop': if($owidth>$oheight){ $pic_h = $height; $pic_w = (int)($pic_h*$owidth/$oheight); }else{ $pic_w = $width; $pic_h = (int)($pic_w*$oheight/$owidth); } break; } return array($pic_w, $pic_h); } /** 獲取截圖的偏移量 * @param int $pic_w 圖寬度 * @param int $pic_h 圖高度 * @return Array $offset_w, $offset_h */ private function get_crop_offset($pic_w, $pic_h){ $offset_w = 0; $offset_h = 0; switch(strtoupper($this->_croppos)){ case 'TL': $offset_w = 0; $offset_h = 0; break; case 'TM': $offset_w = (int)(($pic_w-$this->_width)/2); $offset_h = 0; break; case 'TR': $offset_w = (int)($pic_w-$this->_width); $offset_h = 0; break; case 'ML': $offset_w = 0; $offset_h = (int)(($pic_h-$this->_height)/2); break; case 'MM': $offset_w = (int)(($pic_w-$this->_width)/2); $offset_h = (int)(($pic_h-$this->_height)/2); break; case 'MR': $offset_w = (int)($pic_w-$this->_width); $offset_h = (int)(($pic_h-$this->_height)/2); break; case 'BL': $offset_w = 0; $offset_h = (int)($pic_h-$this->_height); break; case 'BM': $offset_w = (int)(($pic_w-$this->_width)/2); $offset_h = (int)($pic_h-$this->_height); break; case 'BR': $offset_w = (int)($pic_w-$this->_width); $offset_h = (int)($pic_h-$this->_height); break; } return array($offset_w, $offset_h); } /** 添加水印 * @param String $dest 圖片路徑 */ private function add_watermark($dest){ if($this->_watermark!=null && file_exists($this->_watermark) && file_exists($dest)){ list($owidth, $oheight, $otype) = getimagesize($dest); list($w, $h, $wtype) = getimagesize($this->_watermark); // 水印圖比原圖要小才加水印 if($w<=$owidth && $h<=$oheight){ if($this->_handler=='imagemagick'){ // imagemagick 添加水印 $cmd = sprintf("composite -gravity %s -geometry %s -dissolve %s '%s' %s %s", $this->_gravity, $this->_geometry, $this->_opacity, $this->_watermark, $dest, $dest); $this->to_log($cmd); exec($cmd); }else{ // gd 添加水印 switch($wtype){ case 1: $water_img = imagecreatefromgif($this->_watermark); break; case 2: $water_img = imagecreatefromjpeg($this->_watermark); break; case 3: $water_img = imagecreatefrompng($this->_watermark); break; default: return false; } switch($otype){ case 1: $dest_img = imagecreatefromgif($dest); break; case 2: $dest_img = imagecreatefromjpeg($dest); break; case 3: $dest_img = imagecreatefrompng($dest); break; default: return false; } // 水印位置 switch(strtolower($this->_gravity)){ case 'northwest': $posX = 0; $posY = 0; break; case 'north': $posX = ($owidth - $w) / 2; $posY = 0; break; case 'northeast': $posX = $owidth - $w; $posY = 0; break; case 'west': $posX = 0; $posY = ($oheight - $h) / 2; break; case 'center': $posX = ($owidth - $w) / 2; $posY = ($oheight - $h) / 2; break; case 'east': $posX = $owidth - $w; $posY = ($oheight - $h) / 2; break; case 'southwest': $posX = 0; $posY = $oheight - $h; break; case 'south': $posX = ($owidth - $w) / 2; $posY = $oheight - $h; break; case 'southeast': $posX = $owidth - $w; $posY = $oheight - $h; break; } imagealphablending($dest_img, true); imagecopy($dest_img, $water_img, $posX, $posY, 0, 0, $w, $h); switch($otype){ case 1:imagegif($dest_img, $dest, $this->_quality); break; case 2:imagejpeg($dest_img, $dest, $this->_quality); break; case 3:imagepng($dest_img, $dest, (int)(($this->_quality-1)/10)); break; } if(isset($water_img)){ imagedestroy($water_img); } if(isset($dest_img)){ imagedestroy($dest_img); } } } } } /** 判斷處理程序是否已安裝 * @return boolean */ private function check_handler(){ $handler = $this->_handler; if(!in_array($handler, array('imagemagick', 'gd', null))){ return false; } // 檢查是否有安裝imagemagick $imagemagick_installed = strstr(shell_exec('convert -version'),'Version: ImageMagick')!=''? true : false; // 檢查是否有安裝gd庫 $gd_installed = function_exists('gd_info')? true : false; switch($handler){ case 'imagemagick': return $imagemagick_installed; break; case 'gd': return $gd_installed; break; case null: if($imagemagick_installed){ $this->_handler = 'imagemagick'; return true; } if($gd_installed){ $this->_handler = 'gd'; return true; } break; } return false; } /** 創(chuàng)建圖片目錄 * @param String $path * @return boolean */ private function create_dirs($dest){ if(!is_dir(dirname($dest))){ return mkdir(dirname($dest), 0777, true); } return true; } /** 判斷參數(shù)是否存在 * @param Array $obj 數(shù)組對(duì)象 * @param String $key 要查找的key * @return boolean */ private function exists($obj,$key=''){ if($key==''){ return isset($obj) && !empty($obj); }else{ $keys = explode('.',$key); for($i=0,$max=count($keys); $i<$max; $i++){ if(isset($obj[$keys[$i]])){ $obj = $obj[$keys[$i]]; }else{ return false; } } return isset($obj) && !empty($obj); } } /** 記錄log * @param String $msg 要記錄的log訊息 */ private function to_log($msg){ if($this->_log){ $msg = '['.date('Y-m-d H:i:s').']'.$msg."\r\n"; file_put_contents($this->_log, $msg, FILE_APPEND); } } /** hex顏色轉(zhuǎn)rgb顏色 * @param String $color hex顏色 * @return Array */ private function hex2rgb($hexcolor){ $color = str_replace('#', '', $hexcolor); if (strlen($color) > 3) { $rgb = array( 'r' => hexdec(substr($color, 0, 2)), 'g' => hexdec(substr($color, 2, 2)), 'b' => hexdec(substr($color, 4, 2)) ); } else { $r = substr($color, 0, 1) . substr($color, 0, 1); $g = substr($color, 1, 1) . substr($color, 1, 1); $b = substr($color, 2, 1) . substr($color, 2, 1); $rgb = array( 'r' => hexdec($r), 'g' => hexdec($g), 'b' => hexdec($b) ); } return $rgb; } /** 獲取圖片類型 * @param String $file 圖片路徑 * @return int */ private function get_file_ext($file){ $filename = basename($file); list($name, $ext)= explode('.', $filename); $ext_type = 0; switch(strtolower($ext)){ case 'jpg': case 'jpeg': $ext_type = 2; break; case 'gif': $ext_type = 1; break; case 'png': $ext_type = 3; break; } return $ext_type; } } // class end ?> 2,php縮略圖類的調(diào)用示例。 <?php define('ROOT', dirname(__FILE__)); require(ROOT."/PicThumb.class.php"); $logfile = ROOT.'/PicThumb.log'; $source1 = ROOT.'/pic/source.jpg'; $dest1 = ROOT.'/pic/1.jpg'; $dest2 = ROOT.'/pic/2.gif'; $dest3 = ROOT.'/pic/3.png'; $source2 = ROOT.'/pic/source_cmyk.jpg'; $dest4 = ROOT.'/pic/4.jpg'; $dest5 = ROOT.'/pic/5.gif'; $dest6 = ROOT.'/pic/6.png'; $watermark = ROOT.'/pic/watermark.png'; // 按比例生成縮略圖 $param = array( 'type' => 'fit', 'width' => 100, 'height' => 100, ); $obj = new PicThumb($logfile); $obj->set_config($param); $flag = $obj->create_thumb($source1, $dest1); if($flag){ echo '<img src="/static/imghw/default1.png" data-src="pic/'.basename($dest1).'" class="lazy".basename($dest1).'" alt="PHP? imagemagick ? gd ????? ??? ?? ???? ?????." >'; }else{ echo 'create thumb fail'; } // 按比例生成縮略圖,不足部分用#FF0000填充 $param = array( 'type' => 'fit', 'width' => 100, 'height' => 100, 'bgcolor' => '#FFFF00' ); $obj = new PicThumb($logfile); $obj->set_config($param); $flag = $obj->create_thumb($source1, $dest2); if($flag){ echo '<img src="/static/imghw/default1.png" data-src="pic/'.basename($dest2).'" class="lazy".basename($dest2).'" alt="PHP? imagemagick ? gd ????? ??? ?? ???? ?????." >'; }else{ echo 'create thumb fail'; } // 裁剪250x250的縮略圖,裁剪位置是底部中間,水印位置西南,透明度50 $param = array( 'type' => 'crop', 'croppos' => 'BM', 'width' => 250, 'height' => 250, 'watermark' => $watermark, 'opacity' => 50, 'gravity' => 'SouthWest' ); $obj = new PicThumb($logfile); $obj->set_config($param); $flag = $obj->create_thumb($source1, $dest3); if($flag){ echo '<img src="/static/imghw/default1.png" data-src="pic/'.basename($dest3).'" class="lazy".basename($dest3).'" alt="PHP? imagemagick ? gd ????? ??? ?? ???? ?????." >'; }else{ echo 'create thumb fail'; } // 按比例生成縮略圖 CMYK格式 $param = array( 'type' => 'fit', 'width' => 100, 'height' => 100, ); $obj = new PicThumb($logfile); $obj->set_config($param); $flag = $obj->create_thumb($source2, $dest4); if($flag){ echo '<img src="/static/imghw/default1.png" data-src="pic/'.basename($dest4).'" class="lazy".basename($dest4).'" alt="PHP? imagemagick ? gd ????? ??? ?? ???? ?????." >'; }else{ echo 'create thumb fail'; } // 按比例生成縮略圖,不足部分用#FF0000填充 CMYK格式 $param = array( 'type' => 'fit', 'width' => 100, 'height' => 100, 'bgcolor' => '#FFFF00' ); $obj = new PicThumb($logfile); $obj->set_config($param); $flag = $obj->create_thumb($source2, $dest5); if($flag){ echo '<img src="/static/imghw/default1.png" data-src="pic/'.basename($dest5).'" class="lazy".basename($dest5).'" alt="PHP? imagemagick ? gd ????? ??? ?? ???? ?????." >'; }else{ echo 'create thumb fail'; } // 裁剪250x250的縮略圖,裁剪位置是底部中間,水印位置西南,透明度50 CMYK格式 $param = array( 'type' => 'crop', 'croppos' => 'BM', 'width' => 250, 'height' => 250, 'watermark' => $watermark, 'opacity' => 50, 'gravity' => 'SouthWest' ); $obj = new PicThumb($logfile); $obj->set_config($param); $flag = $obj->create_thumb($source2, $dest6); if($flag){ echo '<img src="/static/imghw/default1.png" data-src="pic/'.basename($dest6).'" class="lazy".basename($dest6).'" alt="PHP? imagemagick ? gd ????? ??? ?? ???? ?????." >'; }else{ echo 'create thumb fail'; } ?> |

? AI ??

Undress AI Tool
??? ???? ??

Undresser.AI Undress
???? ?? ??? ??? ?? AI ?? ?

AI Clothes Remover
???? ?? ???? ??? AI ?????.

Clothoff.io
AI ? ???

Video Face Swap
??? ??? AI ?? ?? ??? ???? ?? ???? ??? ?? ????!

?? ??

??? ??

???++7.3.1
???? ?? ?? ?? ???

SublimeText3 ??? ??
??? ??, ???? ?? ????.

???? 13.0.1 ???
??? PHP ?? ?? ??

???? CS6
??? ? ?? ??

SublimeText3 Mac ??
? ??? ?? ?? ?????(SublimeText3)

PHP ?? ??? ?? ???? ?? ? ????? ??? ?????. 1. ?? ??? ??? ??? ??? ? ? ??? ??? ??? ?? ?? ??? ???? ???????. 2. ?? ??? ???? ???? ? ?? ????? ?? ?? ?? ??? ?????. 3. $ _get ? $ _post? ?? Hyperglobal ??? ?? ???? ?? ??? ? ??? ??? ??????? ???????. 4. ?? ?? ?? ???? ?? ?? ?? ??? ?????? ?? ??? ??? ?? ??? ???????. ??? ??? ????? ??? ??? ?? ???? ????? ? ??? ? ? ????.

PHP ?? ???? ???? ????? ?? ? ??? ???? ?? ?? ? ??? ???? ?? ??? ?????? ??? ??? ? ? ???????. 1. ??? ?? CSRF? ???? ?? ??? ??? ???? ?????? ??? ???? FINFO_FILE? ?? ?? MIME ??? ?????. 2. ??? ??? ??? ???? ??? ?? ??? ?? ? WEB ????? ??? ???? ??????. 3. PHP ?? ??? ?? ? ?? ???? NGINX/APACHE? ??? ????? ?? ???? ?????. 4. GD ?????? ??? ? ?? ???? ??? ?? ??? ?? ????.

PHP ?? ???? ? ?? ???? ??? ????. 1. // ?? #? ???? ? ?? ??? ???? // ???? ?? ????. 2. ?? /.../ ?? ?? ?? ??? ????? ?? ? ?? ??? ?? ? ? ????. 3. ?? ?? ?? / if () {} /? ?? ?? ??? ????? ??? ?? ?? ?? ??? ???? ????? ???? ??? ?? ???? ???? ??? ? ??? ??????.

Ageneratorinphpisamemory- ???? Way-Erate-Overgedatasetsetsbaluesoneatimeatimeatimeatimallatonce.1.generatorsuseTheyieldKeywordTocroadtOpvaluesondemand, RetingMemoryUsage.2

PHP ??? ???? ??? ??? ??? ????? ????. ??? ????? ?? ???? ??? "?? ? ?"??? "?"? ???????. 1. ??? ? ??? ??? DocBlock (/*/)? ?? ?? ??? ???? ??? ? ?? ???? ??????. 2. JS ??? ???? ?? ???? ??? ?? ??? ??? ?????. 3. ??? ?? ?? ?? ??? ???? ????? ????? ???? ?? ????? ???? ? ??????. 4. Todo ? Fixme? ????? ???? ? ? ??? ??? ???? ?? ?? ? ??? ???????. ??? ???? ?? ??? ??? ?? ?? ?? ???? ???? ? ????.

tolearnpheffectical, startBysetTupaloCalserErverEnmentUsingToolslikexamppandacodeeditor -likevscode.1) installxamppforapache, mysql, andphp.2) useacodeeditorforsyntaxsupport.3)) 3) testimplephpfile.next, withpluclucincludechlucincluclucludechluclucled

PHP??? ???? ??? ?? ?? ????? ???? ??? ?? ??? ??? ?? ? ??? ??? ???? ?????. ???? 0?? ???? ?? ??? ???? ? ?? ???? ?? ?? ? ? ????. MB_SUBSTR? ?? ??? ??? ???????. ? : $ str = "hello"; echo $ str [0]; ?? H; ??? MB_SUBSTR ($ str, 1,1)? ?? ??? ??? ??? ??????. ?? ???????? ???? ??? ???? ?? ???? ?? ?? ???? ?????? ??? ????? ?? ??? ?? ??? ???? ???? ?? ????.

toinstallphpquickly, usexampponwindowsorhomebrewonmacos.1. ??, downloadandinstallxAmpp, selectComponents, startApache ? placefilesinhtdocs.2
