首页
关于
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
软件工程师需要了解的网络知识:从铜线到HTTP
软件工程师需要了解的网络知识:从铜线到HTTP(一)—— 前言软件工程师需要了解的网络知识:从铜线到HTTP(二)—— 以太网与交换机软件工程师需要了解的网络知识:从铜线到HTTP(三)—— TCP/IP软件工程师需要了解的网络知识:从铜线到HTTP(四)—— TCP 和路由器软件工程师需要了解的网络知识:从铜线到HTTP(五)—— HTTP 和 HTTPS
2023年08月09日
10 阅读
0 评论
0 点赞
2023-08-09
聊聊 PHP 私有组件以及如何创建自己的 PHP 组件
聊聊 PHP 私有组件以及如何创建自己的 PHP 组件1、私有组件大多数时候我们使用的都是公开可用的开源组件,但有时候如果公司使用内部开发的PHP组件,而基于许可证和安全方面的问题不能将其开源,就需要使用私有组件。对Composer而言,这是小菜一碟。Composer可用管理放在需要认证的仓库中的私有PHP组件,执行composer install或composer update命令时,如果组件的仓库需要认证凭据,Composer会提醒你需要输入认证信息,此外,Composer还会询问是否把仓库的认证凭据保存在本地的auth.json文件(和composer.json放在同一级)。下面是auth.json的内容示例:1{2 "http-basic": {3 "laravelacademy.org": {4 "username": "your-username",5 "password": "your-password"6 }7}8}auth.json最好不要放到版本控制中,我们要让项目的开发者自己创建auth.json文件,保存他们自己的认证凭据。如果不想傻傻的等待Composer向你询问认证凭据,可以使用下述命令手动告诉Composer远程设备的认证凭据:1composer config http-basic.laravelacademy.org your-username your-password在这个示例中,http-basic告诉Composer我们要为指定的域名添加认证信息。laravelacademy.org是主机名,用于识别存储私有组件仓库的设备,最后两个参数是用户名和密码。默认情况下,这个命令会在当前项目中的auth.json文件里保存凭据。你还可以使用--global标记在系统全局中保存认证凭据。使用这个标记设定认证凭据后,Composer会在本地设备中的所有项目里使用这个凭据。1composer config --global http-basic.laravelacademy.org your-username your-password全局凭据保存在~/.composer/auth.json中,如果你使用的是Windows系统,相应全局凭据保存在APPDATA%/Composer文件夹中。2、创建组件现在你应该知道怎么查找和使用PHP组件了,下面我们来讨论如何创建PHP组件。创建PHP组件是把工作成果分享给PHP社区成员的好方式,PHP社区乐于分享和帮助他人,如果你在应用中使用了开源组件,那么投桃报李,创建有创意的新开源组件是回报社区最好的方式。注:别重新编写已经存在的组件,如果是改进现有组件,可以在拉取请求中把改进发送给原本的组件,否则,PHP生态系统将充斥重复的组件。命名空间在设置命名空间之前,先要确定厂商名称和包名,即形如laravel/framework这样,要确保其全局唯一性,在Packagist中不存在。每个组件都有自己的命名空间,说到这里,人们常常误以为组件的命名空间必须与组件的厂商名和包名一致,其实不然,组件使用的命名空间与组件的厂商名和包名无关,厂商名和包名只是为了让Packagist和Composer识别组件,而组件的命名空间是为了在PHP代码中使用组件。文件系统结构PHP组件的文件系统结构基本上是确定的:src:这个目录用于存放组件的源代码tests:存放组件的测试代码composer.json:Composer配置文件,用于描述组件,声明组件依赖以及自动加载配置等README.md:这个Markdown文件提供关于组件的相关信息、使用文档说明、软件许可证等CONTRIBUTING.md:这个Markdown文件告知别人如何为这个组件做贡献LICENSE:纯文本文件,声明组件的软件许可证CHANGELOG.md:Markdown文件,列出组件在每个版本中引入的改动composer.jsonPHP组件中必须包含composer.json文件,而且这个文件的内容必须是有效的JSON,Composer会使用这个文件中的信息查找、安装和自动加载PHP组件。composer.json文件还包含组件在Packagist目录中的信息。我们新建一个组件目录(~/Packages/urlscanner),然后在urlscanner目录下通过如下命令生成composer.json文件:1composer init然后在终端会让我们按照提示向导一步步填写composer.json内容:commit-init最后回车,会生成相应的composer.json文件,我们对该文件作如下修改:1{2"name": "laravelacademy/urlscanner",3"description": "Scan URLs FROM A CSV FILE AND REPORT INACCESSIBLE URLs",4"keywords": ["url", "scanner", "csv"],5"homepage": "https://xueyuanjun.com",6"license": "MIT",7"authors": [8 {9 "name": "sunqiang",10 "email": "yaojinbu@163.com"11 }12],13"support": {14 "email": "yaojinbu@163.com"15},16"minimum-stability": "dev",17"require": {18 "php": ">=5.4.0",19 "guzzlehttp/guzzle": "~5.0"20},21"require-dev": {22 "phpunit/phpunit": "~4.3"23},24"suggest": {25 "league/csv": "~6.0"26},27"autoload": {28 "psr-4": {29 "LaravelAcademy\\UrlScanner\\": "src/"30 }31}32}我们来仔细研究一下这个文件,看看每个部分究竟是什么意思:name:组件的厂商名和包名,也是Packagist中的组件名description:简要说明组件keywords:描述属性的关键字homepage:组件网站URLlicense:PHP组件采用的软件许可证(更多软件许可证参考:http://choosealicense.com/)authors:作者信息数组support:组件用户获取技术支持的方式require:组件自身依赖的组件require-dev:开发这个组件所需的依赖suggest:建议安装的组件autoload:告诉Composer自动加载器如何自动加载这个组件READEME.md通常这个是用户最先阅读的文件,对托管在Github和Bitbucket中的组件来说,更是如此。标准的READEME.md文件至少提供以下信息:组件的名称和描述安装说明使用说明测试说明贡献方式支持资源作者信息软件许可证实现组件开始之前我们使用如下命令安装依赖:1composer install该命令会把依赖组件安装到vendor目录并生成自动加载器。现在我们要来实现组件的具体功能了。这一步我们要编写组成PHP组件的类、接口和Trait,编写什么类以及编写多少类完全取决于PHP组件的作用。不过组件中的所有类、接口和Trait都要放到src目录下。对这个组件来说我只需要创建一个类Scanner,位于子命名空间Url中,这个子命名空间位于composer.json文件中设定的LaravelAcademy/UrlScanner命名空间下,Scanner类保存在src/Url/Scanner.php文件。Scanner类实现的逻辑和上一节的URL扫描器示例应用相同,只不过现在我们要把扫描URL的功能封装在一个PHP类中:1<?php2namespace LaravelAcademy\UrlScanner\Url;34use GuzzleHttp\Client;56class Scanner7{8protected $urls;910protected $httpClient;1112public function __construct(array $urls)13{14 $this->urls = $urls;15 $this->httpClient = new Client();16}1718/**19 * 获取访问指定URL的HTTP状态码20 *21 * @param $url22 * @return int23 */24public function getStatusCodeForUrl($url)25{26 $httpResponse = $this->httpClient->get($url);27 return $httpResponse->getStatusCode();28}2930/**31 * 获取死链32 *33 * @return array34 */35public function getInvalidUrls()36{37 $invalidUrls = [];38 foreach ($this->urls as $url) {39 try {40 $statusCode = $this->getStatusCodeForUrl($url);41 } catch (\Exception $e) {42 $statusCode = 500;43 }4445 if ($statusCode >= 400) {46 array_push($invalidUrls, ['url' => $url, 'status' => $statusCode]);47 }48 }4950 return $invalidUrls;51}5253}我们没有解析并迭代处理一个CSV文件,而是把一个URL数组传递给Scanner类的构造函数,因为我们要尽量让这个扫描URL的类通用。如果直接处理CSV文件就限制了这个组件的用途。我们把获取URL的来源开放给用户,让他们自己从文件、数组亦或是CSV文件中获取。所以回到上面的composer.json,我们在suggest中声明了league/csv组件,只是建议安装,并不是必须安装。提交到Packagist我们先将代码提交到GitHub(注意将vendor目录添加到.gitignore)仓库(我的是nonfu/urlscanner):add-to-gitignore涉及到的git命令如下:1git init2git remote add origin https://github.com/nonfu/urlscanner.git3git add .4git commit -m “urlscanner"5git pull origin master6git push origin master这样就将本地组件提交到GitHub仓库:pull-to-github然后在Packagist中通过GitHub账户登录,通过https://packagist.org/packages/submit提交组件,在输入框中输入刚刚提交的GitHub仓库地址:submit-to-packagistcheck成功后点击submit即可将组件提交到Packagist:submit-to-packagist-success其中红色的警告的意思是需要我们通过GitHub Service Hook去GitHub中创建一个钩子,以后每次更新组件的GitHub仓库时通知Packagist。3、使用组件至此,我们已经成功将自己的组件提交到Packagist,现在任何人都可以使用Composer安装这个URL扫描器组件,然后在自己的PHP应用中使用。在终端执行如下命令安装这个组件:1composer require laravelacademy/urlscanner dev-mastercomposer-require-urlscanner然后在我们的代码中使用:<?phprequire “vendor/autoload.php”;$urls = [“https://xueyuanjun.com”, “http://laravel-academy.org”, “https://packagist.org"];$scanner = new \LaravelAcademy\UrlScanner\Url\Scanner($urls);print_r($scanner->getInvalidUrls());1<?php2require “vendor/autoload.php”;34$urls = [5“https://xueyuanjun.com”,6“http://laravel-academy.org”,7“https://packagist.org"8];910$scanner = new \LaravelAcademy\UrlScanner\Url\Scanner($urls);11print_r($scanner->getInvalidUrls());
2023年08月09日
8 阅读
0 评论
0 点赞
2023-08-09
漫谈 PHP 组件、框架、Composer 那些事
漫谈 PHP 组件、框架、Composer 那些事1、什么是组件组件是一组打包的代码,是一系列相关的类、接口和Trait,用于帮助我们解决PHP应用中某个具体问题。例如,你的PHP应用需要收发HTTP请求,可以使用现成的组件如guzzle/guzzle实现。我们使用组件不是为了重新实现已经实现的功能,而是把更多时间花在实现项目的长远目标上。优秀的PHP组件具备以下特性:作用单一:专注于解决一个问题,而且使用简单的接口封装功能小型:小巧玲珑,只包含解决某个问题所需的最少代码合作:PHP组件之间可以良好合作,组合在一起实现大型项目测试良好:本身提供测试,而且有充足的测试覆盖度文档完善:应该提供完善的文档,能让开发者轻易安装、理解和使用2、组件 vs 框架我们选择框架时,要为这个框架的工具投入很多,框架通常会提供大量工具,但却没有提供我们所需的某个工具时,痛苦就转嫁到我们头上,我们要寻找并集成自定义的PHP库。把第三方代码集成到框架中是件难事,因为第三方代码和框架可能没有使用相同的接口。选择框架时,我们看中的是框架的未来,但是谁又能保证某个框架始终是完成某项工作最好的工具呢?存在多年的大型项目必须有好的表现,而且要时刻做好调整,如果选错了PHP框架,可能无法做到这一点。较旧的PHP框架可能由于缺乏社区支持而变慢或过时,这些旧框架通常使用过程式代码编写,而没有使用新式的面向对象代码以及PHP的一些新特性,总之,决定是否使用PHP框架时,要考虑的事情很多。庆幸的是,Laravel在这些担忧方面表现良好,因此才能在众多PHP框架中脱颖而出,从某种意义上来说,Laravel也是个基于组件开发的框架(核心组件是自身的Illuminate库,功能实现上则大量依赖第三方组件),相比Symfony而言,上手又比较简单,所以兼具了扩展性和易用性。但是,Laravel也存在一些不足,比如Laravel自身的组件不能轻易解耦,用于Laravel框架之外(但是相信这种状况会有好转,比如其数据库和队列组件就可以解耦出去)。综合来看,Laravel仍是一个出色的框架,能帮组我们快速创建强大的应用。那我们应该使用组件还是框架呢?答案是,使用正确的工具做正确的事,如果能通过一些PHP组件快速实现小型项目,那就使用组件,如果有多个团队成员开发大型项目,而且能从框架提供的约定准则和结构中受益,那就使用框架(如果是在纠结使用什么框架,那么选择Laravel吧,它不会让你失望),使用框架能够引导并加速项目的开发。PS:这句话也适用于语言之争,用正确的语言做正确的事,没事少BB,这是学院君对语言之争的态度和立场。3、使用组件Packagist我们在Packagist中查找PHP组件,这个网站用于收集PHP组件,最好的PHP组件在Packagist中都能找到。Packagist比如我们想使用一个http组件用于收发HTTP消息,在搜索框中搜索http,得到的第一个结果就是Guzzle,就用它吧。ComposerPackagist是查找PHP组件的社区,Composer则是安装PHP组件的工具。Composer是PHP的依赖管理器,运行在命令行中,你告诉Composer需要哪些组件,Composer会下载并把这些组件自动加载到你的项目中,就这么简单。Composer和Packagist紧密合作,如果你告诉Composer想要使用guzzlehttp/guzzle组件,Composer会从Packagist中获取guzzlehttp/guzzle组件,找到这个组件的仓库地址,确定要使用哪个版本,还能找出这个组件的依赖,然后把guzzlehttp/guzzle组件及其依赖下载到你的项目中。此外,Composer会为项目中的所有PHP组件自动生成符合PSR标准的自动加载器,有效地抽象了依赖管理和自动加载,所以,对PHP社区来说,Composer是最重要的附加工具,没有之一,想想之前我们要使用诸如include、require、spl_autoload_register来手动实现自动加载的痛苦日子,这一点也不为过。关于Composer的安装和使用,这里不赘述,请参考Composer中文网。4、示例项目下面我们通过一个示例项目来演示如何使用Composer和组件来开发一个PHP应用,这个应用的作用是扫描一个CSV文件中的URL,找出死链,该应用会向每个URL发HTTP请求,如果返回的HTTP状态码大于等于400,就把这个死链发给标准输出。这是一个命令行应用,开发好之后,我们会执行这个脚本,传入csv文件的路径,在标准输出中显示死链列表。安装组件开始之前,先看看哪些任务可以使用现有的PHP组件解决:我们需要一个可以迭代处理csv文件数据的组件,此外还要向csv文件中的每个URL发送HTTP请求,因此还需要一个可以发送HTTP请求并检查HTTP响应的组件。浏览Packagist后,我们找到guzzlehttp/guzzle和league/csv两个组件,前者用于处理HTTP消息,后者用于处理CSV数据。下面我们在项目最顶层运行如下命令:1composer require guzzlehttp/guzzle2composer require league/csvComposer会将依赖安装到根目录的vendor目录下,安装完成后,会在根目录下生成composer.json和composer.lock文件:guzzlehttp+csvcomposer.lock文件中会列出项目使用的所有PHP组件,以及组件的具体版本号,这其实是锁定了项目,让项目只能使用具体版本的PHP组件。这样的好处是,composer会下载这个文件中列出的具体版本,而不管Packagist中可用的最新版本是多少,你应该把composer.lock文件纳入版本控制,这样让团队成员使用的PHP版本和你一样,如果本地开发和服务器使用的PHP组件版本相同,可以尽量降低由组件版本不同导致的bug。如果确实要下载最新版本的组件并更新composer.lock,可以使用composer update命令。自动加载接下来我们来编写应用代码,在根目录下创建一个scan.php文件,然后在该文件顶部使用require导入Composer创建的自动加载器:1<?php2require 'vendor/autoload.php';Composer创建的自动加载器其实就是个名为autoload.php的文件,保存在vendor目录中,Composer下载各个PHP组件时,会检查每个组件的composer.json文件,确定如何加载该组件,得到这个信息后,Composer会在本地为该组件创建一个符合PSR标准的自动加载器。这样我们就可以实例化项目中的任何PHP组件,这些组件按需自动加载。编写代码下面我们正式使用Guzzle和CSV组件编写scan.php代码:1<?php2//使用composer自动加载器3require 'vendor/autoload.php';45//实例Guzzle Http客户端6$client = new GuzzleHttp\Client();78//打开并迭代处理CSV9$csv = League\Csv\Reader::createFromPath($argv[1]);10foreach ($csv as $csvRow) {11try {12 //发送HTTP GET请求13 $httpResponse = $client->get($csvRow[0]);1415 //检查HTTP响应的状态码16 if($httpResponse->getStatusCode() >= 400) {17 throw new Exception();18 }19} catch (Exception $e) {20 //把死链发给标准输出21 echo $csvRow[0] . PHP_EOL;22}23}下面我们在urls.csv中添加一些URL,一行一个,而且至少有一个是死链:urls-csv然后打开终端,执行scan.php脚本:1php scan.php urls.csv我们传入了两个参数,第一个是脚本文件scan.php的路径,另一个是CSV文件的路径。输出如下:invalid-url下一节我们将探讨私有的PHP组件以及如何创建自己的PHP组件并上传到Packagist。
2023年08月09日
11 阅读
0 评论
0 点赞
2023-08-09
PHP & HTML5 文件夹上传
PHP & HTML5 文件夹上传拖拽上传文件夹到一个web应用程序。所以上传多个文件是一个有趣的了不起的进步。但是现在我提供给你 webkitdirectory !注意:这只会在一个最新的webkit的浏览器上运行。webkitdirectory目前不是标准 ,纯粹是为了玩。我不建议你在正式环境部署这个应用程序。I had the pleasure of having a little play around with this when I should have probablybeen working with processing for university but I do like to procrastinate。(此略)所以,干脆痛快:html 代码会员.jpg很简单,对吗?确实啊!上PHP代码。PHP 代码if($_FILES['file_input']){$uploads = UpFilesTOObj($_FILES['file_input']); $fileUploader=new FileUploader($uploads);}class FileUploader{public function __construct($uploads,$uploadDir='uploads/'){ foreach($uploads as $current) { $this->uploadFile=$uploadDir.$current->name.".".get_file_extension($current->name); if($this->upload($current,$this->uploadFile)){ echo "Successfully uploaded ".$current->name."n"; } } } public function upload($current,$uploadFile){ if(move_uploaded_file($current->tmp_name,$uploadFile)){ return true; } }}function UpFilesTOObj($fileArr){foreach($fileArr['name'] as $keyee => $info) { $uploads[$keyee]->name=$fileArr['name'][$keyee]; $uploads[$keyee]->type=$fileArr['type'][$keyee]; $uploads[$keyee]->tmp_name=$fileArr['tmp_name'][$keyee]; $uploads[$keyee]->error=$fileArr['error'][$keyee]; } return $uploads;}function get_file_extension($file_name){ return substr(strrchr($file_name,'.'),1);}我也一直在准备做MooTools脚本异步上传文件。所以请继续关注。我很高兴听到任何意见或建议。好运。更新:上传时保持目录结构 :所以最近我一直在玩很多新的文件API和一些图像处理等。在javascript中,我有巨大的乐趣这样做!我已经看到很多人问文件夹上传,这是一个令人兴奋的新发展。大多数人似乎有上传文件夹时保留文件结构的问题。在上传时是有可能保持文件夹的结构的。在写作时,我一直无法找到一个等价的不使用webkit的浏览器。这篇文章仅供测试!我正在写一个完整的AJAX文件夹上传脚本,但是我做时,我会去发一些我发现有趣的小代码片段。因此,闲话少说,上代码:未选择任何文件document.getElementById('files').onchange = function(e) { var files = e.target.files; // FileList for (var i = 0, f; f = files[i]; ++i)console.debug(files[i].webkitRelativePath);}检索路径是这么简单!这是一个工作示例:这是最基本的版本,将显示已提交的列表。fiddle是更复杂的比上面的代码让它不显示控制台什么的 。上传到服务器!事情开始变得稍微复杂,当我们上传这些到服务器时。我已经能够找到在撰写本文时,HTTP请求不支持上传时的变换文件路径。这可以很容易地通过我们自己添加它到请求数据解决。function uploadFiles(files){// Create a new HTTP requests, Form data item (data we will send to the server) and an empty string for the file paths. xhr = new XMLHttpRequest(); data = new FormData(); paths = ""; // Set how to handle the response text from the server xhr.onreadystatechange = function(ev){ console.debug(xhr.responseText); }; // Loop through the file list for (var i in files){ // Append the current file path to the paths variable (delimited by tripple hash signs - ###) paths += files[i].webkitRelativePath+"###"; // Append current file to our FormData with the index of i data.append(i, files[i]); }; // Append the paths variable to our FormData to be sent to the server // Currently, As far as I know, HTTP requests do not natively carry the path data // So we must add it to the request manually. data.append('paths', paths); // Open and send HHTP requests to upload.php xhr.open('POST', "upload.php", true); xhr.send(this.data);}This will simply create a triple hash delimited string which we will split into an array of file paths on the server which will correspond to our array of files。这将创建一个三重散列分隔的字符串,我们将分成数组服务器上的文件路径将对应于我们的一系列文件。0)$fileUploader = new FileUploader($_FILES); class FileUploader{public function __construct($uploads,$uploadDir='uploads/'){ // Split the string containing the list of file paths into an array $paths = explode("###",rtrim($_POST['paths'],"###")); // Loop through files sent foreach($uploads as $key => $current) { // Stores full destination path of file on server $this->uploadFile=$uploadDir.rtrim($paths[$key],"/."); // Stores containing folder path to check if dir later $this->folder = substr($this->uploadFile,0,strrpos($this->uploadFile,"/")); // Check whether the current entity is an actual file or a folder (With a . for a name) if(strlen($current['name'])!=1) // Upload current file if($this->upload($current,$this->uploadFile)) echo "The file ".$paths[$key]." has been uploadedn"; else echo "Error"; } } private function upload($current,$uploadFile){ // Checks whether the current file's containing folder exists, if not, it will create it. if(!is_dir($this->folder)){ mkdir($this->folder,0700,true); } // Moves current file to upload destination if(move_uploaded_file($current['tmp_name'],$uploadFile)) return true; else return false; }}?>进展这绝不是完美的,这是我一直在玩,并分享我的发现。我将会更新这篇文章当我有更多要发的东西。或者如果有特别令人兴奋的东西,我甚至可能发一篇新文章。所以现在,到这里下载源码 Folder-Upload-Structure-Sapphiondotcom
2023年08月09日
12 阅读
0 评论
0 点赞
2023-08-09
php 使用 ftp_nb_put() 来断点续传
php 使用 ftp_nb_put() 来断点续传<?php // 开始 $ret = ftp_nb_put ($my_connection, "test.remote", "test.local", FTP_BINARY, ftp_size("test.remote")); // 或: $ret = ftp_nb_put ($my_connection, "test.remote", "test.local", // FTP_BINARY, FTP_AUTORESUME); while ($ret == FTP_MOREDATA) { // 加入其它要执行的代码 echo "."; // 继续传送... $ret = ftp_nb_continue ($my_connection); } if ($ret != FTP_FINISHED) { echo "上传文件中发生错误..."; exit(1); } ?>
2023年08月09日
12 阅读
0 评论
0 点赞
1
...
68
69
70
...
112