关于文章 php

nodejs php python swoole 压力测试

有意思的 Hello World

有意思的 Hello World 三种语言的压力测试

周末突发奇想 看了下swoole

便有了以下测试

python3 aiohttp rps 2000+

nodejs rps 3000+

swoole rps 13000+

被震惊了一下

被群友提醒了一下

swoole 会默认开cpu同等的进程

开启 nodejs 的cluster

rps 下降到2800

瞬间对nodejs怀疑了人生。。。

php redis

从 Redis 迁移到 SSDB

PHP 脚本可以用来将 Redis 服务器上的数据, 拷贝到 SSDB 服务器上.

工具

tools 目录中的 redis-import.php PHP 脚本可以用来将 Redis 服务器上的数据, 拷贝到 SSDB 服务器上.

用法:

php redis-import.php redis_host redis_port redis_db ssdb_host ssdb_port

参数:

  • redis_host: Redis 运行所在的 IP 或者主机名
  • redis_port: Redis 监听的端口
  • redis_db: Redis 的 DB 编号
  • ssdb_host: SSDB 运行所在的 IP 或者主机名
  • ssdb_port: SSDB 监听的端口

请确保你的 PHP Redis 模块 https://github.com/nicolasff/phpredis 已经安装.

Redis 工具的支持

Tool Supported
redis-cli 支持
Twemproxy 支持
Sentinel 不支持

SSDB 和 Redis 命令对照表

SSDB 支持 Redis 协议和客户端, 所以你可以使用 Redis 的客户端来连接 SSDB 进行操作.

但是, 如果你想使用 SSDB 的客户端, 你可能需要下面的命令对照表.

Key-Value

Redis SSDB
get get
set set
setex setx(for kv type only)
del del
incr/incrBy incr
decr/decrBy decr
mget/getMultiple multi_get
setMultiple multi_set
del(multiple) multi_del
keys keys(for kv type only)
getset getset
setnx setnx
exists exists
ttl ttl
expire expire
getbit getbit
setbit setbit
bitcount redis_bitcount, countbit
strlen strlen
getrange getrange

请非常细心地阅读此处的说明:

  • 对于 Redis, substr 命令早已经被废弃, 所以你不要使用 substr 命令在 Redis 客户端(当然, 你__可以__这么做, 但你__必须不__这么做)
  • 如果你还想着 Redis, 那么就用 getrange 命令
  • 注意这两者的区别: substr(start, size), getrange(start, end)
  • 当 size 是负数时, 如果你不熟悉 PHP 语言, 那么你会觉得有些奇怪
  • SSDB 的 substr 命令的描述这 这里

Key-Map(Hash)

Redis SSDB
del(not supported) hclear
hget hget
hset hset
hdel, hmdel hdel, multi_hdel
hIncrBy hincr
hDecrBy hdecr
hKeys hkeys
hVals hscan
hMGet multi_hget
hMSet multi_hset
hLen hsize
hExists hexists
keys hlist(for hash type only)

如果你想删除整个 hash, 那么你就必须使用 SSDB 的客户端来执行 hclear 命令, 用 Redis 的客户端是删除不了整个 hash 的.

Key-Zset

Redis SSDB
del(not supported) zclear
zScore zget
zAdd zset
zRem zdel
zRange zrange
zRevRange zrrange
zRangeByScore zscan
zRevRangeByScore zrscan
zIncrBy zincr
zDecrBy zdecr
zCount zcount
zSum zsum
zAvg zavg
zCard zsize
zRank zrank
zRemRangeByRank zremrangebyrank
zRemRangeByScore zremrangebyscore
keys zlist(for zset type only)

如果你想删除整个 zset, 那么你就必须使用 SSDB 的客户端来执行 zclear 命令, 用 Redis 的客户端是删除不了整个 zset 的.

Key-List(Queue)

Redis SSDB
del(not supported) qclear
llen/lsize qsize
lpush qpush_front
rpush qpush_back
lpop qpop_front
rpop qpop_back
lrange qslice
lindex, lget qget
lset qset
keys qlist(for queue/list type only)

如果你想删除整个 list, 那么你就必须使用 SSDB 的客户端来执行 qclear 命令, 用 Redis 的客户端是删除不了整个 list 的.

linux phalcon php

php的c扩展框架 phalcon 的简单使用

php的c扩展框架 phalcon 的简单使用

Phalcon 是开源、全功能栈、使用 C 扩展编写、针对高性能优化的php框架

生成控制器

 phalcon create-controller --name index2

基本配置

[database]
adapter  = Mysql
host     = "127.0.0.1:port"
username = "root"
password = "root"
dbname   = "tests"

