首页
关于
Search
1
给你10个市场数据调研报告的免费下载网站!以后竞品数据就从这里找!
184 阅读
2
php接口优化 使用curl_multi_init批量请求
144 阅读
3
《从菜鸟到大师之路 ElasticSearch 篇》
107 阅读
4
2024年备考系统架构设计师
104 阅读
5
PHP 文件I/O
92 阅读
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
登录
Search
标签搜索
php函数
php语法
性能优化
安全
错误和异常处理
问题
vue
Composer
Session
缓存
框架
Swoole
api
并发
异步
正则表达式
php-fpm
mysql 索引
开发规范
协程
dafenqi
累计撰写
786
篇文章
累计收到
33
条评论
首页
栏目
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
副业
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
页面
关于
搜索到
560
篇与
的结果
2023-08-09
Composer概述及其自动加载探秘
Composer概述及其自动加载探秘composer概述一开始,最吸引我的当属 Composer 了,因为之前从没用过 Composer 。Composer 是PHP中用来管理依赖关系的工具,你只需在自己的项目中声明所依赖的外部工具库,Composer就会帮你安装这些依赖的库文件。运行 Composer 需要 PHP 5.3.2+ 以上版本。使用composer第一步,声明依赖关系。比方说,你正在创建的一个项目需要一个库来做日志记录。你决定使用 monolog。为了将它添加到你的项目中,你所需要做的就是创建一个 composer.json 文件,其中描述了项目的依赖关系。{"require": { "monolog/monolog": "1.2.*" }}第二步,使用composer。在项目根目录,执行安装命令,执行完毕后,monolog就会被下载到vendor/monolog/monolog 目录。$ php composer.phar install第三步,类的自动加载。除了库的下载,Composer 还准备了一个自动加载文件,它可以加载 Composer 下载的库中所有的类文件。使用它,你只需要将下面这行代码添加到你项目的引导文件中:require 'vendor/autoload.php';这使得你可以很容易的使用第三方代码。例如:如果你的项目依赖 monolog,你就可以像这样开始使用这个类库,并且他们将被自动加载。$log = new Monolog\Logger('name');$log->pushHandler(new Monolog\Handler\StreamHandler('app.log', Monolog\Logger::WARNING));$log->addWarning('Foo');Composer 自动加载探秘在现实世界中使用工具时,如果理解了工具的工作原理,使用起来就会更加有底气。对于一个第一次接触laravel,且是第一次接触 composer 的新手来说,如果理解Composer 是如何工作的,使用起来将会更加自如。我的理解是,composer 根据声明的依赖关系,从相关库的 源 下载代码文件,并根据依赖关系在 Composer 目录下生成供类自动加载的 PHP 脚本,使用的时候,项目开始处引入 “/vendor/autoload.php” 文件,就可以直接实例化这些第三方类库中的类了。那么,Composer 是如何实现类的自动加载的呢?接下来,我们从 laravel 的入口文件开始顺藤摸瓜往里跟进,来一睹 Composer 自动加载的奥妙。1.代码清单 laravel/public/index.php复制代码laravel/public/index.phprequire __DIR__.'/../bootstrap/autoload.php';$app = require_once __DIR__.'/../bootstrap/start.php';$app->run();复制代码第一行先是引入了 laravel/bootstrap/autoload.php,不做解释,打开该文件。2.代码清单 laravel/bootstrap/autoload.php复制代码define('LARAVEL_START', microtime(true));require __DIR__.'/../vendor/autoload.php';if (file_exists($compiled = __DIR__.'/compiled.php')){require $compiled;}Patchwork\Utf8\Bootup::initMbstring();复制代码第一行定义了程序开始执行的时间点。紧接着第二行,引入了 laravel/vendor/autoload.php。第七行,前面说过,引入Composer的autoload.php之后就可以直接使用第三方类库中的类了,这里就是直接使用的 Bootup 类。下面来看看 /vendor/autoload.php 到底做了什么。3.代码清单 laravel/vendor/autoload.php1 // autoload.php @generated by Composer2 3 require_once DIR . '/composer' . '/autoload_real.php';4 5 return ComposerAutoloaderInit9b2a1b1cf01c9a870ab98748dc5f1256::getLoader();到这里,马上就进入自动加在的大门了。这个文件很简单,第5行的函数名是不是看的一头雾水?别被吓到了,他就是个类名而已。这个类是在第3行引入的文件 laravel/vendor/composer/autoload_real.php 里头声明的,接下来打开该文件看 getLoader();4.代码清单laravel/vendor/composer/autoload_real.php复制代码 1 <?php 2 3 // autoload_real.php @generated by Composer 4 5 class ComposerAutoloaderInit9b2a1b1cf01c9a870ab98748dc5f1256 6 { 7 private static $loader; 8 9 public static function loadClassLoader($class)10 {11 if ('Composer\Autoload\ClassLoader' === $class) {12 require DIR . '/ClassLoader.php';13 }14 }15 16 17 public static function getLoader()18 {19 if (null !== self::$loader) {20 return self::$loader;21 }22 23 spl_autoload_register(array('ComposerAutoloaderInit9b2a1b1cf01c9a870ab98748dc5f1256', 'loadClassLoader'), true, true);24 self::$loader = $loader = new \Composer\Autoload\ClassLoader();25 spl_autoload_unregister(array('ComposerAutoloaderInit9b2a1b1cf01c9a870ab98748dc5f1256', 'loadClassLoader'));26 27 $vendorDir = dirname(__DIR__); 28 $baseDir = dirname($vendorDir);29 30 $includePaths = require DIR . '/include_paths.php'; 31 32 array_push($includePaths, get_include_path());33 set_include_path(join(PATH_SEPARATOR, $includePaths));34 35 36 $map = require DIR . '/autoload_namespaces.php';37 foreach ($map as $namespace => $path) {38 $loader->set($namespace, $path);39 }40 41 $map = require DIR . '/autoload_psr4.php';42 foreach ($map as $namespace => $path) {43 $loader->setPsr4($namespace, $path);44 }45 46 $classMap = require DIR . '/autoload_classmap.php';47 if ($classMap) {48 $loader->addClassMap($classMap);49 }50 51 52 $loader->register(true);53 54 $includeFiles = require DIR . '/autoload_files.php';55 foreach ($includeFiles as $file) {56 composerRequire9b2a1b1cf01c9a870ab98748dc5f1256($file);57 }58 59 return $loader;60 }61 }62 63 function composerRequire9b2a1b1cf01c9a870ab98748dc5f1256($file)及 $loader->addClassMap()64 {65 require $file;66 }复制代码第17行,getLoader()中先是判断当前类中的 $loader 值,如果不是 null 就返回,这个可以略过。接着实例化了 ClassLoader 类给 $loader ,laravel/vendor/composer/ClassLoader.php这里引入了几个文件,这些文件是由composer自动生成的,当依赖关系发生改变时不需要修改这些脚本,运行composer重新生成即可。laravel/vendor/composer/autoloade_namespace.phplaravel/vendor/composer/autoloade_prs4.phplaravel/vendor/composer/autoloade_classmap.phplaravel/vendor/composer/autoloade_files.php在设置完一堆的 path 信息后,执行了$loader->set()和 $loader->setPsr4()及$loader->addClassMap(),然后 进行了$loader->register(true);现在我们一个个来看。5.代码清单laravel/vendor/composer/ClassLoader.phpView Code$loader->set($namespace, $path);Psr0标准设置命名空间对应的路径,以便于随后自动加载相关类文件。$loader->setPsr4($namespace, $path);Psr4标准设置命名空间对应的路径,以便于随后自动加载相关类文件。$loader->addClassMap($classMap);设置类文件路径与类名的对应关系,以便于随后自动加载相关类文件。$loader->register(true);public function register($prepend = false){spl_autoload_register(array($this, 'loadClass'), true, $prepend);}这里设置了 欲注册的自动装载函数 $this->loadClass(),关于 spl_autoload_register和 spl_autoload_unregister 的更多信息随后会有专门的解释。现在打开loadClass()的定义复制代码public function loadClass($class){if ($file = $this->findFile($class)) { includeFile($file); return true; }}复制代码这里有个 findFile() 函数,如果相关类的声明所在文件的路径找到了,就包含并运行该文件,然后返回 true 。接着打开findFile()的定义复制代码public function findFile($class){// work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 if ('\\' == $class[0]) { $class = substr($class, 1); } // class map lookup if (isset($this->classMap[$class])) { return $this->classMap[$class]; } $file = $this->findFileWithExtension($class, '.php'); // Search for Hack files if we are running on HHVM if ($file === null && defined('HHVM_VERSION')) { $file = $this->findFileWithExtension($class, '.hh'); } if ($file === null) { // Remember that this class does not exist. return $this->classMap[$class] = false; } return $file;}复制代码先是判断类名是否以'\'开始,如果是的话,清除开头的'\'接着,检查当前类的名字是否在 类名与声明当前类的文件的路径的关系数组 中,如果存在,直接返回相关键值(类文件路径信息)如果上一步没有返回路径信息,执行 findFileWithExtension($class, '.php') 继续查找类文件路径信息,findFileWithExtension的定义后面将会列出。如果仍未找到类的文件路径信息,返回值为 null 且定义了 HHVM_VERSION 信息,则用“.hh”后缀继续查找类文件信息。HHVM_VERSION 是 HHVM版本信息? HHVM 是 Facebook 开发的高性能 PHP 虚拟机,宣称比官方的快9倍。如果仍未找到,则返回 false 。Remember that this class does not exist.(这句注释很有喜感?哈哈)代码清单 findFileWithExtension()复制代码 1 private function findFileWithExtension($class, $ext) 2 { 3 // PSR-4 lookup 4 $logicalPathPsr4 = strtr($class, '\', DIRECTORY_SEPARATOR) . $ext; 5 6 $first = $class[0]; 7 if (isset($this->prefixLengthsPsr4[$first])) { 8 foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { 9 if (0 === strpos($class, $prefix)) {10 foreach ($this->prefixDirsPsr4[$prefix] as $dir) {11 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {12 return $file;13 }14 }15 }16 }17 }18 19 // PSR-4 fallback dirs20 foreach ($this->fallbackDirsPsr4 as $dir) {21 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {22 return $file;23 }24 }25 26 // PSR-0 lookup27 if (false !== $pos = strrpos($class, '\')) {28 // namespaced class name29 $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)30 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);31 } else {32 // PEAR-like class name33 $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;34 }35 36 if (isset($this->prefixesPsr0[$first])) {37 foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {38 if (0 === strpos($class, $prefix)) {39 foreach ($dirs as $dir) {40 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {41 return $file;42 }43 }44 }45 }46 }47 48 // PSR-0 fallback dirs49 foreach ($this->fallbackDirsPsr0 as $dir) {50 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {51 return $file;52 }53 }54 55 // PSR-0 include paths.56 if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {57 return $file;58 }59 }复制代码该函数唯一的目的就是根据刚才通过$loader->set($namespace, $path)和$loader->setPsr4($namespace, $path)方法设置的信息找出类文件的路径信息。接下来,我们回到代码清单laravel/vendor/composer/autoload_real.php ,为精简篇幅,这里只贴出片段(续上节的 $loader->register(true))。复制代码 $loader->register(true); $includeFiles = require __DIR__ . '/autoload_files.php'; foreach ($includeFiles as $file) { composerRequire9b2a1b1cf01c9a870ab98748dc5f1256($file); } return $loader; }}function composerRequire9b2a1b1cf01c9a870ab98748dc5f1256($file){require $file;}复制代码在经历了一番长途跋涉后,终于从 laravel/vendor/composer/ClassLoader.php 中出来了。继 $loader->register(true) 之后,又引入了laravel/vendor/composer/autoload_files.php,相比之下,这个文件要简单得多,只是个数组,列出了几个文件路径。复制代码// autoload_files.php @generated by Composer$vendorDir = dirname(dirname(__FILE__));$baseDir = dirname($vendorDir);return array($vendorDir . '/ircmaxell/password-compat/lib/password.php', $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php', $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Random.php', $vendorDir . '/laravel/framework/src/Illuminate/Support/helpers.php',);复制代码接着就是用 composerRequire9b2a1b1cf01c9a870ab98748dc5f1256() 函数 包含并运行 这几个文件。这四个文件的具体信息,随后会专门写博文来认识。最后 , 返回 ClassLoader 类的实例 $loader 。现在在回到 代码清单 laravel/bootstrap/autoload.php 的第7行复制代码1 define('LARAVEL_START', microtime(true));2 require __DIR__.'/../vendor/autoload.php';3 if (file_exists($compiled = __DIR__.'/compiled.php'))4 {5 require $compiled;6 }7 Patchwork\Utf8\Bootup::initMbstring();复制代码注意这里第7行,之所以可以直接像 Patchwork\Utf8\Bootup::initMbstring() 这么使用而不需要手动required Bootup类文件,是因为 前面在ClassLoader中的register() 函数用 spl_autoload_register() 对Bootup类进行了注册。下面说一下 spl_autoload_register 。spl_autoload_register要使用 spl_autoload_register ,请保证你的PHP版本(PHP 5 >= 5.1.2)。www.php.net 对 spl_autoload_register 的解释如下:注册__autoload()函数,将函数注册到SPL __autoload函数栈中。如果该栈中的函数尚未激活,则激活它们。刚接触 PHP 的同学肯定觉得这个解释云里雾里的,看完依然不知道什么意思。要想理解这句话,首先要弄明白 __autoload() 是个什么东西。__autoload()__autoload 的作用是尝试加载未定义的类,可以通过定义这个函数来启用类的自动加载。下面举个例子:复制代码function __autoload($class){echo '尝试加载的类的名字是:'.$class;}$say= @ new say();复制代码上例会输出:"尝试加载的类的名字是 say "。由于最后一行引用了尚未定义的类 box ,所以 __autoload 函数将被执行。再看下面这段复制代码class say{public function __construct() { echo 'say 类存在,并说出了hello,所以 __autoload 函数不会执行。'; }}function __autoload($class){echo '尝试加载的类的名字是:'.$class;}$say= @ new say();复制代码这将会输出 : say 类存在,并说出了hello,所以 __autoload 函数不会执行。理解完 __autoload 就好办了,再看上面:“将函数注册到SPL __autoload函数栈中”,意思是我们可以自定义 尝试加载未定义的类时 使用的函数。现在返回代码片段spl_autoload_register(array($this, 'loadClass'), true, $prepend);这下是不是很明白了,当实例化一个类的时候,如果这个类没有定义,就执行 ClassLoader 类中的 loadClass 函数。loadClass 的定义前面我们说过了,就是找到声明相关类的文件,然后包含并运行该文件,随后加载相关类。至此,composer的自动加载机制学习完毕。
2023年08月09日
14 阅读
0 评论
0 点赞
2023-08-09
const与define的区别
PHP源码解读:const与define的区别php中const define区别有哪些
2023年08月09日
13 阅读
0 评论
0 点赞
2023-08-09
php 跨域 form提交 2种方法
php 跨域 form提交 2种方法出于安全因素考虑,直接跨域访问是不允许的,下面介绍二种跨域的方法。一,通过php curlfunction curlPost($url,$params) { $postData = ''; foreach($params as $k => $v) { $postData .= $k . '='.$v.'&'; } rtrim($postData, '&'); $ch = curl_init(); curl_setopt($ch,CURLOPT_URL,$url); curl_setopt($ch,CURLOPT_RETURNTRANSFER,true); curl_setopt($ch,CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_POST, count($postData)); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); $output=curl_exec($ch); curl_close($ch); return $output; } echo curlPost("http://test.com",array('name'=>"tank"));以前很多人用curl来抓,邮箱的通讯录,不过现在已经不可以了。哈哈。二,利用jquery form,ajax提交1,下载jquery.form.js2,js代码$('#testform').submit(function() { $(this).ajaxSubmit({ type: 'post', // 提交方式 get/post dataType:"json",//数据类型 url: 'your url', // 需要提交的 url success: function(data) { // data 保存提交后返回的数据,一般为 json 数据 // 此处可对 data 作相关处理 alert('提交成功!'); } $(this).resetForm(); // 提交后重置表单 }); return false; // 阻止表单自动提交事件 });3,php代码header("Access-Control-Allow-Origin:*"); //跨域权限设置,允许所有 header("Access-Control-Allow-Origin:http://www.test.com"); //只允许test.com跨域提交数据
2023年08月09日
8 阅读
0 评论
0 点赞
2023-08-09
PHP basename()函数用法详解
PHP basename()函数用法详解PHP中的basename()函数是一个非常有用的函数,用来获取指定路径中的文件名部分。这里就来详细介绍一下PHP basename()函数的用法。一、函数原型basename ( string $path , string $suffix ) : string二、函数参数$path:需要获取文件名的路径字符串。可以是相对路径或绝对路径。$suffix:可选,如果文件名以$suffix结尾,则此部分会被去掉。三、函数返回值basename()函数的返回值是指定路径下的文件名。如果有$suffix参数,则删除文件名中以$suffix结尾的部分。四、函数示例在下面的示例中,我们将使用以下路径:/var/www/html/test.txt获取文件名echo basename('/var/www/html/test.txt'); // 输出:test.txt删除文件扩展名echo basename('/var/www/html/test.txt', '.txt'); // 输出:test获取当前路径下的文件名echo basename(__FILE__); // 输出:basename.php获取文件夹名$dir = dirname('/var/www/html/test.txt');echo basename($dir); // 输出:html五、注意事项如果路径是以斜杠(/)结尾,则返回空字符串。例如:echo basename('/var/www/html/'); // 输出:''如果路径是"."或"..",则返回相应的文件名字符串。echo basename('.'); // 输出:'.'echo basename('..'); // 输出:'..'$suffix参数是区分大小写的。例如:echo basename('/var/www/html/test.TXT', '.txt'); // 输出:test.TXT如果给定路径不是文件夹或文件,则返回false。echo basename('/var/www/html/test'); // 输出:test以上就是PHP basename()函数的详解。通过此函数,我们可以方便地获取文件名或文件夹名,并进行相应的操作。在实际开发过程中,我们也可以根据需要结合其他的函数和变量使用,以达到更加灵活和高效的效果。支持中文的basenamephp自带的basename函数不支持中文,下面这个方法是最简单的实现。function get_basename($filename){ return preg_replace('/^.+[\\\\\\/]/', '', $filename);}
2023年08月09日
13 阅读
0 评论
0 点赞
2023-08-09
利用 Composer 一步一步构建自己的 PHP 框架
PHP 命名空间 解惑利用 Composer 一步一步构建自己的 PHP 框架(一)——基础准备利用 Composer 一步一步构建自己的 PHP 框架(二)——构建路由利用 Composer 一步一步构建自己的 PHP 框架(三)——设计 MVC利用 Composer 一步一步构建自己的 PHP 框架(四)——使用 ORM利用 Composer 完善自己的 PHP 框架(一)——视图装载利用 Composer 完善自己的 PHP 框架(二)——发送邮件【完结】利用 Composer 完善自己的 PHP 框架(三)——Redis 缓存
2023年08月09日
10 阅读
0 评论
0 点赞
1
...
67
68
69
...
112