解决跨域问题一般是在nginx加入Access-Control-Allow-Origin: * 来处理,但chrome等浏览器不允许星号的存在,只能设置一个域名,这样我们很多时候就不方便.

 

这里给出一个php的解决方式,把下面代码直接放到项目的index.php中即可.

$origin = isset($_SERVER[‘HTTP_ORIGIN’])?$_SERVER[‘HTTP_ORIGIN’]:””;  //获取请求来源,这一行需要根据情况来获取,万能的程序员自行检查吧
if($origin){
    header(“Access-Control-Allow-Origin: $origin”);
    header(‘Access-Control-Allow-Credentials:true’);
    header(‘Access-Control-Allow-Methods:GET, POST, OPTIONS’);
    header(‘Access-Control-Allow-Headers:DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type’);
}

一失足成千古恨,装新mac时把系统分区设置成区分大小写的分区。然后发现adobe全系列都安装不了。整了一天,终于找到了方案。

mark一下步骤

1 到xclient.info之类的网站下载adobe photoshop cc 2017 for mac.dmg文件,记得需要找有Install.app文件的

把该dmg文件解压出来,我们假设解压到~/Downloads/photoshop下。

 

2  使用系统磁盘工具,分出来一个20GB的大小写不敏感的分区。

3 git clone https://github.com/tzvetkoff/adobe_case_sensitive_volumes

下载一个可以伪装系统分区为大小写不敏感的代码

4 cd adobe_case_sensitive_volumes

5 vim MakeFile

修改第一行为

CS6_INSTALLER_PATH=~/Downloads/photoshop/Install.app/Contents/MacOS/Install

保存退出

6 make

7 sudo make run

后面正常安装,注册登录等,安装时会提示分区格式不对,选择我们新建的分区,继续安装即可。

PHP代码编写自动化测试被认为是一个最佳实践,可以帮助你构建出高质量的应用。自动化测试可以帮助你确认没有因为重构或添加 新功能而破坏原有功能,所以应该重视自动化测试。

PHP有多种类型的测试工具和框架可以使用,具体方法各有区别——但是它们的目标都是避免手工测试,满足大型QA组织的需求,保证最新的 更改没有破坏已有功能。

测试驱动开发

Wikipedia的定义:

测试驱动开发(TDD)是以非常短的开发周期,不断进行迭代的软件开发流程:首先开发者针对改进或新功能编写失败的自动化测试用例,然后编写代码使测试用例通过, 最后重构代码,让代码满足可接受的标准。Kent Beck,该技术的创建者或者说重新发现者,在2003年声明TDD鼓励简单的设计和提振信心。

目前对应用有多种类型的测试:

单元测试

单元测试是从编写开始,贯穿于整个开发周期的一种用于保证函数、类和方法的行为与预期一致的编程方法。通过检查各个函数和方法的输入和输出值,你可以保证它们 内部逻辑已经正确执行;通过依赖注入、编写mock类和stubs,你可以验证依赖是否已经正确处理,提高测试覆盖率。

在编写一个类或函数的时候,应该为它的每一个行为创建一个单元测试,至少你要保证它收到错误参数时能够触发错误,而参数正确时能正常工作。这可以帮你在后面 修改类或函数的时候,确认已有功能仍然正常工作。PHP中var_dump()的功能与此类似,但是它是无法用于创建应用的。

单元测试的另外一个用武之地是在给开源项目贡献代码时,如果你编写一个测试,证明代码存在bug,然后修复代码,让测试通过,这样该补丁被接受的概率要高很多。 如果你的项目接受人家的补丁,你应该把单元测试作为项目的一项要求。

PHPUnit是PHP应用的单元测试框架的业界标准,其他几个可选框架是:

集成测试

Wikipedia的定义:

集成测试(也称集成与测试,缩写为I&T)是把各个独立模块集成在一起,作为一个整体进行测试的软件测试阶段,它处于单元测试和验收测试之间。集成测试把已经 做过单元测试的模块集成在一块,然后运行集成测试用例,最终输出一个可以进行系统测试的系统。

很多单元测试工具同时也可以用于集成测试,并且原理也是相通的。

功能测试

有时也称为验收测试,使用工具创建自动化的测试用例,然后在真实的系统上运行,这一点与单元测试验证单个模块的正确性和集成测试验证模块间交互的正确性是有 区别的,这些工具通常使用真实的数据集来模拟真实用户的使用行为来验证系统的正确性。

功能测试工具

行为驱动开发

行为驱动开发(BDD)有两种方式:SpecBDD和StoryBDD。SpecBDD关注技术行为或代码,而StoryBDD关注业务、特性和交互,这两种方式都有对应的PHP框架。