[phalcon]
controllersDir = "../app/controllers/"
modelsDir      = "../app/models/"
viewsDir       = "../app/views/"
baseUri        = "/store/"

生成模型

phalcon model products
  • --name=s Table name 表名
  • --schema=s Name of the schema. [optional] schema名
  • --namespace=s Model’s namespace [optional] 模型命名空间
  • --get-set Attributes will be protected and have setters/getters. [optional] 设置字段访问属性为私有 并添加setters/getters方法
  • --extends=s Model extends the class name supplied [optional] 指定扩展类名
  • --excludefields=l Excludes fields defined in a comma separated list [optional]
  • --doc Helps to improve code completion on IDEs [optional] 辅助IDE的自动完成功能
  • --directory=s Base path on which project will be created [optional] 项目的根目录
  • --force Rewrite the model. [optional] 重写模型
  • --trace Shows the trace of the framework in case of exception. [optional] 出错时显示框架trace信息
  • --mapcolumn Get some code for map columns. [optional] 生成字映射的代码
  • --abstract Abstract Model [optional] 抽象模型

生成简单的curd

phalcon scaffold --table-name products

开启webtools

phalcon webtools enable/disable(开启关闭)

ide自动补全

文档

php url

php的c扩展框架 phalcon 修复url的bug

php的c扩展框架 phalcon 修复url的bug

php的c扩展框架 phalcon 修复url的bug

Phalcon 是开源、全功能栈、使用 C 扩展编写、针对高性能优化的php框架

默认生成的url会重复

修改

app->config->config.php

defined('BASE_PATH') || define('BASE_PATH', getenv('BASE_PATH') ?: realpath(dirname(__FILE__) . '/../..'));
defined('APP_PATH') || define('APP_PATH', BASE_PATH . '/app');

return new \Phalcon\Config([
    'database' => [
        'adapter'     => 'Mysql',
        'host'        => 'localhost:3309',
        'username'    => 'root',
        'password'    => 'root',
        'dbname'      => 'test',
        'charset'     => 'utf8',
    ],
    'application' => [
        'appDir'         => APP_PATH . '/',
        'controllersDir' => APP_PATH . '/controllers/',
        'modelsDir'      => APP_PATH . '/models/',
        'migrationsDir'  => APP_PATH . '/migrations/',
        'viewsDir'       => APP_PATH . '/views/',
        'pluginsDir'     => APP_PATH . '/plugins/',
        'libraryDir'     => APP_PATH . '/library/',
        'cacheDir'       => BASE_PATH . '/cache/',
        'baseUri'        => '/', //这修改成/根  就可以了
    ]
]);
captcha php

非Laravel使用Laravel的验证码库gregwar/captcha

非Laravel使用Laravel的验证码库gregwar/captcha

在Laravel中有很多图片验证码的库可以使用,本篇介绍其中之一:gregwar/captcha, 这个库比较简单,在Laravel中比较常用 但是也可以在其他框架中使用

首先,初始化composer 然后引入包 ```php composer init composer require gregwar/captcha

```

引入autoload.php

这里使用的是yurunphp实在/lib/init.php中引用autoload.php

代码中引入命名空间

```php use Gregwar\Captcha\CaptchaBuilder;

控制器中php

public function captcha($tmp) { //生成验证码图片的Builder对象,配置相应属性 $builder = new CaptchaBuilder; //可以设置图片宽高及字体 $builder->build($width = 100, $height = 40, $font = null); //获取验证码的内容 $phrase = $builder->getPhrase();

    //把内容存入session
    Session::flash('milkcaptcha', $phrase);
    //生成图片
    header("Cache-Control: no-cache, must-revalidate");
    header('Content-Type: image/jpeg');
    $builder->output();
}

```

前端调用

