Home Backend Development PHP Tutorial Multi-threaded cURL

Multi-threaded cURL

Jul 25, 2016 am 08:49 AM

This is a flexible multi-threaded call to cURL.
This is different from the sample provided in the PHP manual http://us2.php.net/manual/zh/function.curl-multi-select.php. The code execution efficiency is much higher
There are two files here, one It is a file of muti_curl, which contains two classes
一个是运用的方法,这里是批量检查代理ip是否可用
  1. class request_setting {
  2. public $url = false;
  3. public $method = 'GET';
  4. public $post_data = null;
  5. public $headers = null;
  6. public $options = null;
  7. function __construct($url, $method = "GET", $post_data = null, $headers = null, $options = null) {
  8. $this->url = $url;
  9. $this->method = $method;
  10. $this->post_data = $post_data;
  11. $this->headers = $headers;
  12. $this->options = $options;
  13. }
  14. public function __destruct() {
  15. unset($this->url, $this->method, $this->post_data, $this->headers, $this->options);
  16. }
  17. }
  18. /***************************************************** *******************************************
  19. Classes for batch operations
  20. * *************************************************** ****************************************/
  21. class muti_curl {
  22. protected $thread_size = 100;
  23. protected $timeout = 30;
  24. private $callback;
  25. protected $options = array(
  26. CURLOPT_SSL_VERIFYPEER => false,//禁用后cURL将终止从服务端进行验证。使用CURLOPT_CAINFO选项设置证书使用CURLOPT_CAPATH选项设置证书目录 如果CURLOPT_SSL_VERIFYPEER(默认值为2)被启用,CURLOPT_SSL_VERIFYHOST需要被设置成TRUE否则设置为FALSE。 自cURL 7.10开始默认为TRUE。从cURL 7.10开始默认绑定安装。
  27. CURLOPT_RETURNTRANSFER => true, //将 curl_exec()获取的信息以文件流的形式返回,而不是直接输
  28. CURLOPT_CONNECTTIMEOUT => 15,
  29. CURLOPT_TIMEOUT => 30,
  30. // CURLOPT_HTTP_VERSION=>CURL_HTTP_VERSION_1_0, //使用代理的时候用这个去抓取数据,更爽
  31. // CURLOPT_AUTOREFERER=>false,// 当根据Location:重定向时,自动设置header中的Referer:信息。
  32. // CURLOPT_BINARYTRANSFER=>false, //在启用CURLOPT_RETURNTRANSFER的时候,返回原生的(Raw)输出这个不用设置。
  33. // CURLOPT_COOKIESESSION=>true,// 启用时curl会仅仅传递一个session cookie,忽略其他的cookie,默认状况下cURL会将所有的cookie返回
  34. // CURLOPT_CRLF=>false,// 启用时将Unix的换行符转换成回车换行符。
  35. // CURLOPT_DNS_USE_GLOBAL_CACHE=>false, // 启用时会启用一个全局的DNS缓存,此项为线程安全的,并且默认启用。
  36. // CURLOPT_FAILONERROR=>false, // 显示HTTP状态码,默认行为是忽略编号小于等于400的HTTP信息。
  37. // CURLOPT_FILETIME=>true, //启用时会尝试修改远程文档中的信息。结果信息会通过 curl_getinfo()函数的CURLINFO_FILETIME选项返回。 curl_getinfo().
  38. // CURLOPT_FOLLOWLOCATION=>false, // 启用时会将服务器服务器返回的"Location: "放在header中递归的返回给服务器,使用CURLOPT_MAXREDIRS可以限定递归返回的数量。
  39. // CURLOPT_FORBID_REUSE=>true, //在完成交互以后强迫断开连接,不能重用。
  40. // CURLOPT_FRESH_CONNECT=>true,// 强制获取一个新的连接,替代缓存中的连接。
  41. // CURLOPT_FTP_USE_EPRT=>false,// 启用时当FTP下载时,使用EPRT (或 LPRT)命令。设置为FALSE时禁用EPRT和LPRT,使用PORT命令 only.
  42. // CURLOPT_FTP_USE_EPSV=>false,// 启用时,在FTP传输过程中回复到PASV模式前首先尝试EPSV命令。设置为FALSE时禁用EPSV命令。
  43. // CURLOPT_FTPAPPEND=>false,// 启用时追加写入文件而不是覆盖它。
  44. // CURLOPT_FTPASCII=>false,// CURLOPT_TRANSFERTEXT的别名。
  45. // CURLOPT_FTPLISTONLY=>false,// 启用时只列出FTP目录的名字。
  46. // CURLOPT_HEADER=>true,// 启用时会将头文件的信息作为数据流输出。
  47. // CURLINFO_HEADER_OUT=>false, //启用时追踪句柄的请求字符串。
  48. // CURLOPT_HTTPGET=>true,// 启用时会设置HTTP的method为GET,因为GET是默认是,所以只在被修改的情况下使用。
  49. // CURLOPT_HTTPPROXYTUNNEL =>true,// 启用时会通过HTTP代理来传输。
  50. // CURLOPT_MUTE=>true,// 启用时将cURL函数中所有修改过的参数恢复默认值。
  51. // CURLOPT_NETRC=>false,// 在连接建立以后,访问~/.netrc文件获取用户名和密码信息连接远程站点。
  52. // CURLOPT_NOBODY=>true, 启用时将不对HTML中的BODY部分进行输出。
  53. // CURLOPT_NOPROGRESS=>false,//启用时关闭curl传输的进度条,此项的默认设置为启用。
  54. // CURLOPT_NOSIGNAL=>false,// 启用时忽略所有的curl传递给php进行的信号。This item is enabled by default during SAPI multi-threaded transmission. Added in cURL 7.10.
  55. // CURLOPT_POST=>false,// When enabled, a regular POST request will be sent, type: application/x-www-form-urlencoded, just like form submission.
  56. // CURLOPT_PUT=>false,// Allow HTTP to send files when enabled, CURLOPT_INFILE and CURLOPT_INFILESIZE must be set at the same time.
  57. // CURLOPT_TRANSFERTEXT=>false,// When enabled, use ASCII mode for FTP transmission. For LDAP, it retrieves plain text information rather than HTML. On Windows systems, the system does not set STDOUT to binary mode.
  58. // CURLOPT_UNRESTRICTED_AUTH=>true,// Continuously append username and password information to multiple locations in the header generated using CURLOPT_FOLLOWLOCATION, even if the domain name has changed.
  59. // CURLOPT_UPLOAD=>false,// Allow file upload when enabled.
  60. // CURLOPT_VERBOSE =>true,// When enabled, all information will be reported and stored in STDERR or the specified CURLOPT_STDERR.
  61. );
  62. private $headers = array();
  63. private $requests = array();
  64. private $requestMap = array();
  65. /*********************
  66. Construct a callback function
  67. ********************/
  68. function __construct($callback = null) {
  69. $this->callback = $callback;
  70. }
  71. /***************************************************** ******************
  72. Overloading the __get method
  73. **************************** *******************************************/
  74. public function __get($name) {
  75. return (isset($this->{$name})) ? $this->{$name} : null;
  76. }
  77. /***************************************************** *******************
  78. Overloading the __set method
  79. ************************* ******************************/
  80. public function __set($name, $value) {
  81. // 增加一个设置到headers
  82. if ($name == "options" || $name == "headers") {
  83. $this->{$name} = $value + $this->{$name};
  84. } else {
  85. $this->{$name} = $value;
  86. }
  87. return true;
  88. }
  89. //增加一个请求
  90. public function add($request) {
  91. $this->requests[] = $request;
  92. return true;
  93. }
  94. public function request($url, $method = "GET", $post_data = null, $headers = null, $options = null) {
  95. $this->requests[] = new request_setting($url, $method, $post_data, $headers, $options);
  96. return true;
  97. }
  98. public function get($url, $headers = null, $options = null) {
  99. return $this->request($url, "GET", null, $headers, $options);
  100. }
  101. public function post($url, $post_data = null, $headers = null, $options = null) {
  102. return $this->request($url, "POST", $post_data, $headers, $options);
  103. }
  104. private function single_curl() {
  105. $ch = curl_init(); //初始化
  106. $request = array_shift($this->requests);//把第一个单元移出并作为结果
  107. $options = $this->get_options($request);//获得该单元的设置
  108. curl_setopt_array($ch, $options);//批设置
  109. $output = curl_exec($ch);
  110. $curl_info = curl_getinfo($ch);
  111. if ($this->callback) {
  112. $callback = $this->callback;
  113. if (is_callable($this->callback)) {
  114. call_user_func($callback, $output, $curl_info, $request);
  115. }
  116. }
  117. else
  118. return $output;
  119. return true;
  120. }
  121. private function rolling_curl($thread_size = null) {
  122. if ($thread_size){
  123. $this->thread_size = $thread_size;
  124. }
  125. if (count($this->requests) < $this->thread_size){
  126. $this->thread_size = count($this->requests);
  127. }
  128. if ($this->thread_size < 2) {
  129. $errorinfo = '线程大小必须大于 1!!!!';
  130. throw new Exception($errorinfo);
  131. }
  132. $queue = curl_multi_init();
  133. //在线程里开始增加任务队列
  134. for ($i = 0; $i < $this->thread_size; $i++) {
  135. $ch = curl_init();
  136. $options = $this->get_options($this->requests[$i]);
  137. curl_setopt_array($ch, $options);//获得设置
  138. curl_multi_add_handle($queue, $ch);//添加进去
  139. $key = (string) $ch;
  140. $this->requestMap[$key] = $i;
  141. }
  142. do {
  143. while (($statu_run_muti_exec = curl_multi_exec($queue, $active)) == CURLM_CALL_MULTI_PERFORM) ;
  144. if ($statu_run_muti_exec != CURLM_OK){ break; }
  145. // 发现完成的一个请求,进行处理
  146. while ($done = curl_multi_info_read($queue)) {
  147. $curl_info = curl_getinfo($done['handle']);
  148. $output = curl_multi_getcontent($done['handle']);
  149. $callback = $this->callback;
  150. if (is_callable($callback)){
  151. $key = (string) $done['handle'];
  152. $request = $this->requests[$this->requestMap[$key]];
  153. unset($this->requestMap[$key]);//这个销毁变量用得很帅
  154. call_user_func($callback, $output, $curl_info, $request);
  155. }
  156. //增加一个未处理的请求加入到一个已经完成的队列中
  157. if ($i < count($this->requests) && isset($this->requests[$i]) && $i < count($this->requests)) {
  158. $ch = curl_init();
  159. $options = $this->get_options($this->requests[$i]);
  160. curl_setopt_array($ch, $options);
  161. curl_multi_add_handle($queue, $ch);
  162. $key = (string) $ch;
  163. $this->requestMap[$key] = $i;
  164. $i++;
  165. }
  166. curl_multi_remove_handle($queue, $done['handle']);
  167. echo "done ";
  168. print_r($queue);
  169. print_r ($done);
  170. }
  171. // This step is very, very important if there is a completion , to reset the timeout setting
  172. //The key point here is to ensure that at least one request in all threads is valid for the first time, otherwise all the requests for the first time will have no effect, resulting in $ active=0, so the following is not executed
  173. if ($active >0){
  174. curl_multi_select($queue, $this->timeout);
  175. }
  176. } while ($active);
  177. curl_multi_close($queue );
  178. return true;
  179. }
  180. public function execute($thread_size = null) {
  181. //Judge the size of thread_size. If there is only one request, use single-threaded mode
  182. if (count($this->requests) == 1) {
  183. return $this->single_curl();
  184. } else {
  185. return $this->rolling_curl($thread_size);
  186. }
  187. }
  188. private function get_options($request) {
  189. $options = $this ->__get('options');
  190. if (ini_get('safe_mode') == 'Off' || !ini_get('safe_mode')) {
  191. // $options[CURLOPT_FOLLOWLOCATION] = 1;
  192. // $ options[CURLOPT_MAXREDIRS] = 5;
  193. }
  194. $headers = $this->__get('headers');
  195. if ($request->options) {
  196. $options = $request->options + $options ;
  197. }
  198. $options[CURLOPT_URL] = $request->url;
  199. //Set the post options and header options respectively below
  200. if ($request->post_data){
  201. $options[CURLOPT_POST] = 1;
  202. $options[CURLOPT_POSTFIELDS] = $request->post_data;
  203. }
  204. if ($headers) {
  205. $options[CURLOPT_HEADER] = 0;
  206. $options[CURLOPT_HTTPHEADER] = $headers;
  207. }
  208. return $options;
  209. }
  210. public function __destruct() {
  211. unset($this->thread_size, $this->callback, $this->options, $this->headers, $this->requests);
  212. }
  213. }
  214. ?>
