github的辅助项目们

时常在github项目上看到类似下面这样的小标签,用于展示项目的一些信息。

今天稍微接触了一下这些(小)项目。目前还没有在blog上使用,过段时间会尝试一下。

Shields.io

提供高质量Github项目进度角标图片的API.shields.io 。引用起来也非常简单

<div id="container">
    <img src="http://progressed.io/bar/28?title=progress" alt="">
    <img src="http://progressed.io/bar/30?title=nice" alt="">
    <img src="http://progressed.io/bar/60?title=极客标签" alt="">
    <img src="https://img.shields.io/teamcity/http/teamcity.jetbrains.com/s/bt345.svg" alt="">
    <img src="https://img.shields.io/pypi/dw/Django.svg" alt="">
    <img src="https://img.shields.io/badge/soul-GBTAG-red.svg" alt="">
</div>
<script type="text/javascript" src="http://cdn.gbtags.com/jquery/1.11.1/jquery.min.js"></script>

转载 | Composer 入门

前言: 最近总结了好多和 composer 相关的文章。这一篇对 composer 做个简单介绍。文章大部分来源于Composer 中文文档

对于现代语言而言,包管理器基本上是标配。Java 有 Maven,Python 有 pip,Ruby 有 gem,Nodejs 有 npm。PHP 的则是 PEAR,不过 PEAR 坑不少:

依赖处理容易出问题
配置非常复杂
难用的命令行接口

composer 也是 PHP 用来管理依赖关系的工具。它做的如此之好,以至于如果你只是纯粹地进行 php 开发,在平时使用中对几乎可以忽略 composer。 你可以在自己的项目中声明所依赖的外部工具库,Composer 会帮你安装这些依赖的库文件。它实际上包含了两个部分:ComposerPackagist

Composer 是由 Jordi Boggiano 和 Nils Aderman 创造的一个命令行工具,它的使命就是帮你为项目自动安装所依赖的开发包。Composer 包含了一个依赖解析器,用来处理开发包之间复杂的依赖关系;另外,它还包含了下载器、安装器等有趣的东西。 Packagist 是 Composer 的默认的开发包仓库。你可以将自己的安装包提交到 packagist,当你在自己的 Git 仓库中新建了 tag 或更新了代码,packagist 都会自动构建一个新的开发包。


php 数组增加元素的方法 array_push 和 array_merge

本文的起因是今天需要给一个数组添加成员,一个是无序数组,直接往里扔就可以,另一个是key-value形式的数组。

无序数组只要array_push即可,key-value数组如果数量少,也可以用 $data['pussy'] = 'wagon'形式。

array_push(array,value1,value2…)

参数	描述
array	必需。规定数组。
value1	必需。规定要添加的值。
value2	可选。规定要添加的值。

例子:

$config = require_once __DIR__ . '/../vendor/xxx.php';
array_push($config['providers'],
    xxx\Providers\HttpClientServiceProvider::class,
    xxx\Providers\SmsServiceProvider::class,
    xxx\Providers\QrCodeServiceProvider::class,
    \Intervention\Image\ImageServiceProvider::class,
    xxx\Providers\ImageServiceProvider::class,
    xxx\Providers\WordSegmentServiceProvider::class,
    xxx\Providers\WechatServiceProvider::class,
    xxx\Providers\RecommendServiceProvider::class,
    Ignited\LaravelOmnipay\LaravelOmnipayServiceProvider::class
);

array_merge(array1,array2,array3…)

参数	描述
array1	必需。规定数组。
array2	可选。规定数组。
array3	可选。规定数组。

例子接上:

$config['aliases'] = array_merge($config['aliases'], [
        'HttpClient' => xxx\Facades\HttpClient::class,
        'Sms' => xxx\Facades\Sms::class,
        'QrCode' => xxx\Facades\QrCode::class,
        'Image' => \Intervention\Image\Facades\Image::class,
        'ImageUpload' => xxx\Facades\Image::class,
        'WordSegment' => xxx\Facades\WordSegment::class,
        'Recommend' => xxx\Facades\Recommend::class,
        'Wechat' => xxx\Facades\Wechat::class,
        'Omnipay' => Ignited\LaravelOmnipay\Facades\OmnipayFacade::class
    ]
);

php include()和 require() 的区别说明

这也是个老生常谈的东西了,今天在阅读laravel的源代码,顺手记一下。

在php中引用文件有两种办法,require(_once) 及 include(_once)。