```

php zend3

zend3mvc文档汉化

zend3mvc文档汉化

快速开始

现在您已经了解了应用程序、模块以及它们是如何构造的,我们将向您展示入门的简单方法。

安装在Zend支架的应用

安装Zend骨架应用最简单的方式开始安装骨架应用composer。 如果你还没有这样做,安装composer。

这里

debian
sudo apt install composer
fedora
sudo dnf install composer

安装好后,修改成中国源

composer config -g repo.packagist composer
 https://packagist.phpcomposer.com

在命令行中运行命令安装脚手架

$ composer create-project -sdev 
zendframework/skeleton-application my-application

创建一个新模块

默认情况下,一个模块提供的zendskeletonapplication,命名为“application”。

它提供了一个控制器来处理应用程序的"index”、布局模板和404个错误页面的模板。

通常,除了为站点和/或交替错误页提供一个备用条目页外,您不需要触摸其他内容。

通过创建新的模块将提供额外的功能。

你开始的模块,我们建议使用zendskeletonmodule为基础。从这里下载它:

https://github.com/zendframework/ZendSkeletonModule/

重命名目录“ZendSkeletonModule”成为的是你想创建新的模块的名称;

完成后,将模块放入你的新项目的模块目录。

更新模块类

让我们更新模块类。 我们要确保命名空间是正确的,配置启用并返回,而我们设置自动初始化。 我们可能想在我们的自动载入的方法是相当宽松的, 所以让我们用standardautoloader保持灵活。开始吧.

  • 首先,让我们 autoload_classmap.php 返回空数组:
// autoload_classmap.php
return array();
  • 我们还将编辑配置 module.config.php 文件如下:
return array(
    'view_manager' => array(
        'template_path_stack' => array(
            'module-name' => __DIR__ . '/../view'
        ),
    ),
);

用小写填写 模块 名称,破折号分开你的模块名称版本;例如,“ZendUser”将成为"zend-user”。

接下来,编辑的 module.php 文件命名空间声明。替换以下行:

namespace ZendSkeletonModule;

使用要为应用程序使用的命名空间。

接下来,重命名目录 src/zendskeletonmodule 为 src/要添加的模块名

和目录 view/zend-skeleton-module 为 src/模块名.

此时,您现在已经正确配置了模块。让我们创建控制器!

创建一个控制器

控制器对象实现 Zend\Stdlib\DispatchableInterface

这意味着他们需要实现 dispatch() 以最小请求对象作为参数的方法。

然而,实际上,这意味着在每个控制器中基于匹配路由来编写逻辑分支。因此,我们已经为您创建了几个基本控制器类:

  • Zend\Mvc\Controller\AbstractActionController 允许路由匹配的 action (视图) 。 当匹配时,控制器将调用一个命名为action的方法。 作为一个例子,如果你有一条返回“foo”为action的关键,“fooaction”方法将被调用。

  • Zend\Mvc\Controller\AbstractRestfulController 通过Request来确定什么样的HTTP方法请求被使用,和调用方法根据。

  • get将调用getlist()法,或者,如果一个“id”匹配的路由过程中,get()方法(与标识符的值)。

  • post 会叫create()方法, 通过在 $_POST 的值.

  • put希望在路由过程中匹配一个 "id", 并调用 update () 方法、传入该标识符以及在原始 post 正文中找到的任何数据。

  • DELETE需要在路由过程中匹配 "id", 并调用 delete () 方法。

  • Zend\Mvc\Controller\AbstractConsoleControllerAbstractActionController 扩展, 但提供了检索Zend\Console\Adapter\AdapterInterface 实例的方法, 并确保在台环境中执行失败。

要开始, 我们将创建一个 "hello 世界"-风格的控制器, 一个单一的动作。

首先, 在目录 src/module name/Controller中创建文件 HelloController.php。

在您喜爱的文本编辑器或 ide 中编辑它, 并插入以下内容:

namespace module name\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;

class HelloController extends AbstractActionController
{
    public function worldAction()
    {
        $message = $this->params()->fromQuery('message', 'foo');
        return new ViewModel(['message' => $message]);
    }
}

以上代码里做什么?

  • 我们正在创建一个视图控制器。
  • 我们在定义一个视图, "world"。
  • 我们正在从查询参数中提取消息 (是的, 在生产中这是一个非常糟糕的主意!总是消毒您的输入!
  • 我们将返回一个 viewmodel, 该数组的值将在以后处理。

我们返回一个 viewmodel。视图层将在呈现视图时使用它, 从中抽取变量和模板名称。默认情况下, 可以省略模板名称, 它将解析为 "小写-模块名称/小写-控制器名称/小写-操作-名称"。但是, 您可以重写此项以在 viewmodel 实例上调用 setTemplate () 来指定不同的东西。通常, 模板将解析为模块的视图目录中带有 ". phtml" 后缀的文件。

因此, 考虑到这一点, 让我们创建一个视图脚本。

创建视图脚本

创建目录view/module-name/hello。在该目录中, 创建一个名为 "world.phtml" 的文件,并在这里面, 粘贴以下内容:

 echo $this->escapeHtml($message)

这样就成。保存文件。

转义输出 escapeHtml () 的方法是什么?它实际上是一个视图帮助器, 它旨在帮助减轻 xss 攻击。不信任用户输入;如果您在视图脚本中对给定变量的源完全不确定, 请根据您拥有的数据类型, 使用提供的转义视图助手之一来转义它。

使用命名空间查看模块名称的脚本

根据 PSR-0, 模块应按照以下规则命名:

Vendor Name\Namespace \ *

从版本3.0 开始, 默认的模板名称解析器使用完全限定的控制器类名, 仅剥离 \Controller\ subnamespace (如果存在)。例如, AwesomeMe \n MyModule \ Controller \ HelloWorldController 通过以下配置解析到模板名称wesome-me/my-module/hello-world :

一下是配置

'view_manager' => array(
    'controller_map' => array(
        'AwesomeMe\MyModule' => true,
    ),
),

(在 v2 版本中, 默认为剥离空间, 但可选的映射规则允许在模块配置中名单命名空间以启用当前的冲突解决程序行为。有关详细信息, 请参阅迁移指南。

创建路由

现在, 我们有了一个控制器和一个视图脚本, 我们需要创建一个路由到它。

默认路由

  • ZendSkeletonModule 导向一个默认路由 访问您的视图 该路由大致定义为/{模块}/{控制器}/{视图}, 这意味着路径 /zend-user/hello/world 将映射到 ZendUser\Controller\HelloController::worldAction() (假定模块名称为 ZendUseZendUser).
  • 在本例中, 我们将创建一个显式路由, 因为创建显式路由是推荐的做法。 应用程序将寻找一个Zend\Mvc\Router\RouteStackInterface 实例来设置路由。 默认生成的路由器是一个Zend\Mvc\Router\Http\TreeRouteStack.

  • 要使用 "默认路由" 功能, 您需要在模块的config/module.config.php 中编辑已发运的路由定义, 然后替换:

    • module-specific-root使用模块特定的根路径。
    • ZendSkeletonModule\ControllerYourModuleName\Controller

此外, 我们需要告诉应用程序, 我们有一个控制器:

// module.config.php
return [
    'controllers' => [
        'invokables' => [
            'module-namespace\Controller\Index' => 'module-namespace\Controller\IndexController',
            // Do similar for each other controller in your module
        ],
    ],
   // ... other configuration ...
];

控制器服务 我们通知应用程序, 我们期望在应用程序的控制器。这是为了防止有人请求任何服务的 ServiceManager 知道在试图打破应用程序。调度器使用一个特殊的、作用域的容器, 它只会将特定注册的控制器作为可类或通过工厂进行。

打开您的config/module.config.php文件, 并将其修改为添加到 "路由" 和 "控制器" 参数, 以便它读取如下内容:

return [
    'router' => [
        'routes' => [
            'module name-hello-world' => [
                'type'    => 'Literal',
                    'options' => [
                    'route' => '/hello/world',
                    'defaults' => [
                        'controller' => 'module name\Controller\Hello',
                        'action'     => 'world',
                    ],
                ],
            ],
        ],
    ],
    'controllers' => [
        'invokables' => [
            'module namespace\Controller\Hello' => 'module
namespace\Controller\HelloController',
        ],
    ],
    // ... other configuration ...
];

告诉应用程序关于我们的模块

一个问题: 我们还没有告诉我们的新模块的应用!

默认情况下, 除非我们告诉模块管理器有关它们, 否则不会使用模块。因此, 我们需要通知应用程序有关它们的信息。

请记住config/application.config.php 文件。让我们修改它添加我们的新模块。一旦完成, 应改为:

return array(
    'modules' => array(
        'Application',
        'module namespace',
    ),
    'module_listener_options' => array(
        'module_paths' => array(
            './module',
            './vendor',
        ),
    ),
);

module namespace 替换为模块的命名空间。

访问 现在更改 url 为"/hello/world"

原文链接 (zhenruyan译)

linux mysql php

mysql解压安装,以及单机同时运行多个版本

mysql解压安装,以及单机同时运行多个版本

bin/mysqld --initialize --user=mysql 
--basedir=/usr/local/mysql --datadir=/data/mysql
如果失败的话
 bin/mysqld --defaults-file=C:\my.ini --initialize  

 此处需要注意记录生成的临时密码如上文YLi>7ecpe;YP

 cp my-default.cnf /etc/my.cnf

bin/mysqld_safe --defaults-file=my.cnf

my.cnf
basedir=/home/free/sqls
datadir=/home/free/sqls/data
port=9999
server_id=29922
socket=/home/free/sqls/my.socke

设置默认utf-8
character_set_server=utf8 
init_connect='SET NAMES utf8'

mysql --socket=xxxx

set password=password('root');
grant all privileges on *.* to root@'%' identified by 'root';

flush privileges;

grant grant option on *.* to 'root'@'%';