PHP(全称:PHP:Hypertext Preprocessor,即“PHP:超文本预处理器”)是一种开源的通用计算机脚本语言,尤其适用于网络开发并可嵌入HTML中使用。PHP的语法借鉴吸收C语言、Java和Perl等流行计算机语言的特点,易于一般程序员学习。PHP的主要目标是允许网络开发人员快速编写动态页面,但PHP也被用于其他很多领域。
yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
yum install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
yum install yum-utils
subscription-manager repos --enable=rhel-7-server-optional-rpms
yum-config-manager --enable remi-php72
yum update
yum install php72 php72-php-fpm php72-php-gd php72-php-json php72-php-mbstring php72-php-mysqlnd php72-php-xml php72-php-xmlrpc php72-php-opcache
php -v
apt -y install software-properties-common
add-apt-repository ppa:ondrej/php
apt -y update
apt install php7.2
apt install php-pear php7.2-fpm php7.2-curl php7.2-dev php7.2-gd php7.2-mbstring php7.2-zip php7.2-mysql php7.2-xml
php -v
# 下载
wget http://hk1.php.net/get/php-7.2.10.tar.gz/from/this/mirror php-7.2.10.tar.gz
# 解压
tar -zxf php-7.2.10.tar.gz php-7.2.10
# 依赖
apt -y install \
build-essential \
gcc \
g++ \
autoconf \
libiconv-hook-dev \
libmcrypt-dev \
libxml2-dev \
libmysqlclient-dev \
libcurl4-openssl-dev \
libjpeg8-dev \
libfreetype6-dev \
libssl-dev
# 编译
./configure --prefix=/usr/local/php7.2 \
--with-config-file-path=/etc/php7.2 \
--enable-fpm \
--enable-pcntl \
--enable-mysqlnd \
--enable-opcache \
--enable-sockets \
--enable-sysvmsg \
--enable-sysvsem \
--enable-sysvshm \
--enable-shmop \
--enable-zip \
--enable-soap \
--enable-xml \
--enable-mbstring \
--disable-rpath \
--disable-debug \
--disable-fileinfo \
--with-mysqli=mysqlnd \
--with-pdo-mysql=mysqlnd \
--with-pcre-regex \
--with-iconv \
--with-zlib \
--with-gd \
--with-openssl \
--with-mhash \
--with-xmlrpc \
--with-curl \
--with-imap-ssl
# 安装
make && make install
# 输出
Build complete.
Don't forget to run 'make test'.
Installing shared extensions: /usr/local/php7.2/lib/php/extensions/no-debug-non-zts-20170718/
Installing PHP CLI binary: /usr/local/php7.2/bin/
Installing PHP CLI man page: /usr/local/php7.2/php/man/man1/
Installing PHP FPM binary: /usr/local/php7.2/sbin/
Installing PHP FPM defconfig: /usr/local/php7.2/etc/
Installing PHP FPM man page: /usr/local/php7.2/php/man/man8/
Installing PHP FPM status page: /usr/local/php7.2/php/php/fpm/
Installing phpdbg binary: /usr/local/php7.2/bin/
Installing phpdbg man page: /usr/local/php7.2/php/man/man1/
Installing PHP CGI binary: /usr/local/php7.2/bin/
Installing PHP CGI man page: /usr/local/php7.2/php/man/man1/
Installing build environment: /usr/local/php7.2/lib/php/build/
Installing header files: /usr/local/php7.2/include/php/
Installing helper programs: /usr/local/php7.2/bin/
program: phpize
program: php-config
Installing man pages: /usr/local/php7.2/php/man/man1/
page: phpize.1
page: php-config.1
Installing PEAR environment: /usr/local/php7.2/lib/php/
[PEAR] Archive_Tar - installed: 1.4.3
[PEAR] Console_Getopt - installed: 1.4.1
[PEAR] Structures_Graph- installed: 1.1.1
[PEAR] XML_Util - installed: 1.4.2
[PEAR] PEAR - installed: 1.10.5
Wrote PEAR system config file at: /usr/local/php7.2/etc/pear.conf
You may want to add: /usr/local/php7.2/lib/php to your php.ini include_path
/home/vps/php-7.2.10/build/shtool install -c ext/phar/phar.phar /usr/local/php7.2/bin
ln -s -f phar.phar /usr/local/php7.2/bin/phar
Installing PDO headers: /usr/local/php7.2/include/php/ext/pdo/
# 配置
mkdir /etc/php7.2
cp php.ini-development /etc/php7.2/php.ini
export PATH=/usr/local/php7.2/bin:$PATH
export PATH=/usr/local/php7.2/sbin:$PATH
source ~/.bashrc
# 测试
php -v
当解析一个文件时,PHP 会寻找起始和结束标记,也就是 <?php 和 ?>
,这告诉 PHP 开始和停止解析二者之间的代码。此种解析方式使得 PHP 可以被嵌入到各种不同的文档中去,而任何起始和结束标记之外的部分都会被 PHP 解析器忽略。
# 纯php文件
<?php echo "Hello World!";
# 嵌入html中的php文件
<p><?php echo "Hello World!"; ?></p>
PHP 支持 9 种原始数据类型。
四种标量类型:
- boolean(布尔型)
- integer(整型)
- float(浮点型,也称作 double)
- string(字符串)
三种复合类型:
- array(数组)
- object(对象)
- callable(可调用)
最后是两种特殊类型:
- resource(资源)
- NULL(无类型)
注意事项:
- var_dump($0x1A) //int(26) 16进制
- var_dump($9223372036854775808) //float(9.2233720368548E+18) 整数溢出自动转换成float
- var_dump(25/7) // float(3.5714285714286) PHP中没有整除的运算符
- var_dump((int) (25/7)) // int(3) 舍弃小数部分转换为int
- var_dump(round(25/7)) // float(4) 四舍五入
Heredoc结构 和 Nowdoc结构
- Heredoc结构类似于双引号字符串,Nowdoc结构是类似于单引号字符串
# Heredoc结构
<?php
$s = 'yy';
$str = <<<"EOD"
$s
EOD;
var_dump($str);
输出:string(2) "yy"
# Nowdoc结构
<?php
$s = 'yy';
$str = <<<'EOD'
$s
EOD;
var_dump($str);
输出:string(2) "$s"
PHP中的数组实际上是一个有序映射。映射是一种把 values 关联到 keys 的类型。此类型在很多方面做了优化,因此可以把它当成真正的数组,或列表(向量),散列表(是映射的一种实现),字典,集合,栈,队列以及更多可能性。由于数组元素的值也可以是另一个数组,树形结构和多维数组也是允许的。
key 可以是 integer 或者 string。value 可以是任意类型。此外 key 会有如下的强制转换:
- 包含有合法整型值的字符串会被转换为整型。例如键名 "8" 实际会被储存为 8。但是 "08" 则不会强制转换,因为其不是一个合法的十进制数值。
- 浮点数也会被转换为整型,意味着其小数部分会被舍去。例如键名 8.7 实际会被储存为 8。
- 布尔值也会被转换成整型。即键名 true 实际会被储存为 1 而键名 false 会被储存为 0。
- Null 会被转换为空字符串,即键名 null 实际会被储存为 ""。
- 数组和对象不能被用为键名。坚持这么做会导致警告:Illegal offset type。
栗子:类型强制与覆盖
<?php
$arr = [
1 => "a",
"1" => "b",
1.5 => "c",
true => "d",
];
var_dump($arr);
输出:array(1) {
[1]=>
string(1) "d"
}
?>
栗子:将目录中的文件名填充入数组
<?php
$handle = opendir('.');
while (false !== ($file = readdir($handle))) {
$files[] = $file;
}
closedir($handle);
empty()
更符合我们的需求
<?php
// 静态变量只在第一次调用函数时被初始化
function test()
{
static $a = 0;
echo $a;
$a++;
}
test(); // 0
test(); // 1
test(); // 2
define("CONSTANT", "hello world")
const CONSTANT = 'Hello World'
__LINE__
文件中的当前行号__FILE__
文件的完整路径和文件名__DIR__
文件所在的目录dirname(__FILE__)
__FUNCTION__
函数名称__CLASS__
类的名称__TRAIT__
Trait 的名字__METHOD__
类的方法名__NAMESPACE__
当前命名空间的名称
略
<?php
// $a % $b 的结果和 $a 的符号相同
echo (5 % 3)."\n"; // prints 2
echo (5 % -3)."\n"; // prints 2
echo (-5 % 3)."\n"; // prints -2
echo (-5 % -3)."\n"; // prints -2
略
<?php
// php5.6+
function sum(...$numbers) {
$acc = 0;
foreach ($numbers as $n) {
$acc += $n;
}
return $acc;
}
echo sum(1, 2, 3, 4); //10
// php5.5
<?php
function sum() {
$acc = 0;
foreach (func_get_args() as $n) {
$acc += $n;
}
return $acc;
}
echo sum(1, 2, 3, 4); //10
<?php
$greet = function($name)
{
printf("Hello %s\n", $name);
};
$greet('World');
$greet('PHP');
类的基本概念:class
,new
,extends
,::class
属性和方法:public
,protected
,private
类常量:self
,parent
,static
自动加载:spl_autoload_register()
构造函数和析构函数:__construct()
,__destruct()
范围解析操作符:::
抽象类:abstract
对象接口:interface
,implements
Trait:trait
重载:__set()
,__get()
,__isset()
,__unset()
,__call()
,__callStatic()
魔术方法:__toString()
,__invoke()
Final:final
对象复制:clone
后期静态调用:解决了单例继承类的应用
<?php
class A {
public static function foo() {
static::who(); // 后期静态调用
}
public static function who() {
echo __CLASS__."\n";
}
}
class B extends A {
public static function test() {
A::foo(); //非转发
parent::foo(); //转发
self::foo(); //转发
}
public static function who() {
echo __CLASS__."\n";
}
}
class C extends B {
public static function who() {
echo __CLASS__."\n";
}
}
C::test();
输出:
A
C
C
序列化:serialize()
,unserialize()
命名空间是一种封装事物的方法
概述:namespace
,use
,as
try {
$a = 10;
if ($a !== '10') {
throw new \Exception('垃圾');
}
} catch (\Exception $e) {
echo $e->getMessage() . "\n";
} finally {
echo "结束\n";
}
yield
// 类似range(),100w数据占用内存不到1kb,而range()在php7.2下面需要占用32mb
function xRange($start, $limit, $step = 1)
{
if ($start < $limit) {
if ($step <= 0) {
throw new \LogicException('Step must be +ve');
}
for ($i = $start; $i <= $limit; $i += $step) {
yield $i;
}
} else {
if ($step >= 0) {
throw new \LogicException('Step must be -ve');
}
for ($i = $start; $i >= $limit; $i += $step) {
yield $i;
}
}
}
&
// $a 和 $b 在这里是完全相同的,这并不是 $a 指向了 $b 或者相反,而是 $a 和 $b 指向了同一个地方。
<?php
$a = &$b;
// 通过引用修改变量的值
<?php
function foo(&$var)
{
$var++;
}
$a=5;
foo($a);
echo $a; //6
$this
:在一个对象的方法中,$this
永远是调用它的对象的引用。
global
:$var = &$GLOBALS["var"]
unset $var 不会 unset 全局变量。
- $GLOBALS
- $_SERVER http://php.net/manual/zh/reserved.variables.server.php
- $_GET
- $_POST
- $_FILES
- $_COOKIE
- $_SESSION
- $_REQUEST
- $_ENV
- $argc
- $argv
// 迭代对象
Iterator extends Traversable {
/* 方法 */
abstract public mixed current ( void )
abstract public scalar key ( void )
abstract public void next ( void )
abstract public void rewind ( void )
abstract public bool valid ( void )
}
// 对象能像数组一样访问
ArrayAccess {
/* 方法 */
abstract public boolean offsetExists ( mixed $offset )
abstract public mixed offsetGet ( mixed $offset )
abstract public void offsetSet ( mixed $offset , mixed $value )
abstract public void offsetUnset ( mixed $offset )
}
stream_context_create
,file_get_contents
,curl
$result = [];
//无键值对
array_walk_recursive($arr, function($value) use (&$result) {
array_push($result, $value);
});
//有键值对
array_walk_recursive($arr, function($value) use (&$result) {
array_push($result, array_values($value));
});
2、Laravel中Model的$visible
,$hidden
原理
array_intersect_key():使用键名比较计算数组的交集
array_flip():交换数组中的键和值
array_diff_key():使用键名比较计算数组的差集
protected function getArrayableItems(array $values)
{
if (count($this->getVisible()) > 0) {
$values = array_intersect_key($values, array_flip($this->getVisible()));
}
if (count($this->getHidden()) > 0) {
$values = array_diff_key($values, array_flip($this->getHidden()));
}
return $values;
}
按phpinfo()上的扩展解读
扩展库 | 作用 |
---|---|
date | 时间库 |
dom/xml/SimpleXML/libxml | xml操作库 |
exif | 相机库 |
fileinfo | 文件相关库 |
filter | 参数过滤库 |
ftp | ftp库 |
gd | 图像库 |
hash | hash算法库 |
iconv | 字符串转换库 |
imagick | 图像库 |
json | json操作库 |
mbstring | 多字节字符串操作库 |
memcached | 缓存库 |
mongodb | 数据库 |
mysqli | 数据库 |
mysqlnd | 数据库 |
openssl | 加密库 |
pcre | 正则库 |
PDO | 数据库 |
Phar | 包 |
posix | 多进程库 |
readline | 交互库 |
redis | 缓存库 |
Reflection | 反射库 |
session | 会话库 |
SPL | 标准库 |
swoole | 异步库 |
tokenizer | 标记库 |
xdebug | debug库 |
Zend OPcache | 缓存库 |
zlib | 压缩库 |
核心函数:spl_autoload_register()
- 使用类之前无需
include / require
- 使用类的时候才会
include / require
文件,实现了lazy loading(延迟加载)
,避免了include / require
多余文件。 - 无需考虑引入 类的实际磁盘地址 ,实现了逻辑和实体文件的分离。
以Laravel框架为例
目录结构:
vendor
├── autoload.php 入口文件
vendor/composer
├── ClassLoader.php composer加载类
├── autoload_classmap.php 自动加载的最简单形式
├── autoload_files.php 用于加载全局函数的文件
├── autoload_namespaces.php 符合PSR0标准的自动加载文件
├── autoload_psr4.php 符合PSR4标准的自动加载文件
├── autoload_real.php composer加载类的初始化
├── autoload_static.php 顶级命名空间初始化类
├── installed.json 所有的依赖库信息
第一步:public/index.php
入口文件直接引入
require __DIR__.'/../vendor/autoload.php';
第二步:vendor/autoload.php
引入
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderIniteaa4bfcc04fea23ae4b766b783b56134::getLoader();
第三步:vendor/composer/autoload_real.php
public static function getLoader()
{
/*********************** 单例模式 ********************/
if (null !== self::$loader) {
return self::$loader;
}
/*********************** 获得自动加载核心类对象 ********************/
spl_autoload_register(array('ComposerAutoloaderIniteaa4bfcc04fea23ae4b766b783b56134', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderIniteaa4bfcc04fea23ae4b766b783b56134', 'loadClassLoader'));
/*********************** 初始化自动加载核心类对象 ********************/
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
// 静态初始化
if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticIniteaa4bfcc04fea23ae4b766b783b56134::getInitializer($loader));
} else {
// 调用核心类接口初始化
// PSRO使用命名空间第一个字母作为前缀索引
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
// PSR4标准顶级命名空间映射用了两个数组,第一个和 PSR0 一样用命名空间第一个字母作为前缀索引,然后是 顶级命名空间,
// 但是最终并不是文件路径,而是 顶级命名空间 的长度。
// 可以将命名空间 Symfony\\Polyfill\\Mbstring\\example 前26个字符替换成目录 __DIR__ . '/..' .
// '/symfony/polyfill-mbstring ,我们就得到了__DIR__ . '/..' . '/symfony/polyfill-mbstring/example.php,
// 先验证磁盘上这个文件是否存在,如果不存在接着遍历。如果遍历后没有找到,则加载失败。
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
/*********************** 注册自动加载核心类对象 ********************/
$loader->register(true);
/*********************** 自动加载全局函数 ********************/
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticIniteaa4bfcc04fea23ae4b766b783b56134::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequireeaa4bfcc04fea23ae4b766b783b56134($fileIdentifier, $file);
}
// 返回自动加载核心类对象
return $loader;
}
public static function getInitializer(ClassLoader $loader)
{
// 匿名函数绑定
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticIniteaa4bfcc04fea23ae4b766b783b56134::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticIniteaa4bfcc04fea23ae4b766b783b56134::$prefixDirsPsr4;
$loader->fallbackDirsPsr4 = ComposerStaticIniteaa4bfcc04fea23ae4b766b783b56134::$fallbackDirsPsr4;
$loader->prefixesPsr0 = ComposerStaticIniteaa4bfcc04fea23ae4b766b783b56134::$prefixesPsr0;
$loader->classMap = ComposerStaticIniteaa4bfcc04fea23ae4b766b783b56134::$classMap;
}, null, ClassLoader::class);
}