采用StoryBDD,开发者编写人类可读的故事来描述应用的行为,然后这些故事可以作为应用的测试用例。PHP中用于StoryBDD编程的框架是Behat,从Ruby 的Cucumber项目演化而来,实现了Gherkin DSL来描述特性行为。

采用SpecBDD,开发者编写规格说明来描述实际代码的行为,与测试一个函数或方法不同,规格描述了一个函数或方法应该具有的行为。PHP中的PHPSpec框 架提供该编程方式的支持,它也是从Ruby的RSpec project演化而来。

BDD链接

  • Behat, the StoryBDD framework for PHP, inspired by Ruby’s Cucumber project;
  • PHPSpec, the SpecBDD framework for PHP, inspired by Ruby’s RSpec project;
  • Codeception is a full-stack testing framework that uses BDD principles.

测试辅助工具

除了测试驱动和行为驱动开发框架,还有大量的通用框架和函数库,可以在各种开发方法下使用。

工具链接

mark文

正常按php安装流程安装完nginx和Php-fpm后,启动服务,发现nginx报502错误.

检查nginx错误日志,说是127.0.0.1:9000收不到数据

在命令行下telnet 127.0.0.1 9000 ,返回connected但立即被中断.

 

处理结果:

检查/etc/php-fpm.d/www.conf文件中

listen.allowed_clients = 127.0.0.1

将这行注释掉,或改为

listen.allowed_clients = 127.0.0.1,localhost,10.60.11.11

最后的10.60.11.11是指本机IP

此文只当是一个mark吧

在mac和linux上软链接的使用基本是相同的,有一点不同的在权限方面:

1 linux的软链文件不能修改权限

详见man chmod :

chmod never changes the permissions of symbolic links; the chmod system call cannot change their permissions. This is not a problem since the permissions of symbolic links are never used. However, for each symbolic link listed on the command line, chmod changes the permissions of the pointed-to file. In contrast, chmod ignores symbolic links encountered during recursive directory traversals.

2 mac的软链文件可以用chmod设置权限  chmod -h 777 ./symlink

详见man chmod :

-h If the file is a symbolic link, change the mode of the link itself rather than the file that the link points to.

从网上找了不少,果然很多中文网站放的都不靠谱

下面是从英文网站找到的

磁力链下载:magnet:?xt=urn:btih:961e2361009c4c719769afd36a093cf3e4dd34c7&dn=Navicat+Premium+11+0+10+Mac+OS+X&tr=udp%3A%2F%2Ftracker.openbittorrent.com%3A80&tr=udp%3A%2F%2Ftracker.publicbt.com%3A80&tr=udp%3A%2F%2Ftracker.istole.it%3A6969&tr=udp%3A%2F%2Fopen.demonii.com%3A1337

 

下载后安装Navicat,把keygen.app放到Applications下面运行。

运行keygen.app,点Generate,点击Actived,点击Patch  over

 

如果之前安装过旧版,或者您在安装中遇到破解不了的问题,参照下面步骤

1) 关闭 Navicat Premium

2) 下载并运行 appcleaner 2.2.x : http://www.freemacsoft.net/appcleaner/
3) 运行 appCleaner, 选择 navicat, 找到所有关联文件删除
4) 断开网络
5) 安装Navicat
6) 把Keygen.app 放到应用文件夹下,并运行.
7) 随便输入姓名和公司名,但不用用test或me
8) 点击Activate按钮,选择Navicat
9) 点击Patch按钮,选择Navicat
10) 关闭keygen,再启动Navicat应该就OK了

注意: 启动后需要到 “Navicat Premium”菜单 > “Preferences”中去掉 “Automatically check for updates”,防止自动更新。自动更新会影响破解。

 

“Swift is a new programming language for iOS and OS X apps that builds on the best of C and Objective-C, without the constraints of C compatibility. Swift adopts safe programming patterns and adds modern features to make programming easier, more flexible, and more fun. Swift’s clean slate, backed by the mature and much-loved Cocoa and Cocoa Touch frameworks, is an opportunity to reimagine how software development works.

Swift has been years in the making. Apple laid the foundation for Swift by advancing our existing compiler, debugger, and framework infrastructure. We simplified memory management with Automatic Reference Counting (ARC). Our framework stack, built on the solid base of Foundation and Cocoa, has been modernized and standardized throughout. Objective-C itself has evolved to support blocks, collection literals, and modules, enabling framework adoption of modern language technologies without disruption. Thanks to this groundwork, we can now introduce a new language for the future of Apple software development.”

 

下载链接: http://pan.baidu.com/s/1hqvaIm4