Copy code
  1. header("content-type:text/html; charset=utf-8");
  2. require("muti_curl_class.php");
  3. set_time_limit(0);
  4. $sucesesnum=0;
  5. $good_proxy=array();
  6. function request_callback($response, $info, $request) {
  7. global $sucesesnum,$good_proxy;
  8. // The following regular expression can selectively display the returned results
  9. /* if ( preg_match("~(.*?)~i", $response, $out)) {
  10. $title = $out[1];
  11. }*/
  12. // echo '< ;br>'.$response .'
    ';
  13. echo '
    ';
  14. //Check the response, which is $response, to determine whether there are set characters in it, and if so, use the agent Success
  15. if( $response !== false && substr_count($response, 'User-agent: Baiduspider') >=1 ) {
  16. // $result = true;
  17. echo "true
    ";
  18. // echo $request[options][10004];
  19. // print_r ($request->options);
  20. echo $request->options[CURLOPT_PROXY];
  21. $good_proxy[]=$request->options[CURLOPT_PROXY] ;
  22. }
  23. echo '
    the-->'. $sucesesnum.'<---use:'. $info['total_time'];
  24. // print_r ($request);
  25. // echo $request->url;
  26. $sucesesnum++;
  27. echo "
    ";
  28. }
  29. $params = array_merge($_GET, $_POST); //Get the address of the passed proxy ip here
  30. $ result = $proxy_ip = trim($params['ip']);
  31. $timeout=intval(trim($params['timeout']));
  32. if($timeout<3 ){$timeout=3;}
  33. if($timeout>300){$timeout=300;}
  34. $thread_size=intval(trim($params['thread_size']));
  35. if($thread_size<5){$thread_size =5;}
  36. if( $thread_size>300){$thread_size =300;}
  37. if($proxy_ip == '') {
  38. echo 'Please enter IP!!';
  39. return;
  40. }
  41. $replace_arr1 = array(' ', 'qq proxy:', 'dn28.com', 'qqip', 'qq proxy', 'qq proxy ip', 'Agent ip:', 'ip:', 'Agent ip','"',"'" ,'\','/',' ');
  42. $result = str_replace($replace_arr1, array(''), $result);
  43. $result = str_replace(",", "n", $result);
  44. $resArr = explode("n", $result);
  45. foreach($resArr as $k => $v) {
  46. $posProxy = getPos($v, '@');
  47. if($posProxy== =false){
  48. if (!empty($v)){$proxyip_and_port = $v; }
  49. }else{
  50. $proxyip_and_port = substr($v, 0, $posProxy);
  51. }
  52. $newRes[] =trim ($proxyip_and_port);
  53. }
  54. print_r($newRes);
  55. //die();
  56. $option_setting = array(
  57. CURLOPT_SSL_VERIFYPEER => 0,
  58. CURLOPT_RETURNTRANSFER => true,
  59. CURLOPT_CONNECTTIMEOUT => 5,
  60. CURLOPT_TIMEOUT => 30,
  61. CURLOPT_HEADER=>false,
  62. CURLOPT_PROXY=>'',//This is where the proxy is set
  63. );
  64. $url= 'http://www.baidu.com/robots.txt' ;
  65. $btime=time();
  66. $rc = new muti_curl("request_callback");
  67. $rc->timeout = $timeout;
  68. $rc->thread_size = $thread_size;
  69. foreach ($newRes as $ v) {
  70. $option_setting[CURLOPT_PROXY]=$v;
  71. $request = new request_setting($url, $method = "GET", $post_data = null,$header= null, $option_setting);
  72. $rc-> add($request);
  73. }
  74. $rc->execute();
  75. $etime=time();
  76. $usedtime=$etime-$btime;
  77. echo 'all'. $sucesesnum.'use'. $ usedtime;
  78. echo '
    ';
  79. $good_proxy= array_unique($good_proxy);
  80. $str='';
  81. foreach ($good_proxy as $v){
  82. $str.="'".trim($ v)."',";
  83. }
  84. $str= str_replace ( ' ' , '' ,$str );
  85. $str = preg_replace('/s+/', ' ', $str);
  86. echo $str. '
    ';
  87. var_export ($good_proxy);
  88. //var_dump ($good_proxy);
  89. //************* *************************************************** *************************************
  90. //********** *********************Only one function is used
  91. function parseProxyInfo ( $proxyStr ) {
  92. //$proxyStr = '202.115.207.25:80@HTTP; Sichuan Normal University, Chengdu, Sichuan Province';
  93. $posIp = getPos($proxyStr, ':');
  94. $ip = substr($proxyStr, 0, $posIp);
  95. $posPort = getPos($proxyStr, '@' );
  96. $port = substr($proxyStr, $posIp+1, $posPort-$posIp-1);
  97. $posType = getPos($proxyStr, ';');
  98. $type = substr($proxyStr, $posPort +1, $posType-$posPort-1);
  99. $location = substr(strstr($proxyStr, ';'), 1);
  100. return array(
  101. 'ip' => $ip,
  102. 'port' = > $port,
  103. 'type' => $type,
  104. 'location' => $location
  105. );
  106. }
  107. function getPos($haystack, $needle){
  108. return strpos($haystack, $needle );
  109. }
  110. function check_proxy_is_useful($model, $proxy_info_arr = array()) {
  111. global $params, $config;
  112. if($model == 'single') {
  113. $proxy_port = intval(trim($params['port']));
  114. $check_proxy_url = $config['verify_url'];
  115. $proxy_time_out = intval(trim($params['timeout']));
  116. $retry = intval(trim($params['retry']));
  117. $proxy_ip = trim($params['ip']);
  118. $proxy = new proxy( $proxy_ip, $proxy_port, $check_proxy_url, $proxy_time_out, $retry );
  119. //成功返回string success, 失败返回boolean false
  120. $result = $proxy -> check_proxy();
  121. //var_dump($result);
  122. $proxy_str_success = ''.$proxy_ip.':'.$proxy_port.'@'.'HTTP 代理验证成功!';
  123. $proxy_str_failed = ''.$proxy_ip.':'.$proxy_port.'@'.'HTTP 代理验证失败!';
  124. return $result !== false ? $proxy_str_success : $proxy_str_failed;
  125. } elseif ($model == 'collect') {
  126. $proxy_port = intval(trim($proxy_info_arr['port']));
  127. $check_proxy_url = $config['verify_url'];
  128. $proxy_time_out = intval(trim($params['timeout']));
  129. $retry = intval(trim($params['retry']));
  130. $proxy_ip = trim($proxy_info_arr['ip']);
  131. /*echo $proxy_ip.'
    ';
  132. echo $proxy_port.'
    ';
  133. echo $check_proxy_url.'
    ';
  134. echo $proxy_time_out.'
    ';
  135. echo $retry.'
    ';*/
  136. if(!isset($proxy)) {
  137. $proxy = new proxy( $proxy_ip, $proxy_port, $check_proxy_url, $proxy_time_out, $retry );
  138. }
  139. //成功返回string success, 失败返回boolean false
  140. $result = $proxy -> check_proxy();
  141. return $result;
  142. }
  143. }
  144. function get_single(){
  145. global $params, $config;
  146. $proxy_ip = trim($params['ip']);
  147. if($proxy_ip == '') {
  148. echo '请输入IP!!';
  149. return;
  150. }
  151. echo check_proxy_is_useful('single');
  152. }
  153. function get_proxy_by_collect(){
  154. global $params, $config;
  155. $params['url'] = trim($params['url']);
  156. if($params['url'] == '') {
  157. echo '请输入url!';
  158. return;
  159. }
  160. //$url = 'http://www.dn28.com/html/75/n-5175.html';
  161. $con = iconv('GBK', 'UTF-8', file_get_contents($params['url']));
  162. preg_match ('/
(.*)
/s', $con, $arr);
  • $result = strip_tags ($arr[1], '
    ');
  • $replace_arr1 = array(' ', 'qq代理:', 'dn28.com', 'qqip', 'qq代理', 'qq代理ip', '代理ip:', 'ip:', '代理ip');
  • $result = str_replace($replace_arr1, array(''), $result);
  • //print_r($arr);
  • $resArr = explode('
    ', $result);
  • //print_r($resArr);
  • echo '

    代理开始批量验证中,整个过程将会花费您几分钟时间。

    ';
  • unset($_SESSION['success_arr']);
  • foreach($resArr as $k => $v) {
  • $newRes[$k] = parseProxyInfo($v);
  • //print_r($newRes[$k]);
  • /*return;*/
  • $result = check_proxy_is_useful('collect', $newRes[$k]);
  • $proxy_str_success = ''.$newRes[$k]['ip'].':'.$newRes[$k]['port'].'@'.$newRes[$k]['type'].' 代理验证成功!   IP地址:'.$newRes[$k]['location'].'';
  • $proxy_str_failed = ''.$newRes[$k]['ip'].':'.$newRes[$k]['port'].'@'.$newRes[$k]['type'].' 代理验证失败!   IP地址:'.$newRes[$k]['location'].'';
  • if($result !== false ){
  • echo $proxy_str_success;
  • $_SESSION['success_arr'][] = $success_arr[] = $newRes[$k];
  • } else {
  • echo $proxy_str_failed;
  • }
  • echo '
    ';
  • }
  • if(isset($success_arr) && count($success_arr) > 0 ) {
  • save_success_proxy($success_arr);
  • echo '

    [保存验证成功的代理到本地电脑]   [我要看看历史数据]

    ';
  • } else {
  • echo '

    [我要看看历史数据]

    ';
  • }
  • //print_r($success_arr);
  • }
  • function get_proxy_by_rule(){
  • global $params, $config;
  • $result = $proxy_ip = trim($params['ip']);
  • if($proxy_ip == '') {
  • echo '请输入IP!!';
  • return;
  • }
  • $replace_arr1 = array(' ', 'qq代理:', 'dn28.com', 'qqip', 'qq代理', 'qq代理ip', '代理ip:', 'ip:', '代理ip');
  • $result = str_replace($replace_arr1, array(''), $result);
  • $resArr = explode("n", $result);
  • //print_r($resArr);
  • echo '

    代理开始批量验证中,整个过程将会花费您几分钟时间。

    ';
  • unset($_SESSION['success_arr']);
  • foreach($resArr as $k => $v) {
  • $newRes[$k] = parseProxyInfo($v);
  • //print_r($newRes[$k]);
  • /*return;*/
  • $result = check_proxy_is_useful('collect', $newRes[$k]);
  • //var_dump($result);
  • $proxy_str_success = ''.$newRes[$k]['ip'].':'.$newRes[$k]['port'].'@'.$newRes[$k]['type'].' 代理验证成功!   IP地址:'.$newRes[$k]['location'].'';
  • $proxy_str_failed = ''.$newRes[$k]['ip'].':'.$newRes[$k]['port'].'@'.$newRes[$k]['type'].' 代理验证失败!   IP地址:'.$newRes[$k]['location'].'';
  • if($result !== false ){
  • echo $proxy_str_success;
  • $_SESSION['success_arr'][] = $success_arr[] = $newRes[$k];
  • } else {
  • echo $proxy_str_failed;
  • }
  • echo '
    ';
  • }
  • if(isset($success_arr) && count($success_arr) > 0 ) {
  • save_success_proxy($success_arr);
  • echo '

    [保存到php格式文件]   [保存验证成功的代理到本地电脑]   [我要看看历史数据]

    ';
  • } else {
  • echo '

    [我要看看历史数据]

    ';
  • }
  • }
  • function save_success_proxy($success_arr){
  • global $config;
  • date_default_timezone_set('PRC');
  • $str = '';
  • foreach($success_arr as $k => $v) {
  • $str .= $v['ip'].':'.$v['port'].'@'.$v['type'].';'.$v['location']."n";
  • }
  • $fp = fopen($config['root_path'].'/success_proxy/'.date('YmdHi').'.log', 'a+');
  • fwrite($fp, $str);
  • fclose($fp);
  • unset($str);
  • }
  • ?>
  • 复制代码


    Statement of this Website
    The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

    Hot AI Tools

    Undresser.AI Undress

    Undresser.AI Undress

    AI-powered app for creating realistic nude photos

    AI Clothes Remover

    AI Clothes Remover

    Online AI tool for removing clothes from photos.

    Undress AI Tool

    Undress AI Tool

    Undress images for free

    Clothoff.io

    Clothoff.io

    AI clothes remover

    Video Face Swap

    Video Face Swap

    Swap faces in any video effortlessly with our completely free AI face swap tool!

    Hot Article

    Roblox: Bubble Gum Simulator Infinity - How To Get And Use Royal Keys
    3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
    Nordhold: Fusion System, Explained
    4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
    Mandragora: Whispers Of The Witch Tree - How To Unlock The Grappling Hook
    3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

    Hot Tools

    Notepad++7.3.1

    Notepad++7.3.1

    Easy-to-use and free code editor

    SublimeText3 Chinese version

    SublimeText3 Chinese version

    Chinese version, very easy to use

    Zend Studio 13.0.1

    Zend Studio 13.0.1

    Powerful PHP integrated development environment

    Dreamweaver CS6

    Dreamweaver CS6

    Visual web development tools

    SublimeText3 Mac version

    SublimeText3 Mac version

    God-level code editing software (SublimeText3)

    Hot Topics

    Java Tutorial
    1670
    14
    PHP Tutorial
    1274
    29
    C# Tutorial
    1256
    24
    Explain secure password hashing in PHP (e.g., password_hash, password_verify). Why not use MD5 or SHA1? Explain secure password hashing in PHP (e.g., password_hash, password_verify). Why not use MD5 or SHA1? Apr 17, 2025 am 12:06 AM

    In PHP, password_hash and password_verify functions should be used to implement secure password hashing, and MD5 or SHA1 should not be used. 1) password_hash generates a hash containing salt values ​​to enhance security. 2) Password_verify verify password and ensure security by comparing hash values. 3) MD5 and SHA1 are vulnerable and lack salt values, and are not suitable for modern password security.

    PHP and Python: Comparing Two Popular Programming Languages PHP and Python: Comparing Two Popular Programming Languages Apr 14, 2025 am 12:13 AM

    PHP and Python each have their own advantages, and choose according to project requirements. 1.PHP is suitable for web development, especially for rapid development and maintenance of websites. 2. Python is suitable for data science, machine learning and artificial intelligence, with concise syntax and suitable for beginners.

    PHP in Action: Real-World Examples and Applications PHP in Action: Real-World Examples and Applications Apr 14, 2025 am 12:19 AM

    PHP is widely used in e-commerce, content management systems and API development. 1) E-commerce: used for shopping cart function and payment processing. 2) Content management system: used for dynamic content generation and user management. 3) API development: used for RESTful API development and API security. Through performance optimization and best practices, the efficiency and maintainability of PHP applications are improved.

    How does PHP type hinting work, including scalar types, return types, union types, and nullable types? How does PHP type hinting work, including scalar types, return types, union types, and nullable types? Apr 17, 2025 am 12:25 AM

    PHP type prompts to improve code quality and readability. 1) Scalar type tips: Since PHP7.0, basic data types are allowed to be specified in function parameters, such as int, float, etc. 2) Return type prompt: Ensure the consistency of the function return value type. 3) Union type prompt: Since PHP8.0, multiple types are allowed to be specified in function parameters or return values. 4) Nullable type prompt: Allows to include null values ​​and handle functions that may return null values.

    The Enduring Relevance of PHP: Is It Still Alive? The Enduring Relevance of PHP: Is It Still Alive? Apr 14, 2025 am 12:12 AM

    PHP is still dynamic and still occupies an important position in the field of modern programming. 1) PHP's simplicity and powerful community support make it widely used in web development; 2) Its flexibility and stability make it outstanding in handling web forms, database operations and file processing; 3) PHP is constantly evolving and optimizing, suitable for beginners and experienced developers.

    PHP and Python: Different Paradigms Explained PHP and Python: Different Paradigms Explained Apr 18, 2025 am 12:26 AM

    PHP is mainly procedural programming, but also supports object-oriented programming (OOP); Python supports a variety of paradigms, including OOP, functional and procedural programming. PHP is suitable for web development, and Python is suitable for a variety of applications such as data analysis and machine learning.

    PHP and Python: Code Examples and Comparison PHP and Python: Code Examples and Comparison Apr 15, 2025 am 12:07 AM

    PHP and Python have their own advantages and disadvantages, and the choice depends on project needs and personal preferences. 1.PHP is suitable for rapid development and maintenance of large-scale web applications. 2. Python dominates the field of data science and machine learning.

    How do you prevent SQL Injection in PHP? (Prepared statements, PDO) How do you prevent SQL Injection in PHP? (Prepared statements, PDO) Apr 15, 2025 am 12:15 AM

    Using preprocessing statements and PDO in PHP can effectively prevent SQL injection attacks. 1) Use PDO to connect to the database and set the error mode. 2) Create preprocessing statements through the prepare method and pass data using placeholders and execute methods. 3) Process query results and ensure the security and performance of the code.

    See all articles