他们最主要的不同点在于

  • 使用include时,一般是放在流程控制的处理部分中。PHP 程序网页在读到 include 的文件时,才将它读进来。这种方式,可以把程序执行时的流程简单化。当包含的文件不存在时,系统会报出警告级别的错误(warning),程序会继续往下执行。
  • 使用require时,通常放在 PHP 程序的最前面,使得 PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部份。当包含的文件不存在时,系统会先报出警告级别的错误(warning),接着又报一个致命级别的错误(Fatal error)。程序终止执行。
  • incluce在用到时加载,require在一开始就加载,_once后缀表示已加载的不加载
  • require()通常来导入静态的内容,而include()则适合用导入动态的程序代码。

      对include()语句来说,在执行文件时每次都要进行读取和评估;
      而对于require()来说,文件只处理一次(实际上,文件内容替换require()语句)。
      这就意味着如果可能执行多次的代码,则使用require()效率比较高,如果每次执行代码时是读取不同的文件,或者有通过一组文件迭代的循环,就使用include()语句。
    
  • include有返回值,而require没有。

    例如laravel的index.php文件中通过 require_once 对 app 进行赋值:

      // index.php
          <?php
          require __DIR__.'/../bootstrap/autoload.php';
          $app = require_once __DIR__.'/../bootstrap/app.php';
    
      // app.php
    
          <?php
          $app = new Illuminate\Foundation\Application(
              realpath(__DIR__.'/../')
          );
            
          ...
    
          return $app;
    

参考资料


使用 satis 搭建一个私有的 Composer 包仓库

在日常php开发中可能需要使用大量的composer包,大部份都可以直接使用,但公司内部有一些与业务相关的包,是不能公开的,这时候我们就需要搭建一个公司内部使用的composer仓库。

composer官方提供的工具有satis和toran proxy。 satis的搭建相对简单一些,于是我选用satis进行搭建。它的文档在composer 以及 github

1. 建立项目

使用 Composer 自带的建项目功能,这个相当于 git clone + composer install + 运行 post-install 脚本。

composer create-project composer/satis my-satis --stability=dev --keep-vcs

2. 建立配置文件

在 satis 项目目录下建立 satis.json 文件

{
  "name": "仓库名称",
  "homepage": "http://satis仓库地址",
  "repositories": [
    { "type": "vcs", "url": "https://github.com/mycompany/privaterepo" },
    { "type": "vcs", "url": "http://svn.example.org/private/repo" },
    { "type": "vcs", "url": "https://github.com/mycompany/privaterepo2" }
  ],
  "require-all": true
}

注意:仓库名称需要和仓库里 composer.json 的 name 定义一致,和路径没什么关系,不然就会找不到。

因为加入私有源的仓库本身可能也有依赖,require-all 会把这些依赖的信息也抓进来。如果不需要的话,可以指定某个仓库,甚至某个版本:

{
  "name": "仓库名称",
  "homepage": "http://satis仓库地址/",
  "repositories": [
    { "type": "vcs", "url": "https://github.com/mycompany/privaterepo" },
    { "type": "vcs", "url": "http://svn.example.org/private/repo" },
    { "type": "vcs", "url": "https://github.com/mycompany/privaterepo2" }
  ],
  "require": {
    "company/package": "*",
    "company/package2": "*",
    "company/package3": "2.0.0"
  }
}

3. 生成仓库列表

php bin/satis build satis.json public/

selenium 入门

Selenium是用于自动化测试工具,它是在Apache许可证2.0许可的开放源代码工具。Selenium是一套工具,它有助于自动化Web应用程序测试。本文介绍它的快速入门配置(php版本)与一个很简单的php爬虫应用。

Composer 安装 Selenium:

composer require facebook/webdriver

下载Selenium Server并启动:

下载Selenium Standalone Server:http://www.seleniumhq.org/download/

安装java jdk后,运行如下命令:

java -jar selenium-server-standalone-3.0.1.jar

下载浏览器插件

selenium 支持多种浏览器,我目前使用的是chrome。http://chromedriver.storage.googleapis.com/index.html?path=2.27/

下载解压,你会得到一个 chromedriver.exe 文件,放到 chrome 的安装目录下(我的:C:\Program Files (x86)\Google\Chrome\Application\),然后在 path 环境变量中添加 chrome 的安装目录。

运行测试代码

打开命令提示符,运行后边的文件 php bilibili.php 命令,最后打印了哔哩哔哩顶部的8个视频。


php 获取编码和转换编码

做爬虫抓取页面的时候,常常有非utf-8的混入,包括gbk gb2312 甚至是 Big5,需要转换成我们期望的格式。 同时,Windows与其他操作系统也不同。普通的Linux和Mac都是原生使用utf-8的编码格式,而中文的windows用的则是gbk格式。因此针对不同系统的终端输出(console,cmd),我们也需要进行编码转换。

看代码说话:

function exchangeEncoding($text, $pageEncoding = '', $targetEncoding = 'UTF-8')
{
    if (!$pageEncoding) {
        $pageEncoding = mb_detect_encoding($text, array("ASCII", 'UTF-8', "GB2312", "GBK", 'BIG5'));
    }

    if ($pageEncoding != $targetEncoding) {
        return mb_convert_encoding($text,$targetEncoding,$pageEncoding);
    }

    return $text;
}

function consoleText($text, $pageEncoding = '', $consoleEncoding = '')
{
    // windows
    if (!$consoleEncoding) {
        if (stristr(php_uname('s'), 'win')) {
            $consoleEncoding = "GBK";
        } else {
            $consoleEncoding = 'UTF-8';
        }
    }
    return exchangeEncoding($text, $pageEncoding, $consoleEncoding);
}

1 2 3 4 5 6 16 17 18 19 20