项目中需要在客户上传APK后自动分析出APK包名\名称等信息,并提取出应用的图标,并立即返回到服务端 .

试了很多方法,都很难满足需求,其中最知名的应该是ApkParser,但它不能得到应用图标信息;

另外还有推荐使用apktool进行反编译apk包,但速度太慢,解一个包大概要5秒以上,不适合做实时程序.

我的最终方案是:

1 用aapt读取包信息

aapt dump badging ./xxx.apk

aapt包含在android sdk中的build-tools文件夹,可以把这个文件拷到服务器上单独使用,大小仅1.2M;需要注意的一点是,该程序是32位环境的程序,64位系统运行可能需要安装大概三个扩展包(如果本身没有的话),我服务器CentOS可以直接运行,就不细说了

该命令执行很快,瞬间. PHP实时返回数据没问题

这里返回的信息中就已经包含了包名\APP名称 及应用图标在apk包中的位置(类似res/drawable-mdpi/icon.png).

命令行返回的信息是纯文本,PHP不能直接用,我下面的PHP源码中会将其转为数组,以方便使用

2 用unzip直接提取需要的图标文件

#解压apk包中指定图片
unzip ./xxx.apk res/drawable-mdpi/icon.png -d /tmp

#将解压出来的图片移到我们需要的位置
mv /tmp/res/drawable-mdpi/icon.png /tmp/temp.png

因为apk本身就是zip文件重命名而已,所以无需改名,可以直接解压. 另unzip可以指定只解压压缩包中某文件,也省了很多资源.

3 最后就是在PHP中用exec执行这些命令行了,参见下面源码


/**
* Android包处理程序
* Class Service_Android
*
* @author:wangshuai
* @website:www.enjoyphp.com
*/
class Service_Android
{
/**
* 获取Apk包信息
*
* 需要/usr/bin/aapt
*
* @param $apkFile
* @return array
*/
public function getApkInfo($apkFile)
{
try {
exec('/usr/bin/aapt dump badging ' . $apkFile, $out, $return);
$apkInfo = array();
foreach ($out as $line) {
$lineana = array();
$a = explode(":", $line);
$key = trim($a[0]);
$value = trim($a[1]);
preg_match_all('/((?P<key>\S+)=)?\'(?P<value>.*?)\'/', $value, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
if ($match['key']) {
$lineana[$match['key']] = $match['value'];
} else {
$lineana[] = $match['value'];
}
}
$apkInfo[$key][] = $lineana;
}
//checkRet会把上面读出来的配置整理一下
$ret = $this->checkRet($apkInfo);
} catch (Exception $e) {
echo $e->getMessage();
$ret = array();
}
return $ret;
}

/**
* 从Apk包中提取指定文件,并移到$toFile
*
* @param $apkFile apk文件
* @param $sourceFile apk文件中相应文件路径
* @param $toFile 输出文件
* @return bool
*/
function getFileFromApk($apkFile, $sourceFile, $toFile)
{
exec('unzip ' . $apkFile . ' $sourceFile -d /tmp', $out, $return);
if (rename("/tmp/" . $sourceFile, $toFile)) {
return true;
} else {
return false;
}
}

/**
* 辅助函数,处理Apk信息数组
*
* @param $info
* @return mixed
*/
function checkRet($info)
{
foreach ($info as $key => $lineana) {
if (is_array($lineana)) {
$info[$key] = $this->checkRet($lineana);
if (count($info[$key]) == 1) {
$info[$key] = current($info[$key]);
}
} else {
}
}
return $info;
}
}

 

一段使用示例:



<?php
$apk = "/tmp/wht.apk";
$iconFile = '/tmp/a.png';
/** @var Service_Android $android */
$android = new Service_Android();
$res = $android->getApkInfo($apk);
var_dump($res);
$packageName = $res['package']['name'];
$appName = $res['application-label'];
$android->getFileFromApk($apk,$res['application']['icon'],$iconFile);

注意事项:

1 运行该程序需要PHP有exec权限
2 获取的apk包信息中,APP名称可能会有多国语言名称,ICON会有多种尺寸; 如果有需要,请自行根据需要修改,上面只介绍了使用默认信息.

PSR是Proposing a Standards Recommendation(提出标准建议)的缩写,是由PHP Framework Interoperability Group(PHP通用性框架小组,简称PHP-FIG)发起的,通过他们命名就可以看出,这是个主要是针对框架通用性而做努力的开放性小组,他们的在Github上有自己的仓库地址,目前只有一个被接受的标准,那就是PSR-0标准,标准定义了PHP自动加载的命名规范和文件路径规范。 针对PSR-0标准主要提到了以下几点:

