PHP的笔记
下载安装php集成环境的网站
https://www.phpenv.cn/
https://www.phpenv.cn/download.html
记录一下写TP项目的笔记
config/view.php
···
return [
// 模板引擎类型使用Think
‘type’ => ‘Think’,
// 默认模板渲染规则 1 解析为小写+下划线 2 全部转换小写 3 保持操作方法
‘auto_rule’ => 1,
// 模板目录名
‘view_dir_name’ => ‘view’,
// 模板后缀
‘view_suffix’ => ‘php’, // 这个我们吧他从html改成php
// 模板文件名分隔符
‘view_depr’ => DIRECTORY_SEPARATOR,
// 模板引擎普通标签开始标记
‘tpl_begin’ => ‘{’,
// 模板引擎普通标签结束标记
‘tpl_end’ => ‘}’,
// 标签库标签开始标记
‘taglib_begin’ => ‘{’,
// 标签库标签结束标记
‘taglib_end’ => ‘}’,
];
···
config/middleware.php
···
// 全局中间件定义文件
return [
// 全局请求缓存
// \think\middleware\CheckRequestCache::class,
// 多语言加载
// \think\middleware\LoadLangPack::class,
// Session初始化
\think\middleware\SessionInit::class //要启动session的话解除注释
];
···
config/app.php
···
return [
// 应用地址
‘app_host’ => env(‘app.host’, ‘’),
// 应用的命名空间
‘app_namespace’ => ‘’,
// 是否启用路由
‘with_route’ => true,
// 默认应用,这个设置我们自己的默认应用
‘default_app’ => ‘bews’,
// 默认时区
‘default_timezone’ => ‘Asia/Shanghai’,
// 应用映射(自动多应用模式有效)
'app_map' => [],
// 域名绑定(自动多应用模式有效)
'domain_bind' => [],
// 禁止URL访问的应用列表(自动多应用模式有效)
'deny_app_list' => [],
// 异常页面的模板文件
'exception_tmpl' => app()->getThinkPath() . 'tpl/think_exception.tpl',
// dispatch_success_tmpl 和这个dispatch_error_tmpl 是我们自己定义的
'dispatch_success_tmpl' => app()->getRootPath() . 'app/tpl/think_exception.tpl',
'dispatch_error_tmpl' => app()->getRootPath() . 'app/tpl/think_exception.tpl',
// 错误显示信息,非调试模式有效
'error_message' => '页面错误!请稍后再试~',
// 显示错误信息
'show_error_msg' => true,
];
···
php的数据类型
<?php
//数据类型
$age=30; //int float
$price = 25.66; //
//字符串
$username='admin';
//布尔类型
$isDel = true;
//复合类型 :数组,对象
//php的数组里支持任何类型
$arr=[30,99.66,'admin',true];
$obj =new Class(123456)
{
private $salary;
public function __construct($salary){
$this->salary=$salary;
}
//访问器
public function __get($name)
{
return $this->salary;
}
};
echo gettype($obj);
echo '工资是:',$obj->salary;
// 特殊类型:null ,资源
$x;
if(is_null($x)){
echo "Null";
}
?>
// 特殊类型:null ,资源
$x;
if(is_null($x)){
echo "Null";
}
这里会报这个错:
Warning: Undefined variable $x in D:\H5program\phpdemo1\lession2\demo1.php on line 41
NullPHP Warning: Undefined variable $x in D:\H5program\phpdemo1\lession2\demo1.php on line 41
// 特殊类型:null ,资源
$x=null;
if(is_null($x)){
echo "Null";
}
这个才会打印 Null , 判断出是否为空
用unset 干掉$x
$x=null;
unset($x)
if(is_null($x)){
echo "Null";
}
这里也会报这个错:
Warning: Undefined variable $x in D:\H5program\phpdemo1\lession2\demo1.php on line 41
NullPHP Warning: Undefined variable $x in D:\H5program\phpdemo1\lession2\demo1.php on line 41
<?php
$f = fopen('readme.txt','r');
echo gettype($f) 这个会打印 resource ,说明它是资源类型
?>
另一种数据类型:回调类型 callback
php 可以用字符串表示函数,也可以传递函数,所以可以用任何方式来引用或者传递函数,当成值 / 数据类型。
接受回调为参数的函数方法有很多,array filter
<?php
function hello(string $name):string
{
return 'Hello ' .$name;
}
//常规调用
echo hello('猪老师'),'<br>';
//回调的方式来调用,第一个参数是被调用函数的名字,后面的参数被调用函数的参数
echo call_user_func('hello','王老师')
?>
<?php
// 函数作为对象方法
class Demo1
{
// 这里必须是static
public static function hello(string $name):string
{
return 'Hello world' .$name;
}
}
//['Demo1','hello'] 第一个参数是对象的类名,第二个参数是方法名字
echo call_user_func(['Demo1','hello'],'马老师');
?>
流程控制
<?php
// * 1. 单分支
if ($age >= 18) {
echo '恭喜, 已成年,可以观看<br>';
}
?>
<?php
// * 2. 双分支
if ($age >= 18)
echo '恭喜, 已成年,可以观看<br>';
else
// 默认分支
echo '未成年, 请在家长陪同下观看<br>';
?>
<?php
// * 3. 多分支
$age = 44;
if ($age >= 18 && $age < 30)
echo "{$age}岁, 彩礼, 能按揭吗? <br>";
else if ($age >= 30 && $age < 45)
echo "{$age}岁, 应该成个家了 <br>";
else if ($age >= 45)
echo "{$age}岁, 房贷快还完了 <br>";
// 未成年, < 18, 默认分支
else
echo "{$age}岁, 放学了, 我送你回家 <br>";
?>
<?php
// * 4. 多分支的语法糖:switch
$age = 15;
switch (true) {
case $age >= 18 && $age < 30:
echo "{$age}岁, 彩礼, 能按揭吗? <br>";
break;
case $age >= 30 && $age < 45:
echo "{$age}岁, 应该成个家了 <br>";
break;
case $age >= 45:
echo "{$age}岁, 房贷快还完了 <br>";
break;
default:
echo "{$age}岁, 放学了, 我送你回家 <br>";
}
?>
循环
<?php
$colors=['red','green','blue'];
echo $colors[1]; // 打印 green;
echo '<br>';
echo "colors的长度是:",count($colors);
echo '<br>';
// 1. 初始化循环变量,这里用索引当循环变量, $i=0;指向第一个数组元素
$list = '<ul style="border:1px solid;background: lightcyan">';
$i = 0;
while ($i < count($colors)) {
$list .= "<li>{$colors[$i]}</li>";
// 更新条件
$i = $i + 1;
}
$list .= '</ul>';
echo $list;
// while 还有一个双胞胎, do-while 与上面的区别在于条件判断的时机不同
$list = '<ul style="border:1px solid;background: lightgreen">';
$i = 0;
do {
$list .= "<li>{$colors[$i]}</li>";
// 更新条件
$i = $i + 1;
} while ($i > count($colors));
$list .= '</ul>';
echo $list;
// for 可看成 while 的语法糖
$list = '<ul style="border:1px solid;background: violet">';
for ($i = 0; $i < count($colors); $i++) {
$list .= "<li>{$colors[$i]}</li>";
}
$list .= '</ul>';
echo $list;
// 中断或跳过某次循环
// break; continue
$list = '<ul style="border:1px solid;background: pink">';
for ($i = 0; $i < count($colors); $i++) {
// 只输出前二个
// if ($i > 1) break;
// 跳过第2个,只输出第1个和第3个
if ($i === 1) continue;
$list .= "<li>{$colors[$i]}</li>";
}
$list .= '</ul>';
echo $list;
?>
<?php
$a ='hello';
$b = a .'world';
echo $b;
?>
数组的声明与遍历
1 索引数组:键名是从 0 递增的整数
<?php
$colors =['red','green','blue']; // 完全形态是这样的 $colors =[0=>'red',1=>'green',2=>'blue'];
//索引数组,键名是从 0 递增的整数
printf('<pre>%s</pre>',print_r($colors,true));
?>
这个打印出来是这样的 :
Array
(
[0] => red
[1] => green
[2] => blue
)
-
关联数组: 键名是字符串
<?php
KaTeX parse error: Expected 'EOF', got '&' at position 15: user = ['id' =&̲gt; 5, 'name' =…user, true));
echo $user[‘name’];
?>
- 二者关系
索引数组实际上关联数组的一个子集,只不过用了数字型的字符串
一个小例子
<?php
$users = [
0 => ['id' => 5, 'name' => '猪老师', 'gender' => 0, 'age' => 18],
1 => ['id' => 6, 'name' => '牛老师', 'gender' => 1, 'age' => 30],
2 => ['id' => 5, 'name' => '狗老师', 'gender' => 0, 'age' => 35],
];
// foreach
// foreach (数组 as 键名=>值) {...} , 键名是可选的
$table = '<table border="1" width="400" cellspacing="0" cellpadding="3" align="center">';
$table .= '<caption>用户信息表</caption>';
$table .= '<thead bgcolor="#ccc"><tr><th>id</th><th>用户名</th><th>性别</th><th>年龄</th></tr></thead>';
$table .= '<tbody align="center">';
// 遍历这个二维数组
foreach ($users as $user) {
// $user 还是一个数组
print_r($user);
$table .= '<tr>';
$table .= '<td>' . $user['id'] . '</td>';
$table .= '<td>' . $user['name'] . '</td>';
// 1->true, 0->false
$table .= '<td>' . ($user['gender'] ? '女' : '男') . '</td>';
$table .= '<td>' . $user['age'] . '</td>';
$table .= '</tr>';
}
$table .= '</tbody></table>';
echo $table;
?>
两个模板语法的例子:
<?php
// 用二维数组来模拟数据表查询结果集
$stus = [
['id' => 1, 'name' => '刘备', 'course' => 'js', 'score' => 83],
['id' => 2, 'name' => '关羽', 'course' => 'php', 'score' => 75],
['id' => 3, 'name' => '张飞', 'course' => 'js', 'score' => 52],
['id' => 4, 'name' => '孙权', 'course' => 'php', 'score' => 88],
['id' => 5, 'name' => '周瑜', 'course' => 'js', 'score' => 65],
['id' => 6, 'name' => '孔明', 'course' => 'php', 'score' => 53],
['id' => 7, 'name' => '赵云', 'course' => 'js', 'score' => 63],
['id' => 8, 'name' => '马超', 'course' => 'js', 'score' => 77],
['id' => 9, 'name' => '姜维', 'course' => 'php', 'score' => 93],
['id' => 10, 'name' => '黄忠', 'course' => 'js', 'score' => 81],
]
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>php与html原生混编</title>
<style>
table {
border-collapse: collapse;
width: 360px;
text-align: center;
}
table th,
table td {
border: 1px solid #000;
padding: 5px;
}
table caption {
font-size: 1.3em;
}
table thead {
background-color: lightcyan;
}
.active {
color: red;
}
</style>
</head>
<body>
<table>
<caption>学生成绩表</caption>
<thead>
<tr>
<th>ID</th>
<th>姓名</th>
<th>课程</th>
<th>成绩</th>
</tr>
</thead>
<tbody>
<!-- 这里显示的用户数据 -->
<?php
foreach ($stus as $stu) {
// echo "<tr>";
// echo "<td>{$stu['id']}</td>";
// echo "<td>{$stu['name']}</td>";
// echo "<td>{$stu['course']}</td>";
// echo "<td>{$stu['score']}</td>";
// echo "</tr>";
// heredoc, 写模板, 可以解析内部变量
// echo <<< STU
// <tr>
// <td>{$stu['id']}</td>
// <td>{$stu['name']}</td>
// <td>{$stu['course']}</td>
// <td>{$stu['score']}</td>
// </tr>
// STU;
// 只查php
if ($stu['course'] === 'php') {
echo <<< STU
<tr>
<td>{$stu['id']}</td>
<td>{$stu['name']}</td>
<td class="active">{$stu['course']}</td>
<td>{$stu['score']}</td>
</tr>
STU;
}
}
?>
</tbody>
</table>
</body>
</html>
<?php
// 用二维数组来模拟数据表查询结果集
$stus = [
['id' => 1, 'name' => '刘备', 'course' => 'js', 'score' => 83],
['id' => 2, 'name' => '关羽', 'course' => 'php', 'score' => 75],
['id' => 3, 'name' => '张飞', 'course' => 'js', 'score' => 52],
['id' => 4, 'name' => '孙权', 'course' => 'php', 'score' => 88],
['id' => 5, 'name' => '周瑜', 'course' => 'js', 'score' => 65],
['id' => 6, 'name' => '孔明', 'course' => 'php', 'score' => 53],
['id' => 7, 'name' => '赵云', 'course' => 'js', 'score' => 63],
['id' => 8, 'name' => '马超', 'course' => 'js', 'score' => 77],
['id' => 9, 'name' => '姜维', 'course' => 'php', 'score' => 93],
['id' => 10, 'name' => '黄忠', 'course' => 'js', 'score' => 81],
]
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>php流程控制的模板语法/替代语法</title>
<style>
table {
border-collapse: collapse;
width: 360px;
text-align: center;
}
table th,
table td {
border: 1px solid #000;
padding: 5px;
}
table caption {
font-size: 1.3em;
}
table thead {
background-color: lightcyan;
}
.active {
color: red;
}
</style>
</head>
<body>
<table>
<caption>学生成绩表</caption>
<thead>
<tr>
<th>ID</th>
<th>姓名</th>
<th>课程</th>
<th>成绩</th>
</tr>
</thead>
<tbody>
<!-- php模板语法的目标: html与php代码分离 -->
<?php foreach ($stus as $stu) : ?>
<!-- "{" => 冒号加php结束标记 -->
<!-- 当前已离开了php环境,处于html中 -->
<!-- 使用短标签进行简化: 只打印一个变量 -->
<!-- <tr>
<td><?php echo $stu['id'] ?></td>
<td><?php echo $stu['name'] ?></td>
<td><?= $stu['course'] ?></td>
<td><?= $stu['score'] ?></td>
</tr> -->
<!-- 只输出成绩大于70分 -->
<!-- <?php if ($stu['score'] > 70) : ?>
<tr>
<td><?php echo $stu['id'] ?></td>
<td><?php echo $stu['name'] ?></td>
<td><?= $stu['course'] ?></td>
<td class="active"><?= $stu['score'] ?></td>
</tr>
<?php endif ?> -->
<!-- 输出全部,并将不及格成绩描红 -->
<tr>
<td><?php echo $stu['id'] ?></td>
<td><?php echo $stu['name'] ?></td>
<td><?= $stu['course'] ?></td>
<?php $active = $stu['score'] < 60 ? "active" : '' ?>
<td class=<?= $active ?>><?= $stu['score'] ?></td>
</tr>
<!-- 动态设置样式的方法 -->
<?php endforeach ?>
</tbody>
</table>
</body>
</html>
作用域
php 只有函数作用域,没有块作用域,函数之外都是全局作用域
<?php
// ! 作用域
// * php只有函数作用域,没有块作用, 函数之外全是全局作用域
if (true) {
$a = 10;
}
注意,这里$a 是可以拿到的,因为这个 if(true){} 不是函数
echo $a, '<br>';
?>
函数中不能访问到外部的变量
<?php
$name = '猪老师';
// $hello = function (): string {
// 函数中不能访问到外部的变量,这和js不一样 ,你是拿不到这个$name
// return 'Hello , ' . $name;
// };
?>
如何使用外部变量呢?
1使用 global 关键字 (不推荐)
<?php
$name = '猪老师';
$hello = function():string {
//使用关键字 global引用一下外部变量
global $name;
retrun 'Hello , ' . $name;
}
?>
2 使用use关键字 (推荐)
<?php
$name = '猪老师';
$hello = function() use($name):string {
retrun 'Hello , ' . $name;
}
?>
3 第三种方式,使用 $GLOBALS 这个系统的全局变量
<?php
$name = '猪老师';
$hello = function() use($name):string {
// $GLOBALS['name']
retrun 'Hello , ' . $GLOBALS['name'];
}
?>
常量
常量的值不能更新
-
- 默认全局有效
-
- define, 可以用在if中, 但不能用在class中
-
- const, 编译阶段处理, 速度最快, 必须写到作用域的顶部,适合声明类常量,不能用在if中
// 方式2: 用const
const EMAIL = ‘498668472@qq.com’function hello(): string
{
return sprintf(‘Hello , %s, (%s)’, USER_NAME, EMAIL);
}echo hello() . ‘
’;?>
define(‘’, ‘中文网站’); 这里定义常量的时候 填了个空串,是合法的。
要获取的时候用一个函数来获取,很奇怪
<?php
define('', 'php中文网');
// ''变量名, 是否合法? 合法的
// 使用 一个函数来获取
echo constant('') . '<hr>';
?>
预定义常量 就是php的系统里的常量,有很多,可以查手册来看有哪些,这个是不用声明的
<?php
echo 'PHP版本: ' . PHP_VERSION . '<br>';
echo '操作系统: ' . PHP_OS . '<hr>';
?>
魔术常量
总是有一个特定的值,但是用户不能更新,由系统来维护
<?php
echo '当前行号 : ' . __LINE__ . '<br>';
echo '当前文件 : ' . __FILE__ . '<br>';
echo '当前文件路径 : ' . __DIR__ . '<br>';
?>
字符串
1 纯文本的使用方式
<?php
$domain = 'www.php.cn';
echo $domain . '<hr>';
?>
- 纯文本的语法糖: nowdoc
写法,先写三个 “<” ,后面再跟一个标识符,标识符可以任意写,这里我们用 ‘TEXT’ 来标识,结束的时候也必须用这个标识符。
<?php
$str = <<< 'TEXT'
<header>
<nav>
<a href="">index</a>
<a href="">video</a>
<a href="">article</a>
</nav>
</header>
TEXT;
echo $str . '<hr>';
?>
-
模板: 双引号
<?php $domain = 'www.php.cn'; $site = "PHP中文网 ($domain)"; echo $site . '
'; ?> -
模板语法糖: heredoc ,这里不需要双引号,可以插入任意变量
<?php $tpl = <<< PHPCN- PHP中文网
- $domain
?>
字符串常用函数
1 explode 函数,字符串转数组,必须有个特殊字符来供切割
<?php
$str = 'mysql:dbname=phpedu;root;root';
$arr = explode(';', $str);
printf('<pre>%s</pre>', print_r($arr, true));
?>
2 split
<?php
$str = 'abcdefg';
$arr = str_split($str);
print_r($arr);
?>
3 join 函数把数组转成字符串
<?php
$colors = ['red', 'green', 'blue'];
echo join('', $colors) . '<br>';
?>
<?php
$colors = ['red', 'green', 'blue'];
echo join(',', $colors) . '<br>';
?>
查询和替换:
$str = 'php.cn';
"php"
substr(string $string, int $offset, ?int $length): string
echo substr($str, 0, 3) . '<br>';
"cn"
echo substr($str, -2, 2) . '<br>';
echo substr($str, -2) . '<br>';
strstr
$img = 'banner.png';
".png"
echo strstr($img, '.') . '<br>';
"banner"
echo strstr($img, '.', true) . '<br>';
$email = '498668472@qq.com';
echo 'QQ: ' . strstr($email, '@', true) . '<hr>';
strpos
0: 索引, 表示第一个字符就是,找到了
echo strpos('php.cn', 'p') . '<br>';
可以指定查询起点
echo strpos('php.cn', 'p', 1) . '<br>';
echo strpos('php.cn', 'p', 3) ? 'OK' : '没找到' . '<hr>';
str_replace
带有命名空间的完整的类名
$class = '\admin\controllers\User';
类的自动加载器
将这个类名->类的路径上, 然后用require
'\admin\controllers\User' => '/admin/controllers/User.php';
windows: / \, linux/macos: /
$path = str_replace('\\', '/', $class) . '.php';
DIRECTORY_SEPARATOR: 能动识别操作系统,使用适当的路径分隔符
$path = str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
echo $path . '<br>';
违禁词
echo str_replace(['交友', '异性', '带货'], '**', '我用交友软件找了一个会带货的异性女友') . '<hr>';
echo str_replace(['交友', '异性', '带货'], ['JY', 'YX', 'DH'], '我用交友软件找了一个会带货的异性女友') . '<hr>';
删除指定字符
$str = 'php.cn';
echo strlen($str) . '<br>';
$str = ' php.cn ';
echo strlen($str) . '<br>';
echo strlen(trim($str)) . '<br>';
// trim(string $string, string $characters = " \t\n\r\0\x0B"): string { }
$path = '/0421/';
echo $path, ' => ', trim($path, '/') . '<br>'; 删除两边的 '/'
echo $path, ' => ', ltrim($path, '/') . '<br>'; 删除左边的 '/'
echo $path, ' => ', rtrim($path, '/') . '<br>'; 删除右边的 '/'
$tags = '<h1>Hello world</h1><?php echo "给我一百万, 否则黑了你的服务器" ?>';
echo strip_tags($tags) . '<hr>';
url相关
这个会打印很多东西
<?php
printf('<pre>%s</pre>', print_r($_SERVER, true));
?>
echo $_SERVER['QUERY_STRING'] . '<br>';
$arr = explode('&', $_SERVER['QUERY_STRING']);
// printf('<pre>%s</pre>', print_r($arr, true));
// queryString -> array
parse_str($_SERVER['QUERY_STRING'], $arr);
// printf('<pre>%s</pre>', print_r($arr, true));
$userArr = ['id' => 1, 'username' => 'admin', 'role' => 'manager'];
// id=1&username=admin&role=manage
// echo http_build_query($userArr) . '<br>';
// printf('<pre>%s</pre>', print_r($_GET, true));
$url = 'http://php.edu/0421/demo4.php?a=1&b=2&c=3&id=1';
$arr = parse_url($url);
printf('<pre>%s</pre>', print_r($arr, true));
echo $_SERVER['QUERY_STRING'];
echo '<hr>';
echo parse_url($url)['query'];
echo parse_url($url)['query'] === $_SERVER['QUERY_STRING'] ? '相等' : '不等';
键值对形式数组的遍历
<?php
//再谈数组遍历
$stu =['id'=>1,'name'=>'Jack','course'=>'java','score'=>90];
// 拿到数组的键值对
printf('[%s]=>%s<br>',key($stu),current($stu));// 这个默认会拿到当前数组的第一个值
?>
<?php
$stu =['id'=>1,'name'=>'Jack','course'=>'java','score'=>90];
printf('[%s]=>%s<br>',key($stu),current($stu));
next($stu);//后移
printf('[%s]=>%s<br>',key($stu),current($stu));
next($stu);//后移
printf('[%s]=>%s<br>',key($stu),current($stu));
prev($stu); //前移
printf('[%s]=>%s<br>',key($stu),current($stu));
?>
打印这个 :
[id]=>1
[name]=>Jack
[course]=>java
[name]=>Jack
上述代码实现自动遍历
// 自动遍历
<?php
$stu =['id'=>1,'name'=>'Jack','course'=>'java','score'=>90];
if (count($stu) > 0) {
while (true) {
printf('[%s]=>%s<br>', key($stu), current($stu));
if (next($stu)) {
continue;
}else{
break;
}
}
} else {
echo '空数组';
}
?>
foreach 遍历(快捷遍历)
<?php
$stu = ['id' => 1, 'name' => 'Jack', 'course' => 'php', 'score' => 90];
foreach($stu as $key => $value) {
printf('[%s]=>%s<br>', $key, $value);
}
?>
解构遍历
// 索引数组
list($id, $name) = [10, 'Tony'];
// list 不是函数,因为函数不能放在等号左边, 不能用在“左值”
printf('$id = %s, $name = %s<br>', $id, $name);
<?php
// 解构通常用来遍历二维或以上的数组
$users = [
['id' => 10, 'name' => 'Tony'],
['id' => 11, 'name' => 'John'],
['id' => 12, 'name' => 'Jerry'],1. 与值相关
];
// foreach
foreach ($users as list('id' => $id, 'name' => $name)) {
printf('$id = %s, $name = %s<br>', $id, $name);
}
?>
数组函数
与值相关
<?php
$arr = [3 => 10, 9 => 20, 0 => 'html', 'id' => 'css', 20 => 20, 30];
printf('<pre>%s</pre>', print_r($arr, true));
?>
打印:
Array
(
[3] => 10
[9] => 20
[0] => html
[id] => css
[20] => 20
[21] => 30
)
这个打印的全部的数组
array_values()
<?php
$arr = [3 => 10, 9 => 20, 0 => 'html', 'id' => 'css', 20 => 20, 30];
printf('<pre>%s</pre>', print_r(array_values($arr), true));
?>
打印:
Array
(
[0] => 10
[1] => 20
[2] => html
[3] => css
[4] => 20
[5] => 30
)
这个打印的是数组的值
in_array()
$arr = [3 => 10, 9 => 20, 0 => 'html', 'id' => 'css', 20 => 20, 30];
var_dump(in_array('html', $arr));
这个打印 : bool(true) , 说明 html 这个值在数组里
array_search()
<?php
$arr = [3 => 10, 9 => 20, 0 => 'html', 'id' => 'css', 20 => 20, 30];
$key = array_search('20', $arr);
echo $key; 这个打印的是9 ,它是20的键
echo $arr[$key]; 这个会根据键值拿到value的值,键值是9,value就是20
?>
array_unique 去重复
<?php
$arr = [3 => 10, 9 => 20, 0 => 'html', 'id' => 'css', 20 => 20, 30];
printf(
'<pre>%s</pre>',
print_r(array_unique($arr), true)
);
?>
打印:
Array
(
[3] => 10
[9] => 20
[0] => html
[id] => css
[21] => 30
)
少了一个 20=>20 去掉了重复的
统计
$arr = [3 => 10, 9 => 20, 0 => 'html', 'id' => 'css', 20 => 20, 30];
echo count($arr); 这个会打印出数组里有6个元素
这个是求和函数
<?php
function sum (...$args)
{
return array_sum($args);
}
echo sum(1,2,3,4,5,6) //打印 21
?>
这个是求乘积的
function mul(...$args)
{
return array_reduce($args, function ($acc, $cur) {
return $acc * $cur;
}, 1);
}
echo mul(2, 3, 4, 5); //这个打印120
--------------------------------------------------
function mul(...$args)
{
return array_product($args);
}
echo mul(2, 3, 4, 5); //这个也打印120
栈和队列
<?php
// 栈与队: 一个增删元素受限的数组(线性表)
// 1. 栈操作:
// 仅限在尾部进行增删
$stack = [];
array_push($stack, 10);
// printf('<pre>%s</pre>', print_r($stack, true));
array_push($stack, 20, 30);
// printf('<pre>%s</pre>', print_r($stack, true));
echo array_pop($stack);
echo array_pop($stack);
echo array_pop($stack);
// printf('<pre>%s</pre>', print_r($stack, true));
// 仅限头部增删
array_unshift($stack, 10);
// printf('<pre>%s</pre>', print_r($stack, true));
array_unshift($stack, 30, 20);
// printf('<pre>%s</pre>', print_r($stack, true));
echo array_shift($stack);
echo array_shift($stack);
echo array_shift($stack);
// 2. 队: 尾部添加, 头部删除
$queue = [];
// 入队
array_push($queue, 10, 20, 30);
printf('<pre>%s</pre>', print_r($queue, true));
// 出队
echo array_shift($queue);
echo array_shift($queue);
echo array_shift($queue);
printf('<pre>%s</pre>', print_r($queue, true));
头部添加, 尾部删除
array_unshift() + array_pop()
?>
排序相关
<?php
$blue = range(1, 16);
printf('<pre>%s</pre>', print_r($blue, true));
打乱排序
shuffle($blue);
printf('<pre>%s</pre>', print_r($blue, true));
?>
<?php
// ! 值
$arr = [30, 4, 82, 15, 20, 'abc', 'hello', 2, 46];
printf('原始:<pre>%s</pre>', print_r($arr, true));
sort($arr);
// 确保原关系不变, 原来的键与值的对应不发生变化
asort($arr);
printf('升序:<pre>%s</pre>', print_r($arr, true));
?>
打印这个:
原始:
Array
(
[0] => 30
[1] => 4
[2] => 82
[3] => 15
[4] => 20
[5] => abc
[6] => hello
[7] => 2
[8] => 46
)
升序:
Array
(
[0] => 2
[1] => 4
[2] => 15
[3] => 20
[4] => 30
[5] => 46
[6] => 82
[7] => abc
[8] => hello
)
降序
<?php
$arr = [30, 4, 82, 15, 20, 'abc', 'hello', 2, 46];
printf('原始:<pre>%s</pre>', print_r($arr, true));
rsort($arr);
//确保原关系不变, 原来的键与值的对应不发生变化
arsort($arr);
printf('升序:<pre>%s</pre>', print_r($arr, true));
?>
打印:
原始:
Array
(
[0] => 30
[1] => 4
[2] => 82
[3] => 15
[4] => 20
[5] => abc
[6] => hello
[7] => 2
[8] => 46
)
升序:
Array
(
[0] => hello
[1] => abc
[2] => 82
[3] => 46
[4] => 30
[5] => 20
[6] => 15
[7] => 4
[8] => 2
)
查询和替换
array_slice
<?php
$stu = ['id' => 101, 'name' => '无忌', 'age' => 20, 'course' => 'php', 'grade' => 80];
printf('<pre>%s</pre>',print_r($stu,true));
$res = array_slice($stu,0,2);// 从0 开始取前2个
printf('<pre>%s</pre>',print_r($res,true));
$res = array_slice($stu,-2); //取后2个的值
printf('<pre>%s</pre>',print_r($res,true));
?>
array_splice() 这个删除数组里的元素
<?php
$arr = [10, 28, 9, 33, 56, 21, 82, 47];
// 删除从索引1 开始的2个元素
$res = array_splice($arr, 1, 2); // 删除28 和 9 ,res数组里是28 和9
printf('<pre>%s</pre>', print_r($res, true));
?>
array_splice() 也可以更新指定位置的元素
第2个位置删除2个,使用新的数据来替换掉它
<?php
$arr = [10, 28, 9, 33, 56, 21, 82, 47];
$res = array_splice($arr, 1, 2, ['hello', 'world']);// 这个的$res 是返回的2个被删除的指定位置的元素
printf('<pre>%s</pre>', print_r($res, true));
printf('<pre>%s</pre>', print_r($arr, true));
?>
res是这个
Array
(
[0] => 28
[1] => 9
)
arr被更新了
Array
(
[0] => 10
[1] => hello
[2] => world
[3] => 33
[4] => 56
[5] => 21
[6] => 82
[7] => 47
)
数组回调函数
<?php
array_filter: 仅返回数组中可转为true的元素集合
$arr = [
150,
'php',
true,
[4, 5, 6],
(new class
{
}),
[],
null,
false,
'',
0,
'0'
];
$res = array_filter($arr, function ($item) {
if ($item) {
return is_scalar($item);
}
});
printf('<pre>%s</pre>', print_r($res, true));
?>
array_map
$arr = ['php', [3, 4, 5], (new class
{
public $name = '电脑';
public $price = 8888;
}), 15, 20];
// array_map的第一个值是回调函数,第二个值是arr
$res = array_map(function ($item) {
switch (gettype($item)) {
case 'array':
$item = join(', ', $item);
break;
case 'object':
$item = join(', ', get_object_vars($item));
}
return $item;
}, $arr);
printf('<pre>%s</pre>', print_r($res, true));
归并
这个会把数组里的元素加起来
$arr = [10, 20, 30, 40, 50];
$res = array_reduce($arr, function ($acc, $cur) {
echo $acc, ', ', $cur, '<br>';
return $acc + $cur;
}, 0);
echo $res . '<hr>';
array_walk()
<?php
$user = ['id' => 10, 'name' => 'admin', 'email' => 'admin@php.cn'];
array_walk($user, function ($value, $key, $color) {
printf('[%s]=><span style="color:%s">%s</span>', $key, $color, $value);
}, 'blue');
?>
打印这个:
[id]=>10[name]=>admin[email]=>admin@php.cn
php操作数据库
启动数据库扩展:
在php.ini 中
extension="D:\PHP\php-8\ext\php_mysqli.dll"
extension="D:\PHP\php-8\ext\php_pdo_mysql.dll"
```
<?php
namespace pdo_edu;
use PDO;
$username = 'root';
$password = 'helloMuseum';
$dsn = 'mysql:host=192.168.56.104;dbname=mydb1;port=3307;charset=utf8';
$db=new PDO($dsn,$username,$password);
var_dump($db);
if($db){
echo '<h2>连接成功</h2>';
}
```
php 操作数据库的例子
同一级别目录下创建两个文件
config/database.php
<?php
namespace pdo_edu;
$dbConfig=[
'type'=>'mysql',
'host'=>'192.168.56.104',
'dbname'=>'mydb1',
'port'=>'3307',
'charset' => 'utf8',
'username'=>'root',
'password'=>'helloMuseum'
];
return $dbConfig;
config/connect_test.php
<?php
namespace pdo_edu;
use PDO;
// 同一级别目录下的文件引入,
$dbConfig = require 'database.php';
// $dbConfig = include 'database.php'; 这是用include 引入,也是可以的
//print_r($dbConfig);
//将关联数组中的每一个成员,打散成独立的变量
extract($dbConfig);
echo <<< SHOW
$type;
$host;
$dbname;
$port;
$charset;
$username;
$password;
SHOW;
// pdo: 连接三要素
// 1. dsn
// mysql:host=127.0.0.1;dbname=phpedu;port=3306;charset=utf8;
$tpl = '%s:host=%s;dbname=%s;port=%s;charset=%s';
$args = [$type, $host, $dbname, $port, $charset];
$dsn = sprintf($tpl, ...$args);
// 2. 创建数据对象
$db = new PDO($dsn, $username, $password);
// var_dump($db);
if ($db) echo '<h2>连接成功</h2>';
config/connect.php
<?php
namespace pdo_edu;
use PDO;
$dbConfig = include 'database.php';
extract($dbConfig);
$tpl = '%s:host=%s;dbname=%s;port=%s;charset=%s';
$args = [$type, $host, $dbname, $port, $charset];
$dsn = sprintf($tpl, ...$args);
//echo $dsn;
$db = new PDO($dsn, $username, $password);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
// var_dump($db);
跟config文件夹同级创建demo2.php
<?php
namespace pdo_edu;
use PDO;
require __DIR__ . '/config/connect.php';
数据库的操作例子
读操作select,写操作insert update,delete
create table staff(
id int primary key auto_increment,
name varchar(10) comment '姓名',
sex int default 1 comment '性别',
email varchar(30) comment '邮箱'
)
demo3.php
<?php
namespace php_edu;
/**
* 数据库常用操作
* 1. 读操作: select
* 2. 写操作: insert,update,delete
* 简称: CURD, 增删改查
*/
// 1. 连接数据库
require __DIR__ . '/config/connect.php';
// 2. CURD: INSERT
/**
* PDO预处理
* 为什么要用预处理?
* 1. 防止SQL注入攻击, 2. 数据延迟绑定
* (编程时只写SQL语句模板,执行SQL时再给占位符绑定真实数据)
* 预处理过程:
* 1. 创建SQL语句模板对象: 数据使用占位符表示
* 2. 执行SQL语句,根据操作类型(写/读),读返回结果集/数组, 写返回受影响的记录数量
*/
// INSERT 插入
// INSERT 表名 SET 字段1=值1, 字段2=值2, ....
// SQL语句的推荐规范:
// 1. 关键字全大写
// 2. 表名,字段名使用反引号做为定界符
$sql = 'INSERT `staff` SET `name` = ?, `sex` = ?, `email` = ?';
// 1. 创建SQL语句模板对象
$stmt = $db->prepare($sql);
// 2. 执行SQL语句
$stmt->execute(['小龙女', 1, 'xiaolongnv@php.cn']);
$stmt->execute(['洪七公', 0, 'hongqigong@php.cn']);
$stmt->execute(['黄蓉', 0, 'huangrong@php.cn']);
$stmt->execute(['杨过', 0, 'yangguo@php.cn']);
$stmt->execute(['猪老师', 0, 'zhulaoshi@php.cn']);
$stmt->execute(['灭绝', 0, 'miejue@php.cn']);
// 成功
// $stmt->rowCount(): 返回受影响的记录数量
if ($stmt->rowCount() > 0) {
echo '新增成功, 新增记录的主键ID = ' . $db->lastInsertId();
} else {
echo '新增失败';
print_r($stmt->errorInfo());
}
// INSET INTO table (字段列表) VALUES (值列表)
update
<?php
namespace php_edu;
// 1. 连接数据库
require __DIR__ . '/config/connect.php';
// 2. CURD: UPDATE 更新
// UPDATE 表名 SET 字段1=值1 ... WHERE 更新条件
$sql = 'UPDATE `staff` SET `name` = ? WHERE `id` = ?';
$stmt = $db->prepare($sql);
$stmt->execute(['老顽童', 6]);
if ($stmt->rowCount() > 0) {
echo '更新成功';
} else {
echo '更新失败';
print_r($stmt->errorInfo());
}
delete
<?php
namespace php_edu;
// 1. 连接数据库
require __DIR__ . '/config/connect.php';
// 2. CURD: DELETE 删除
// DELETE FROM 表名 SET 字段1=值1 ... WHERE 更新条件
// $sql = 'DELETE FROM `staff` WHERE `id` = ? ';
// '?' : 匿名占位符
// 'string': 命名占位符
$sql = 'DELETE FROM `staff` WHERE `id` = :id';
$stmt = $db->prepare($sql);
$stmt->execute([':id' => $_GET['id']]);
// 如果条件来自外部, 例如 url 中 get 参数
// echo $_GET['id'];
if ($stmt->rowCount() > 0) {
echo 'id = ' . $_GET['id'] . ' 删除成功';
} else {
echo '删除失败';
print_r($stmt->errorInfo());
}
select
<?php
namespace php_edu;
use PDO;
// 1. 连接数据库
require __DIR__ . '/config/connect.php';
// 2. CURD: SELECT 单条查询
// SELECT 字段列表 FROM 表名 WHERE 查询条件
$sql = 'SELECT `id`,`name` FROM `staff` WHERE `id` > :id';
$stmt = $db->prepare($sql);
$stmt->execute(['id' => 10]);
// 单条查询
// $staff = $stmt->fetch(PDO::FETCH_ASSOC);
// printf('<pre>%s</pre>', print_r($staff, true));
// $staff = $stmt->fetch(PDO::FETCH_ASSOC);
// printf('<pre>%s</pre>', print_r($staff, true));
// $staff = $stmt->fetch(PDO::FETCH_ASSOC);
// printf('<pre>%s</pre>', print_r($staff, true));
// $staff = $stmt->fetch(PDO::FETCH_ASSOC);
// var_dump($staff);
// PDO::FETCH_ASSOC: 结果集获取模式,只返回关联部分
while ($staff = $stmt->fetch()) {
printf('<pre>%s</pre>', print_r($staff, true));
}
<?php
namespace php_edu;
use PDO;
// 1. 连接数据库
require __DIR__ . '/config/connect.php';
// 2. CURD: SELECT 多条查询
// SELECT 字段列表 FROM 表名 WHERE 查询条件
$sql = 'SELECT `id`,`name` FROM `staff` WHERE `id` > :id';
$stmt = $db->prepare($sql);
$stmt->execute(['id' => 10]);
// fetchAll: 返回全部满足条件的记录集合,二维数组
$staffs = $stmt->fetchAll();
// print_r($staffs);
foreach ($staffs as $staff) {
printf('<pre>%s</pre>', print_r($staff, true));
}
文件上传
https://www.php.net/manual/zh/index.php
https://www.php.net/manual/zh/reserved.variables.files.php
允许上传文件的表单特征:
1. method=“POST”
2. 文件编码格式enctype=“multipart/form-data”
$_FILES: PHP超全局变量数量, 保存着上传文件的全部信息
- $_FILES: 二维数组,每个元素对应一个上传的文件
- name: 原始文件名
- type: 文件类型, mime类型
- tmp_name: 临时目录
- error: 错误代码
- size: 文件大小(字节表示 byte)
单文件上传:
<!DOCTYPE html>
<html lang="zh-CN">
<?php
// $_FILES: PHP超全局变量数量, 保存着上传文件的全部信息
printf('<pre>%s</pre>', print_r($_FILES, true));
if (isset($_FILES['my_pic'])) {
$name = $_FILES['my_pic']['name'];
$tmpName = $_FILES['my_pic']['tmp_name'];
$error = $_FILES['my_pic']['error'];
if ($error > 0) {
$tips = '<span style="color:red">上传失败:</span>';
switch ($error) {
case 1:
$tips .= '上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值';
break;
case 2:
$tips .= '文件大小超过了上传表单中MAX_FILE_SIZE最大值';
break;
case 3:
$tips .= '文件只有部分被上传';
break;
case 4:
$tips .= '没有文件被上传';
break;
case 6:
$tips .= '找不到临时目录';
break;
case 7:
$tips .= '文件写入失败,请检查目录权限';
break;
}
echo "<p>$tips</p>";
} else {
// 判断用户是不是通过合法的POST方式上传
if (is_uploaded_file($tmpName)) {
// 设置允许上传文件类型的白名单
$allow = ['jpg', 'jpeg', 'png', 'gif'];
// 获取文件扩展名
$ext = pathinfo($name)['extension'];
if (in_array($ext, $allow)) {
// 二个条件都满足了
// 1. post方式上传的 2. 文件类型是合法的
// 目标目录
$path = 'uploads/';
// 自定义目标文件名
$dest = $path . md5($name) . '.' . $ext;
// 将文件从临时目录中移动到目标目录中并重命名
if (move_uploaded_file($tmpName, $dest)) {
echo '<p style="color:green">上传成功</p>';
// 预览
echo "<img src='$dest' width='200' >";
} else {
echo '<p style="color:red">移动失败</p>';
}
} else {
echo '<p style="color:red">文件类型错误</p>';
}
} else {
echo '<p style="color:red">非法方式上传</p>';
}
}
}
?>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文件上传的表单构造,超全局变量$_FILE</title>
</head>
<body>
<!-- 允许上传文件的表单特征:
1. method="POST"
2. enctype="multipart/form-data" -->
<form action="" method="POST" enctype="multipart/form-data">
<fieldset>
<legend>单文件上传</legend>
<!-- 浏览器中限制上传文件的大小,写到一个隐藏域中,并写到type=file之前 -->
<input type="hidden" name="MAX_FILE_SIZE" value="300000">
<input type="file" name="my_pic">
<button>上传</button>
</fieldset>
</form>
</body>
</html>
多文件上传
<!DOCTYPE html>
<html lang="zh-CN">
<?php
// $_FILES: PHP超全局变量数量, 保存着上传文件的全部信息
printf('<pre>%s</pre>', print_r($_FILES, true));
foreach ($_FILES as $file) {
// $file中保存着每一个文件的信息
if ($file['error'] === 0) { // error等于0 表示上传成功
$destFile = 'uploads/' . $file['name'];
move_uploaded_file($file['tmp_name'], $destFile);
echo "<img src='$destFile' width='200'>";
}
}
?>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>多文件上传1</title>
</head>
<body>
<form action="" method="POST" enctype="multipart/form-data">
<fieldset>
<legend>多文件上传:逐个上传</legend>
<input type="file" name="my_pic1">
<input type="file" name="my_pic2">
<input type="file" name="my_pic3">
<button>上传</button>
</fieldset>
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<?php
// $_FILES: PHP超全局变量数量, 保存着上传文件的全部信息
printf('<pre>%s</pre>', print_r($_FILES, true));
if (isset($_FILES['my_pic'])) {
// 这时只需要遍历 $_FILES['my_pic']['error'] 这个数组
foreach ($_FILES['my_pic']['error'] as $key => $error) {
if ($error === 0) {//error等于0 表示上传成功
// 临时文件名
$tmpName = $_FILES['my_pic']['tmp_name'][$key];
// 原始文件名
$name = $_FILES['my_pic']['name'][$key];
// 目标文件名
$destFile = 'uploads/' . $name;
move_uploaded_file($tmpName, $destFile);
echo "<img src='$destFile' width='200'>";
}
}
}
?>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>多文件上传2</title>
</head>
<body>
<form action="" method="POST" enctype="multipart/form-data">
<fieldset>
<legend>多文件上传:逐个上传2</legend>
<!-- 数组来表示每个要上传的表单域的名称 -->
<input type="file" name="my_pic[]">
<input type="file" name="my_pic[]">
<input type="file" name="my_pic[]">
<button>上传</button>
</fieldset>
</form>
</body>
</html>
批量上传
<!DOCTYPE html>
<html lang="zh-CN">
<?php
// $_FILES: PHP超全局变量数量, 保存着上传文件的全部信息
printf('<pre>%s</pre>', print_r($_FILES, true));
if (isset($_FILES['my_pic'])) {
// 这时只需要遍历 $_FILES['my_pic']['error'] 这个数组
foreach ($_FILES['my_pic']['error'] as $key => $error) {
if ($error === 0) {
// 临时文件名
$tmpName = $_FILES['my_pic']['tmp_name'][$key];
// 原始文件名
$name = $_FILES['my_pic']['name'][$key];
// 目标文件名
$destFile = 'uploads/' . $name;
move_uploaded_file($tmpName, $destFile);
echo "<img src='$destFile' width='200'>";
}
}
}
?>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>多文件上传2</title>
</head>
<body>
<form action="" method="POST" enctype="multipart/form-data">
<fieldset>
<legend>多文件上传:批量上传</legend>
<!-- multiple: 允许同时选择多个 -->
<input type="file" name="my_pic[]" multiple>
<button>上传</button>
</fieldset>
</form>
</body>
</html>
分页
demo5.php
<?php
// 1. 连接数据库
$db = new PDO('mysql:dbname=phpedu', 'root', 'root');
// 2. 当前页, 在GET参数中
// https://www.php.cn/course.html?p=5
// $page = isset($_GET['p']) ? $_GET['p'] : 1;
// null合并
$page = $_GET['p'] ?? 1;
echo "当前页: p= $page <br>";
// 3. 每页显示数量
$num = 5;
// 4. 记录总数
$sql = 'SELECT COUNT(`id`) AS `total` FROM `staff`';
$stmt = $db->prepare($sql);
$stmt->execute();
// 将某列的仠与php变量绑定 , `total` => $total
$stmt->bindColumn('total', $total);
$stmt->fetch(PDO::FETCH_ASSOC);
echo "总记录数量: $total <br>";
// 5. 总页数
// 10.1 => 11 ceil: 向上取整,不丢数据
$pages = ceil($total / $num);
echo "总页数: $pages <br>";
// 6. 偏移量
// offset = (page - 1) * num
$offset = ($page - 1) * $num;
echo "偏移量: $offset <br>";
// 7. 分页数据
// $sql = "SELECT * FROM `staff` LIMIT $num OFFSET $offset";
$sql = "SELECT * FROM `staff` LIMIT $offset, $num";
$stmt = $db->prepare($sql);
$stmt->execute();
$staffs = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 遍历
echo '<hr>';
if (count($staffs) === 0) {
echo '查询结果为空';
} else {
foreach ($staffs as $staff) {
extract($staff);
printf('$d-%s-%s-%s<br>', $id, $name, $sex, $email);
}
}
echo '<hr>';
demo6.php
<?php require 'demo5.php' ?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>页面展示分页数据</title>
<style>
table {
width: 400px;
border-collapse: collapse;
text-align: center;
}
table th,
table td {
border: 1px solid;
padding: 5px;
}
table thead {
background-color: lightcyan;
}
table caption {
font-size: larger;
margin-bottom: 8px;
}
p>a {
text-decoration: none;
color: #555;
border: 1px solid;
padding: 5px 10px;
margin: 10px 2px;
}
.active {
background-color: seagreen;
color: white;
border: 1px solid seagreen;
}
</style>
</head>
<body>
<table>
<caption>员工信息表</caption>
<thead>
<tr>
<th>ID</th>
<th>姓名</th>
<th>性别</th>
<th>邮箱</th>
</tr>
</thead>
<tbody>
<?php foreach ($staffs as $staff) : extract($staff) ?>
<tr>
<td><?= $id ?></td>
<td><?= $name ?></td>
<td><?= $sex ?></td>
<td><?= $email ?></td>
</tr>
<?php endforeach ?>
</tbody>
</table>
<p>
<?php for ($i = 1; $i <= $pages; $i++) : ?>
<!-- <a href="<?= $_SERVER['PHP_SELF'] . '?p=' . $i ?>" class="<?= ($i == $_GET['p']) ? 'active' : null ?>"><?= $i ?></a> -->
<?php
$url = $_SERVER['PHP_SELF'] . '?p=' . $i;
$active = $i == $_GET['p'] ? 'active' : null;
?>
<a href="<?= $url ?>" class="<?= $active ?>"><?= $i ?></a>
<?php endfor ?>
</p>
</body>
</html>
php的会话控制
这个是cookie的用法
<?php
// cookie: 在客户端(浏览器)保存用户信息
// 第一次访问一个php脚本文件
// 那么这个php可以通过一个函数来给客户端设置cookie
// 服务器识别用户,是通过用户使用的终端/浏览器来识别
setcookie('username', 'Peter-Zhu', time() + 60, '/');
echo $_COOKIE['username'] . '<br>';
$_COOKIE['username'] = 'admin';
echo $_COOKIE['username'] . '<br>';
// $_COOKIE['username'] = null;
unset($_COOKIE['username']);
echo $_COOKIE['username'] ?? '没找到' . '<br>';
// 实际工作中, 为了用户数据的安全, 应该将用户资料保存到服务器上
实际工作中, 为了用户数据的安全, 应该将用户资料保存到服务器上
这才是session的用法
在php.ini 里的
这个参数可以修改session的位置
session.save_path = "/tmp"
改成
session.save_path = "D:/PHP/session/"
<?php
// 发一张好人卡给用户的访问终端
// 好人卡,就是用户使用设备的ID
// 开启一个会话
session_start();
/**
* 执行二个动作
* 1. 浏览器: PHPSESSID, 基于cookie
* 2. 服务器: 创建一个与PHPSESSID同名的会话文件
*/
$_SESSION['email'] = 'admin@php.cn';
$_SESSION['password'] = md5(md5('123456') . 'php.cn888');
// $_SESSION = [];
// 直接将服务器上的会话文件删除,如果不把这个 session_destory()注释掉,你就看不到你的session 了,在文件夹里
session_destroy();
index.php
<?php
session_start();
// 判断用户是否已经登录?
if (isset($_SESSION['user'])) $user = unserialize($_SESSION['user']);
// print_r($user);
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<nav>
<?php if (isset($user)) : ?>
<a href="" id="logout">退出</a>
<?php else : ?>
<a href="login.php">登录</a>
<?php endif ?>
</nav>
<script>
document.querySelector('#logout').addEventListener('click', function(event) {
if (confirm('是否退出?')) {
// 禁用默认跳转行为
event.preventDefault();
// 跳转到处理器
location.assign('handle.php?action=logout');
}
});
</script>
</body>
</html>
login.php
<!DOCTYPE html>
<html lang="zh-CN">
<?php
session_start();
// 判断用户是否已经登录?
if (isset($_SESSION['user'])) echo '<script>alert("不要重复登录");locatoin.href="index.php"</script>';
?>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>用户登录表单</title>
</head>
<body>
<form action="handle.php?action=login" method="POST">
<fieldset style="display: inline-block;background:lightcyan">
<legend>用户登录</legend>
<p>
<input type="email" name="email" placeholder="user@email.com" require>
</p>
<p>
<input type="password" name="password" placeholder="不少于6位" require>
</p>
<p>
<button>提交</button>
</p>
</fieldset>
<a href="register.php">如果没有帐号,请先登录</a>
</form>
</body>
</html>
register.php
<!DOCTYPE html>
<html lang="zh-CN">
<?php
session_start();
// 判断用户是否已经登录?
if (isset($_SESSION['user'])) echo '<script>alert("不要重复登录");locatoin.href="index.php"</script>';
?>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>用户注册表单</title>
</head>
<body>
<form action="handle.php?action=login" method="POST">
<fieldset style="display: inline-block;background:lightcyan">
<legend>用户注册</legend>
<p>
<input type="email" name="email" placeholder="user@email.com" require>
</p>
<p>
<input type="password" name="password" placeholder="不少于6位" require>
</p>
<p>
<input type="password" name="password" placeholder="二次必须一致" require>
</p>
<!-- 二次密码是否一致用JS进行验证就可以了 -->
<p>
<button>提交</button>
</p>
</fieldset>
</form>
</body>
</html>
handle.php
<?php
// 开启会话
session_start();
// 根据用户的不同请求,执行不同的操作
// 比如:登录 , 注册, 退出
// 连接数据并获取用户表中的数据
$db = new PDO('mysql:dbname=phpedu', 'root', 'root');
$stmt = $db->prepare('SELECT * FROM `user`');
$stmt->execute();
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
// print_r($users);
$action = $_GET['action'];
switch (strtolower($action)) {
// 登录
case 'login':
//要保证数据是通用POST请求发送的
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// 先拿到登录数据
extract($_POST);
// $email = $_POST['email'];
// $password = sha1($_POST['password']);
// $result 是数组
$result = array_filter($users, function ($user) use ($email, $password) {
return $user['email'] === $email && $user['password'] === md5($password);
});
if (count($result) === 1) {
// 验证成功,将用户信息写到SESSION
// print_r(serialize(array_pop($result)));
// $a = serialize(array_pop($result));
// print_r(unserialize($a));
// 将用户信息序列化之后保存到SESSION中
$_SESSION['user'] = serialize(array_pop($result));
exit('<script>alert("验证通过");location.href="index.php"</script>');
} else {
exit('<script>alert("邮箱或密码错误");location.href="index.php"</script>');
}
} else {
die('请求错误');
}
break;
// 退出
case 'logout':
if (isset($_SESSION['user'])) {
session_destroy();
exit('<script>alert("退出成功");location.assign("index.php")</script>');
}
break;
// 注册
case 'register':
// 1. 获取到新用户的信息
$name = $_POST['name'];
$email = $_POST['email'];
$password = md5($_POST['psw1']);
$register_time = time();
// 2. 将新用户添加到表中
$sql = 'INSERT user SET name=?,email=?,password=?,register_time=?';
$stmt = $db->prepare($sql);
$stmt->execute([$name, $email, $password, $register_time]);
if ($stmt->rowCount() === 1) {
echo '<script>alert("注册成功");locaton.href="index.php"</script>';
} else {
exit('<script>alert("注册失败");locaton.href="index.php"</script>');
}
break;
}
php的面向对象
文件包含
方式1 用include inc目录下建立一个f1.php
inc/f1.php
<?php
$username ='朱元璋';
return $email ='1234@qq.com';
demo1.php
<?php
include 'inc/f1.php';
echo $username .'<br>';
echo $email .'<br>';
```
方式2 用 绝对路径
<?php
include __DIR__ . '/inc/f1.php';
echo $username .'<br>';
echo $email .'<br>';
```
这里使用了 f1.php 里return 返回的值
<?php
include __DIR__ . '/inc/f1.php';
echo $username .'<br>';
$email = include __DIR__ . '/inc/f1.php' ;
echo $email .'<br>';
```
<?php
require __DIR__ . '/inc/f1.php';
echo $username .'<br>';
$email = require __DIR__ . '/inc/f1.php' ;
echo $email .'<br>';
```
include 和 require的区别:
include 用到的时候再加载,动态的; require 应该写在顶部,静态;一般用require多一点,需要出错不执行。
类
<?php
// 类声明
class Goods
{
}
//类的实例化:创建对象的过程
$goods = new Goods;
var_dump($goods);
echo '<hr>';
echo get_class($goods) .'<br>';
// 动态类
$str = 'goods';
$class = ucfirst('goods');
$o = new $class;
var_dump($o);
var_dump($o instanceof Goods);
类的成员: (1) 常规成员:属性,方法。
<?php
/**
* 类成员
* (一) 常规成员
* 1. 属性: 可以被其它方法所共享
* 2. 方法: 自定义, 魔术方法
*
* 访问限制符:
* 1. private: 私有,仅限在当前类中使用
* 2. protected: 继承, 可在本类或子类中使用, 不对外公开
* 3. public: 公共/公共,默认
*
* (二) 静态成员
* 1. static, 静态属性, 静态方法
* 2 . 与类实例无关, 静态成员 不要用$this
* 3 . 内部用self, 外部用类名
*
*/
class User1
{
// 常规成员
// 1. 属性
// 语法: 访问限制符 类成员声明
// 声明为私有, 实现封装
private $username;
// 2. 方法
// 2.1 自定义方法: 用户自己声明自己调用
public function getUsername()
{
// -> 对象成员访问符
// 当前实例的引用, $this 与实例绑定的
return $this->username;
}
// 2.2 魔术方法: 由系统来调用,用户不能直接调用
// 构造方法: 实例化进自动调用
public function __construct(string $username)
{
$this->username = $username;
}
}
// 实例化
$user1 = new User1('张老师');
echo $user1->getUsername();
echo '<hr>';
class User2
{
// 静态属性
private static $username = 'admin';
// 类常量: 与实例无关,用类访问
const APP = '商城';
// 方法
public static function getUsername()
{
// self: 功能与$this类似, 与当前类 User2 绑定
return self::$username;
}
}
// 实例访问静态方法是一个兼容bug, 能成功,但不要再用了
// echo (new User2)->getUsername();
// 应该永远用类来访问静态成员
echo User2::getUsername();
echo User2::APP;
<?php
/**
* 类的扩展/抽象/最终
* 1. protected: 受保护/可继承
* 2. extends: 扩展/继承
* 3. parent: 父类引用
* 4. abstract: 抽象
* 5. final: 最终类
*/
// 父类, 基类, 超类
class Person
{
// protected: 成员可继承,可以在子类中使用
protected $name;
// private: 私有, 仅限当前类, 子类,外部都不可见
private $id = 12345;
// public: 类中,子类, 类外都可见
public function __construct($name)
{
$this->name = $name;
}
// getInfo::protected
// 比protected再严格的是 private, 比它更宽松的是: public
protected function getInfo()
{
return $this->name;
}
}
// 学生类
// extends: Stu这个类,扩展了Person类的功能
class Stu extends Person
{
// 1. 属性扩展
private $lesson;
private $score;
// 2. 方法扩展/重写
public function __construct($name, $lesson, $score)
{
// 引用了父类的构造方法
// parent: 父类引用 Person
parent::__construct($name);
$this->lesson = $lesson;
$this->score = $score;
}
public function getInfo()
{
// $this->name
// return $this->name . "同学, ($this->lesson : $this->score 分)";
return parent::getInfo() . "同学, ($this->lesson : $this->score 分)";
}
}
$stu = new Stu('小狗', 'PHP', 88);
echo $stu->getInfo();
echo '<hr>';
$person = new Person('小猪');
// var_dump只打印属性
var_dump($person);
echo '<hr>';
// 如果不想让用户直接使用父类,而必须通过继承/扩展的子类来间接使用
// 将父类声明为一个抽象类
abstract class Demo1
{
}
// (new Demo1);
class Demo2 extends Demo1
{
}
echo 'Demo2的父类是: ' . get_parent_class(new Demo2);
echo '<hr>';
abstract class Demo3
{
// hello 方法已经被实现了
// protected function hello()
// {
// // ...
// }
// 抽象方法: 只有方法名,参数列表,没有具体实现(大括号)
abstract protected function hello($name);
}
class Demo4 extends Demo3
{
// 工作类Demo4中必须实现父类中的抽象成员
public function hello($name)
{
return 'Hello , ' . $name;
}
}
echo call_user_func([new Demo4, 'hello'], '牛老师');
echo '<hr>';
// 如果一个类不用扩展,直接当成工作类/直接干活的,直接new
// 为了防止被继承, 可声明为最终类
// final class Demo5
// {
// }
// class Demo6 extends Demo5
// {
// }
<?php
// 接口: 大号的抽象类
// 接口的所有成员,必须是抽象
// interface: 声明接口
// implements: 实现接口
interface iUser
{
// 1. 类常量
const NATION = 'CHINA';
// 2. 必须是抽象,必须是public
public function m1();
public function m2();
// 官方手册: 不建议声明抽象构造方法
}
// 接口不能直接用, 要用一个类来实现它
// 1. 用普通类来实现一个接口, 必须将接口中的所有抽象方法全部实现
class Demo1 implements iUser
{
public function m1()
{
}
public function m2()
{
}
}
// 2. 用抽象类来实现一个接口, 允许有不实现的抽象成员
abstract class Demo2 implements iUser
{
public function m1()
{
}
}
// php默认只支持单继承
// class A extends B, C , D
// 可通过接口,间接实现多继承
interface A
{
}
interface B
{
}
interface C
{
}
class Test implements A, B, C
{
}
// 查看当前类实现的所有接口
$arr = class_implements('Test');
printf('<pre>%s</pre>', print_r($arr, true));
属性和方法的重载命、名空间和自动加载
<?php
class User
{
//属性
private $data=[
'age' =>20
];
//查询拦截器
public function __get($name)
{
// $name :属性名
if(array_key_exists($name,$this->data))
{
return $this->data[$name];
}
return "属性 {$name} 不存在";
}
//更新拦截器
public function __set($name,$value)
{
// 1 有没有这个属性
if(array_key_exists($name,$this->data))
{
if($name==='age')
{
if($value>=18 && $value <=59)
{
$this->data[$name]=$value;
}else{
echo '年龄必须在18-59之间';
}
}else{
// 以上操作仅对age有效,其它属性直接赋值
$this->data[$name]=$value;
}
}else{
echo '禁止动态创建属性';
}
}
// 方法拦截器,使用 __call,当访问一个方法的时候默认会调用它
// 当类里有一个方法拦截器后,调用一个不存在的方法的时候就不会报异常了
public function __call($name, $args)
{
// $name: 方法名, $args: 传给方法的参数
printf('方法: %s<br>参数:<pre>%s</pre>', $name, print_r($args, true));
}
// 静态方法拦截器 使用 __callStatic,当访问一个静态方法的时候默认会调用它
public static function __callStatic($name, $args)
{
// $name: 方法名, $args: 传给方法的参数
printf('方法: %s<br>参数:<pre>%s</pre>', $name, print_r($args, true));
}
}
$user = new User;
// 这个会打印属性name 不存在
echo $user->name . '<br>';
/**
* 为一个属性赋值的时候,必须要搞清楚2件事
* 1. 有没有这个属性?
* 2. 这个值是否合法?
*/
$user->age = 80;
echo ' 打印值age :'. $user->age . '<br>';
echo '<hr color=red>';
// 常规方法/非静态方法/用实例调用
$user->hello('猪老师', 'php.cn');
// 静态方法
User::world(100, 200);
方法重载小案例
<?php
// 方法重载的小案例
// Db::table('think_user')->where('id', 1)->find();
// 1. 查询类
class Query
{
public function table($table)
{
// 返回当前类实例,方便后面的链式调用
return $this;
}
public function where($where)
{
return $this;
}
public function find()
{
// 不需要返回 $this,它最一个最终方法,输出查询结果
// 用数组来模拟数据表的查询结果
return ['id' => 1, 'name' => '猪老师', 'email' => '498668472@qq.com'];
}
}
$query = new Query;
// $query->table('think_user');
// $query->where('id', 1);
// $query->find();
$query->table('think_user')->where('id', 1)->find();
// Db::table('think_user')->where('id', 1)->find()
// 2. 入口类: 实现请求转发
class Db
{
// 静态方法重载/重定向
public static function __callStatic($name, $args)
{
// $query = new Query;
// return $query->$name($args);
// 回调的方式来执行对象方法
return call_user_func_array([new Query, $name], $args);
}
}
$res = Db::table('think_user')->where('id', 1)->find();
printf('<pre>%s</pre>', print_r($res, true));
命名空间
文件名相同,但是路径不同,所以不是同一个文件。
一个文件中,只允许声明一个命名空间;
命名空间的命名,应该与成员的路径一致;
inc/f1.php
<?php
function hello()
{
return __FUNCTION__;
}
const APP = '商城';
class Demo1
{
}
<?php
/**
* 命名空间: 解决了全局成员的命名冲突
* 全局成员: 类/接口, 常量 , 函数
*/
require __DIR__ . '/inc/f1.php';
这里会报错的,因为函数默认是全局的
function hello()
{
return __FUNCTION__;
}
这里会报错的,因为常量默认是全局的
const APP = '社区';
echo APP;
这里会报错,类/接口 是全局成员,不能重复声明
class Demo1
{
}
inc/f2.php
<?php
namespace ns1;
// 如果没有写命名空间,默认在全局
function hello($name)
{
return 'Hello 1111 ' . $name;
}
demo4.php
<?php
// 命名空间,使用namespace声明,必须写到第一行
namespace ns1;
require __DIR__ . '/inc/f2.php';
echo hello('猪老师') . '<br>';
demo4.php
<?php
require __DIR__ . '/inc/f2.php';
//命名空间写在了方法前面,指明使用ns1下的hello
echo \ns1\hello('猪老师') . '<br>';
demo5.php
// 一个脚本中,可以创建多个空间
namespace ns1 {
// 空间成员
//常量
const APP = '商城';
}
// 空间分级管理: 子空间
namespace ns2\ns3 {
const APP = '问答';
echo APP . '<br>';
}
namespace ns2 {
// 空间成员
//常量
const APP = '社区';
// 2. 非限定名称: 总是从当前空间开始查询
echo APP . '<br>';
echo \ns2\APP . '<br>';
// 在ns2中访问 ns1的APP
// 一定要通过全局空间/根空间进行访问
// 根空间: \
// 1. 完全限定名称: 从根空间开始查询
echo \ns1\APP . '<br>';
// 在ns2空间, 访问子空间 ns2\ns3中的成员
// 3. 限定名称: ns3\APP
echo '<span style="color:red">' . ns3\APP . '</span><br>';
}
/**
* 命名空间类型
* 1. 完全限定名称: 根空间开始 '\a\b\APP' "绝对路径"
* 2. 非限定名称: 从当前空间开始, 'APP' "当前路径"
* 3. 限定名称: 子空间, 'ns\APP' "相对路径"
*/
// 全局空间: 匿名的,不要写空间名, 用"\"来引用
namespace {
function hello()
{
echo 'hello 大家好';
}
echo '<span style="color:blue">' . ns1\APP . '</span><br>';
echo '<span style="color:coral">' . \ns2\ns3\APP . '</span><br>';
}
php/cn/Demo.php
<?php
/**
* 命名空间
* 1. 一个文件中, 只允许声明一个命名空间并只写一个类
* 2. 命名空间的命名,应该与成员的路径一致
*/
// 当前类文件的路径: php/cn/
// 和当前类的命名空间相似
namespace php\cn;
class Demo
{
}
echo Demo::class . '<br>';
php/cn/Demo1.php
<?php
/**
* 命名空间
* 1. 一个文件中, 只允许声明一个命名空间并只写一个类
* 2. 命名空间的命名,应该与成员的路径一致
*/
// 当前类文件的路径: php/cn/
// 和当前类的命名空间相似
namespace php\cn;
class Demo1
{
}
echo Demo1::class . '<br>';;
php/cn/Demo2.php
<?php
/**
* 命名空间
* 1. 一个文件中, 只允许声明一个命名空间并只写一个类
* 2. 命名空间的命名,应该与成员的路径一致
* 3. 类名,必须与类文件名对应
*/
// 当前类文件的路径: php/cn/
// 和当前类的命名空间相似
namespace php\cn;
class Demo2
{
}
echo Demo2::class . '<br>';
demo8.php
/**
* 命名空间
* 1. 一个文件中, 只允许声明一个命名空间并只写一个类
* 2. 命名空间的命名,应该与成员的路径一致
* 3. 类名,必须与类文件名对应
*/
<?php
namespace php\cn;
class Demo
{
}
echo Demo::class;
demo8.php
<?php
namespace ns1;
require __DIR__ . '/php/cn/Demo.php';
require __DIR__ . '/php/cn/Demo1.php';
require __DIR__ . '/php/cn/Demo2.php';
如果文件太多那么是不是要写很多require,那么使用自动加载
autoloader.php
<?php
// 类文件自动加载器
// 注册一个类的自动加载器
spl_autoload_register(function ($class) {
// echo $class;
// 1. 将命名空间=>映射到一个类文件的绝对路径
$path = str_replace('\\', DIRECTORY_SEPARATOR, $class);
// 2. 生成类文件路径
$file = __DIR__ . DIRECTORY_SEPARATOR . $path . '.php';
// 3. 加载这个类文件
require $file;
});
demo8.php
<?php
namespace ns1;
require __DIR__ . '/autoloader.php';
class Demo2
{
}
//访问Demo2
new \php\cn\Demo2;
echo Demo2::class . '<br>';
echo \php\cn\Demo2::class;
Composer的使用
Composer:https://www.phpcomposer.com/
Composer 是包依赖管理器
下载php依赖的地址:http://packagist.p2hp.com/
php.ini 修改了xdebug的配置
[xdebug]
zend_extension="D:\PHP\php-8\ext\php_xdebug-3.2.0-8.1-vs16-x86_64.dll"
// 这些参数被我注释掉了
;xdebug.remote_enable = 1
;xdebug.remote_autostart = 1
;xdebug.mode=debug
;xdebug.start_with_request=yes
这个命令可以升级 composer
composer selfupdate
这个命令来查看版本号
composer --version
composer install - 如有 composer.lock 文件,直接安装,否则从 composer.json 安装最新扩展包和依
composer update - 从 composer.json 安装最新扩展包和依赖;
第一步,我们在项目根目录里创建一个配置文件,文件的名字叫composer.json
也可以直接进入空目录,composer init 来创建文件
把依赖的下载地址换成阿里云的
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
把依赖的下载地址换成腾讯云的
composer config -g repos.packagist composer https://mirrors.cloud.tencent.com/composer/
vendor/composer/
autoload_classmap.php 类用这个操作
autoload_namespaces.php
autoload_psr4.php
autoload_real.php 操作文件用这个
autoload_static.php
ClassLoader.php
installed.json
instead.php
InstalledVersions.php
LICENSE
vendor/
autoload.php
在composer.json里写
{
"name": "hiapad/composer-demo",
"autoload": {
"psr-4": {
"Hiapad\\ComposerDemo\\": "src/"
},
//这里是我们添加上的 lib 和 src
"classmap": ["lib/","src/"]
},
"authors": [
{
"name": "guiyongbin",
"email": "739952043@qq.com"
}
],
"require": {
"zyan/captcha": "*"
}
}
然后执行 composer dumpautoload
会在vendor/composer/autoload_classmap.php里生成内容
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
//这就是生成的内容
return array(
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
'ns1\\Test1Class' => $baseDir . '/src/Test1.php',
'ns2\\Test2Class' => $baseDir . '/src/Test2.php',
'ns3\\Test1Class' => $baseDir . '/lib/Test1.php',
'ns4\\Test2Class' => $baseDir . '/lib/Test2.php',
);
demo.php 要使用composer的自动加载器
<?php
namespace demo1;
// 使用composer的自动加载器
require __DIR__ . '/vendor/autoload.php';
echo \ns1\Test1Class::show() .'<br>';
echo \ns2\Test2Class::show() .'<br>';
echo \ns3\Test1Class::show() .'<br>';
echo \ns4\Test2Class::show() .'<br>';
config/database.php 这是一个文件,不是一个类,那么如何加载文件呢
<?php
const DB = [
'type' => 'mysql',
'host' => 'localhost'
];
func/helper.php
<?php
// 公共函数库
function D($name)
{
var_dump($name);
}
在composer.json 里
{
"name": "hiapad/composer-demo",
"autoload": {
"psr-4": {
"Hiapad\\ComposerDemo\\": "src/"
},
"classmap": ["lib/","src/"],
// 这个就是加载文件的
"files": ["config/database.php", "func/helper.php"]
},
"authors": [
{
"name": "guiyongbin",
"email": "739952043@qq.com"
}
],
"require": {
"zyan/captcha": "*"
}
}
执行composer dumpautoload
demo.php
<?php
namespace demo1;
// 使用composer的自动加载器
require __DIR__ . '/vendor/autoload.php';
echo \ns1\Test1Class::show() .'<br>';
echo \ns2\Test2Class::show() .'<br>';
echo \ns3\Test1Class::show() .'<br>';
echo \ns4\Test2Class::show() .'<br>';
echo '<hr color=red>';
echo DB['host'] . '<br>';
//使用D 函数打印一个数组
echo D(['id' => 1, 'usrename' => 'admin']);
PSR-4 类的命名空间与类文件路径进行映射
创建文件夹 admin/controller
创建文件 admin/controller/admin.php
<?php
namespace admin\controller;
class User1
{
public static function index()
{
return '当前类名是: ' . __CLASS__;
}
}
composer.json
{
"name": "hiapad/composer-demo",
"autoload": {
"psr-4": {
"Hiapad\\ComposerDemo\\": "src/",
// 这样把admin 这个命名空间和目录admin 进行映射
"admin\\": "admin/"
},
"classmap": ["lib/","src/"],
"files": ["config/database.php", "func/helper.php"]
},
"authors": [
{
"name": "guiyongbin",
"email": "739952043@qq.com"
}
],
"require": {
"zyan/captcha": "*"
}
}
demo1.php
<?php
namespace demo1;
// require __DIR__ . '/src/Test1.php';
// require __DIR__ . '/src/Test2.php';
// require __DIR__ . '/lib/Test1.php';
// require __DIR__ . '/lib/Test2.php';
// 使用composer的自动加载器
require __DIR__ . '/vendor/autoload.php';
echo \ns1\Test1Class::show() .'<br>';
echo \ns2\Test2Class::show() .'<br>';
echo \ns3\Test1Class::show() .'<br>';
echo \ns4\Test2Class::show() .'<br>';
echo '<hr color=red>';
echo DB['host'] . '<br>';
//使用D 函数打印一个数组
echo D(['id' => 1, 'usrename' => 'admin']);
// PSR-4: 类的命名空间与类文件路径进行映射
echo \admin\controller\User1::index() . '<br>';