要求

  • 一个完全合格的命名空间和类名必须有以下的结构“\<提供者名称>\(<命名空间>\)*<类名>”
  • 每个命名空间必须有顶级的命名空间(“提供者”)
  • 每个命名空间可以有任意多个子命名空间
  • 每个命名空间在被从文件系统加载时必须被转换为“操作系统路径分隔符”(DIRECTORY_SEPARATOR )
  • 每个“_”字符在“类名”中被转换为DIRECTORY_SEPARATOR 。“_”符号在命名空间中没有这个含义
  • 符合命名标准的命名空间和类名必须以“.php”结尾来加载文件
  • 提供商名称,命名空间,类名可以由大小写字母组成,其中命名空间和类名是大小写敏感的以保证多系统兼容性
  • 如果文件不存在需要返回false

例子

\Doctrine\Common\IsolatedClassLoader => /path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php
\Symfony\Core\Request => /path/to/project/lib/vendor/Symfony/Core/Request.php
\Zend\Acl => /path/to/project/lib/vendor/Zend/Acl.php
\Zend\Mail\Message => /path/to/project/lib/vendor/Zend/Mail/Message.php

下划线在命名空间和类名中的使用

\namespace\package\Class_Name => /path/to/project/lib/vendor/namespace/package/Class/Name.php
\namespace\package_name\Class_Name => /path/to/project/lib/vendor/namespace/package_name/Class/Name.php

设置这个标准是为了保证最基本的共同点。你可以通过实现5.3的SplClassLoader来测试这个标准。

扩展例子

提供一个函数来展示如何使用上述标准。

<?php

function autoload($className)
{
    $className = ltrim($className, '\\');
    $fileName  = '';
    $namespace = '';
    if ($lastNsPos = strripos($className, '\\')) {
        $namespace = substr($className, 0, $lastNsPos);
        $className = substr($className, $lastNsPos + 1);
        $fileName  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
    }
    $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';

    require $fileName;
}

SplClassloader的实现

接下来这个gist实现了SplClassLoader可以加载你按照上面标准来实现的通用类库,这是5.3里面推荐的加载方式。

http://gist.github.com/221634

扩展实现

因为这个标准提到了如果文件不存在的时候应该范围false,但是在上面函数的例子中并没有实现该机制,所有有人实现了优化的SplClassLoader。

<?php

class ClassLoader
{
    /**
     * @var array Contains namespace/class prefix as key and sub path as value
     */
    protected $paths;

    /**
     * Construct a loader instance
     *
     * @param array $paths Containing class/namespace prefix as key and sub path as value
     */
    public function __construct( array $paths )
    {
        $this->paths = $paths;
    }

    /**
     * Load classes/interfaces following PSR-0 naming
     *
     * @param string $className
     * @return null|boolean Null if no match is found, bool if match and found/not found.
     */
    public function load( $className )
    {
        if ( $className[0] === '\\' )
            $className = substr( $className, 1 );

        foreach ( $this->paths as $prefix => $subPath )
        {
            if ( strpos( $className, $prefix ) !== 0 )
                continue;

            $lastNsPos = strripos( $className, '\\' );
            $prefixLen = strlen( $prefix ) + 1;
            $fileName = $subPath . DIRECTORY_SEPARATOR;

            if ( $lastNsPos > $prefixLen )
            {
                // Replacing '\' to '/' in namespace part
                $fileName .= str_replace(
                    '\\',
                    DIRECTORY_SEPARATOR,
                    substr( $className, $prefixLen, $lastNsPos - $prefixLen )
                ) . DIRECTORY_SEPARATOR;
            }

            // Replacing '_' to '/' in className part and append '.php'
            $fileName .= str_replace( '_', DIRECTORY_SEPARATOR, substr( $className, $lastNsPos + 1 ) ) . '.php';

            if ( ( $fileName = stream_resolve_include_path( $fileName ) ) === false )
                return false;

            require $fileName;
            return true;
        }
    }
}

引用地址:https://github.com/andrerom/fig-standards/blob/psr2/proposed/PSR-2.md

写在后面

标准对于开发者来说是一个好事,如今已经越来越多的开源项目加入了这个标准Pear2、PHPBB、ComposerPackagist、Joomla、Drupal、SymfonyCakePHPDoctrine2等等,我常用的一个框架MicroMVC也在很早的时候就采用了这个标准。采用同样标准的项目可以无缝的接入,做为开发者最好要尝试并接收一个好的标准。

扩展阅读

PHP官方关于SplClassLoader的RFC:https://wiki.php.net/rfc/splclassloader PHP标准化组织论坛:https://groups.google.com/forum/?fromgroups#!forum/php-standards