[实践OK]PHP 5.3版本的Mysqlli驱动没升级前得安装Mysql才能编译,而后面的已经不建议使用它了, 而建议使用mysqlnd。
Php/Js/Shell/Go jackxiang 2017-6-22 23:40
一、旧版本的PHP(php5.3.27)要装Mysql之后才能装Mysql(mysqli)扩展?编译选项有这个:
--with-mysql=/usr/local/mysql --with-mysqli=/usr/local/mysql/bin/mysql_config
传统的安装php的方式中,我们在编译PHP时,一般需要指定以下几项:
--with-mysql=/usr/local/mysql
--with-pdo-mysql=/usr/local/mysql
这实际上就是使用了mysql官方自带的libmysql驱动, 这是比较老的驱动, PHP 5.3开始已经不建议使用它了, 而建议使用mysqlnd.
以上是摘录,更多查看:http://blog.163.com/yxba_02/blog/static/187557620160401018458/
二、PHP7啥的都不用指定Mysql的位置,直接就能编译通过的呀~
PHP7这样的:
--with-mysql=mysqlnd \
--with-mysqli=mysqlnd \
--with-pdo-mysql=mysqlnd \
现在系统存在历史问题,没法一时半会升级PHP7了,还在用 php5.3.27上混,编译选项有指定Mysql路径的。
ldd php
发现:
libmysqlclient.so.18 => /usr/lib64/libmysqlclient.so.18 (0x00002b5b5dec7000)
也就是说PHP5.3.7最后还是编译成自己的LIb了,没有Mysql一样能跑,这TM是个问题,装个PHP还得装上Mysql,这个低版本的PHP还得装Mysql服务才行哟。
总之,Mysql和PHP在低版本有了较强的捆绑,而新的PHP7采用Mysqlnd(MySQL Native Driver),摆脱了这一依赖,更简单,更高效。php高版本不再使用mysql_connect()来连接数据库。
--with-mysql=/usr/local/mysql --with-mysqli=/usr/local/mysql/bin/mysql_config
传统的安装php的方式中,我们在编译PHP时,一般需要指定以下几项:
--with-mysql=/usr/local/mysql
--with-pdo-mysql=/usr/local/mysql
这实际上就是使用了mysql官方自带的libmysql驱动, 这是比较老的驱动, PHP 5.3开始已经不建议使用它了, 而建议使用mysqlnd.
以上是摘录,更多查看:http://blog.163.com/yxba_02/blog/static/187557620160401018458/
二、PHP7啥的都不用指定Mysql的位置,直接就能编译通过的呀~
PHP7这样的:
--with-mysql=mysqlnd \
--with-mysqli=mysqlnd \
--with-pdo-mysql=mysqlnd \
现在系统存在历史问题,没法一时半会升级PHP7了,还在用 php5.3.27上混,编译选项有指定Mysql路径的。
ldd php
发现:
libmysqlclient.so.18 => /usr/lib64/libmysqlclient.so.18 (0x00002b5b5dec7000)
也就是说PHP5.3.7最后还是编译成自己的LIb了,没有Mysql一样能跑,这TM是个问题,装个PHP还得装上Mysql,这个低版本的PHP还得装Mysql服务才行哟。
总之,Mysql和PHP在低版本有了较强的捆绑,而新的PHP7采用Mysqlnd(MySQL Native Driver),摆脱了这一依赖,更简单,更高效。php高版本不再使用mysql_connect()来连接数据库。
PHP7框架之Lumen之Hello World,PHP7下的Lumen (5.5.*)框架之Hello World,如何调用Models下面的数据层,触目了解其MVC思想和取数据成功实践于基于其领悟,学下先进。
Php/Js/Shell/Go jackxiang 2017-1-13 15:20
背景:听说Lumen起家是以一个叫av的框架,larvael。以Auth2.0起步,Lumen是精简版本,于是想了解一下。发现居然边TM路由就卡住了,Fuck,不光是我老外也有这个问题,都没有解决,主要是一个Nginx的转写问题,这块在Lumen的文档里写的很垃圾,我都不知这些人是怎么写文档的,有用Apache,有Nginx的就不能写细一点么,说一下原理啥的,关键是Nginx配置文件里面的:location /里面的重写。
From:http://blog.csdn.net/wowkk/article/details/52104689
Lumen 5.5.*版本的Lumen,目录:lumen-clear-edition
composer create-project laravel/lumen lumen-clear-edition --prefer-dist "5.5.*" # proc_open,
vi ms/survey/bootstrap/app.php
require __DIR__.'/../config/providers.php'
vi ms/survey/config/providers.php
<?php
$app->register(Common\Providers\RedisServiceProvider::class);
$app->register(Common\Providers\MysqlServiceProvider::class);
$app->register(Common\Providers\KafkaServiceProvider::class);
$app->register(Common\Providers\EventServiceProvider::class);
$app->register(Common\Providers\QueueServiceProvider::class);
注册的文件在:
ls ./lumen-clear-edition/common/Providers
EventServiceProvider.php MysqlServiceProvider.php RedisServiceProvider.php
启动方法:
启动方法#服务提供者中注册一个视图 composer 则应该在 boot 方法中完成。此方法会在所有其它的服务提供者被注册后才被调用,意味着你能访问已经被框架注册的所有其它服务:https://lumen.laravel-china.org/docs/5.3/providers,ServiceProvider类,和绑定easy_kafka类:
lumen-clear-edition/common/Providers/KafkaServiceProvider.php
vi lumen-clear-edition/common/Service/Kafka/Kafka.php #自己写这个类的方法。
绑定的easy_kafka在这儿:
lumen-clear-edition/common/Facades/Kafka.php
ms/survey/app/Http/Controllers/Api/V1/ActivityController.php #路由@./ms/survey/routes/web.php
$router->group(['namespace'=>'Api\V1'], function () use ($router) {
$router->post('activity/form', ['uses' => 'ActivityController@form']);
ms/survey/app/Helpers/Client/SurveyClient.php
类的加载,common文件夹位置:
"autoload": {
"psr-4": {
"App\\": "app/",
"Common\\": "common/"
}
},
#composer dump-autoload --optimize
Do not run Composer as root/super user! See https://getcomposer.org/root for details
Generating optimized autoload files
生成文件在这儿(挪动一下文件放到新目录,建议重新运行一下这个:composer dump-autoload --optimize,再就是如果有PHP的OPcache得重新启动一下PHP-FPM或关闭掉Opcache,/usr/local/php/etc/php.d/opcache.ini ,opcache.enable=0):
./lumen-clear-edition/vendor/composer/autoload_psr4.php: 'Common\\' => array($baseDir . '/common'),
More:
#find ./ -mtime 0 -type f
./composer.json <== "Common\\": "common/"
./app/Http/Controllers/Api/V1/ActivityController.php
./app/Helpers/Client/SurveyClient.php
./common/Providers/UserServiceProvider.php
./common/Facades/User.php
./common/Services/User/User.php
./config/providers.php
composer dump-autoload --optimize改动的:
./vendor/autoload.php ==》return ComposerAutoloaderInit7d1969d6b0c0a5e119f2b7e0932178e2::getLoader();
./vendor/composer/autoload_psr4.php
./vendor/composer/autoload_static.php
./vendor/composer/autoload_classmap.php
./vendor/composer/autoload_files.php
./vendor/composer/ClassLoader.php
./vendor/composer/autoload_namespaces.php
./vendor/composer/autoload_real.php
访问URL: http://47.93.207.136/activity/survey
最后,这个Provider的类如何使用参考,但写得不是很明白,最新版本的和实际使用并不定一模一样的:http://www.cnblogs.com/cxscode/p/7569856.html
路由:https://lumen.laravel.com/docs/5.4
中文文档:http://laravelacademy.org/laravel-docs-5_4
5.4这个路由,老外写得很简单,这帮人可能是想你去看他的代码吧,有很多人在问:
http://www.thinksaas.cn/ask/question/22000/
class KafkaServiceProvider extends ServiceProvider{
return new \Common\Service\Kafka\Kafka(); #lumen-clear-edition/common/Service/Kafka/Kafka.php
lumen-clear-edition/common/Service/Kafka/Kafka.php 里:
做微服务:/usr/local/nginx/conf/vhosts/ms.conf
server_name 10.70.**.142;
root /data/www/ms/;
rewrite ^/(survey)/.*$ /$1/public/index.php last;
http://10.70.33.140/survey/public/index.php
/data/www/ms/survey/public/index.php
路由:
/data/www/ms/survey/routes/web.php
一)$app->group(['prefix' => 'private','namespace'=>'Api\V1'], function () use ($app) {
$app->get('survey/list', ['uses' => 'SurveyController@list']);
http://47.93.207.136/private/survey/list
app/Http/Controllers/Api/V1/SurveyController.php
二)$app->group(['namespace'=>'Api\V1'], function () use ($app) {
$app->get('activity/survey', ['uses' => 'ActivityController@survey']);
http://47.93.207.136/activity/survey
app/Http/Controllers/Api/V1/ActivityController.php 里有一行:
$client = new SurveyClient();
./app/Helpers/Client/SurveyClient.php:class SurveyClient{
Lumen (5.5.2) (Laravel Components 5.5.*),路由的写法有点不一样:
$router->group(['prefix' => 'private','namespace'=>'Api\V1'], function () use ($router) {
$router->get('survey/list', ['uses' => 'SurveyController@list']);
$router->group(['namespace'=>'Api\V1'], function () use ($router) {
$router->get('activity/survey', ['uses' => 'ActivityController@survey']);
调用层级及配置文件的一个情况,二是如何引入框架目录的入口:
./app/Http/Controllers/Api/V1/SurveyController.php:class SurveyController extends Controller{
/**
* 删除互动
*/
public function delete(Request $request){
$iid = intval($request->input('iid'));
$res = Survey::deleteSurvey($iid);#调用Models
return $this->out($res?1:0,$res?"success":"failed");
}
调用Models位置:
./app/Models/Survey.php: public static function deleteSurvey($iid){
配置文件:
/data/www/ms/survey/config_production/database.php
/data/www/ms/survey/config_production/kafka.php
/data/www/ms/survey/config_production/redis.php
vi /data/htdocs/lumen.levoo.com/bootstrap/app.php #引入框架目录
======================================================================================
Lumen 中可以使用的 Facades,查看源代码,可用清单如下(https://segmentfault.com/a/1190000002902055):
/survey/bootstrap/app.php:$app->withFacades(); $app->withFacades();
./lumen-clear-edition/vendor/laravel/lumen-framework/src/Application.php: public function withFacades($aliases = true, $userAliases = [])
./vendor/laravel/lumen-framework/src/Application.php
public function withAliases($userAliases = [])
if (! static::$aliasesRegistered) {
static::$aliasesRegistered = true;
$merged = array_merge($defaults, $userAliases);
foreach ($merged as $original => $alias) {
class_alias($original, $alias);
}
}
==========================================================================================
/usr/local/composer/composer.phar global require "laravel/lumen-installer"
https://lumen.laravel.com/docs/5.4#server-requirements 下面的:
chmod a+x /root/.config/composer/vendor/laravel/lumen-installer/lumen
/root/.config/composer/vendor/bin/lumen new lumen.levoo.com
/data/htdocs/lumen.levoo.com/blog/routes/web.php
你可以将所有路由都定义在routes/web.php中。最基本的 Lumen 路由接收:
http://laravelacademy.org/post/6337.html
$app->group(['prefix'=>'test'],function($app){
$app->get("/index",["uses" => "TestController@index"]);
});
【lumen】基础点记录使用:blog.csdn.net/imdingding/article/details/48679359
app/Http/routes.php中进行路由配置可以使用如下路由组的形式,在路由上lumen和laravel有一些区别
$app->group(['prefix' => 'scrollnews','namespace' => 'App\Http\Controllers'],function($app) {
$app->get('/','NewsController@showall');
$app->get('/{time}_{newpage}.htm','NewsController@showtime');
$app->get('/{newpage}.htm', 'NewsController@show');
});
http://123.57.252.183/test/index
hello Lumen (5.4.5) (Laravel Components 5.4.*)
/data/htdocs/lumen.levoo.com/app/Http/Controllers/TestController.php
<?php
namespace App\Http\Controllers;
use App\user; //新增部分
use Laravel\Lumen\Routing\Controller as BaseController;
use Illuminate\Http\Request;
class TestController extends BaseController
{
//直接传人sql方式操作数据库
function index(Request $request){
echo "hello Lumen (5.4.5) (Laravel Components 5.4.*)。";die;
return User::all();
}
}
以上实践来源及变通参看了:http://blog.5ibc.net/p/87952.html
PHP message: PHP Fatal error: Uncaught UnexpectedValueException: The stream or file "/data/htdocs/lumen.levoo.com/storage/logs/lumen.log" could not be opened: failed to open stream: Permission denied in /data/htdocs/lumen.levoo.com/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php:107
mkdir
chmod -R 755 /data/htdocs/lumen.levoo.com/storage
chown -R www /data/htdocs/lumen.levoo.com/storage
Controller类的写法:https://segmentfault.com/q/1010000002727820
/data/htdocs/lumen.levoo.com/blog/app/Http/Controllers/AccountController.php
关于数据库配置文件:
默认情况下, Lumen 使用单一的 .env 文件来配置你的应用, 然而, 你也可以使用 Laravel 风格 的配置方法.
/data/htdocs/lumen.levoo.com/vendor/laravel/lumen-framework/config/database.php
文件夹下对应的配置文件复制到根目录下的 config 文件里面就行.
https://lumen.laravel-china.org/docs/5.3/configuration#configuration-files
Redis:
CACHE_DRIVER=file
SESSION_DRIVER=redis
QUEUE_DRIVER=sync
REDIS_HOST=192.168.1.248
REDIS_PASSWORD=null
REDIS_PORT=6379
今天在部署服务器的时候,使用composer来安装依赖。遇到了如下情况,这块出错好像和Redis配置有关,得在.env里配置好并运行起来。
The Process class relies on proc_open, which is not available on your PHP installation.
[ErrorException]
proc_get_status() has been disabled for security reasons
开始的时候,我有些不知所措,于是冷静下来思考一番,然后goolge了一下
解决方法:
在php.ini中,找到disable_functions选项,看看后面是否有proc_open函数被禁用了,如果有的话,去掉即可
其实如果php的文档熟悉的话,你应该马上就能知道proc_open实际上是一个函数,是php用来和shell交互的函数,一般这种可以直接作用于操作系统的函数是非常不安全的,对于这种不安全的函数,总是要做一些措施来进行保护
php artisan make:migration create_table_cars --create=cars
php artisan make:migration create_table_cars --create=cars
Created Migration: 2017_03_04_160644_create_table_cars
/data/htdocs/lumen.levoo.com/database/migrations/2017_03_04_160644_create_table_cars.php
public function up()
{
Schema::create('cars', function (Blueprint $table) {
$table->increments('id');
$table->string('make');
$table->string('model');
$table->string('year');
$table->timestamps();
});
}
php artisan migrate
Migrated: 2017_03_04_161708_create_table_cars
migrations记录历史 /car 两个表:
id int(10) UNSIGNED
make varchar(255)
model varchar(255)
year varchar(255)
create d_attimestamp
问题实践来源:http://www.cnblogs.com/crisenchou/p/6237781.html
打开方法来自:http://www.codesec.net/view/497671.html?winzoom=1
Model这块和Controll层的配置:
1)Controll层, /data/htdocs/lumen.levoo.com/app/Http/Controllers/TestController.php
<?php
namespace App\Http\Controllers;
use App\Models\Information;
use App\Models\Collection;
//use App\User; //新增部分APP目录下
use App\Models\User; //App\Models\User目录下
use Laravel\Lumen\Routing\Controller as BaseController;
use Illuminate\Http\Request;
class TestController extends BaseController
{
//直接传人sql方式操作数据库
function index(Request $request){
/*
$UserModel = new User();
$result = $User::all(); //这样也成
$result2 = $UserModel::all2(); //这样也成
*/
$result = User::all();
$result2 = User::all2();//这个在Model自定义的all2也能被调用输出结果
print_r($result);
echo "<hr>";
print_r($result2);
}
}
2)Model层:/data/htdocs/lumen.levoo.com/app/Models/User.php
<?php
//namespace App; //这个得注释掉,容易和App/User.php发生错误引用。
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
//默认操作数据库的users表,需要定制的话请看文档,下面有自己的配置。
class User extends Model
{
/**
* The connection name for the model.
*
* @var string
*/
protected $connection = 'mysql';
/**
* 表名
*
* @var string
*/
protected $table = 'levoo_sns_user'; //指定操作表名
protected $primaryKey = "id"; //指定主键
public $timestamps = false;
protected $dateFormat = 'U';
static public function all2(){
$User = User::all();
return $User;
}
}
=================MVC模板学习=============================
/data/htdocs/lumen.levoo.com/app/Http/Controllers/TestController.php
<?php
namespace App\Http\Controllers;
use App\Models\Information;
use App\Models\Collection;
//use App\User; //新增部分APP目录下
use App\Models\User; //App\Models\User目录下
use Laravel\Lumen\Routing\Controller as BaseController;
use Illuminate\Http\Request;
class TestController extends BaseController
{
//直接传人sql方式操作数据库
function index(Request $request){
/*
$UserModel = new User();
$result = $User::all(); //这样也成
$result2 = $UserModel::all2(); //这样也成
*/
$result = User::all();
//$result2 = User::all2();//这个在Model自定义的all2也能被调用输出结果
/*
print_r($result);
echo "<hr>";
print_r($result2);
*/
//view()->exists('user');
return view('test', ['name' => 'jackX','results' => $result]);
}
}
vi /data/htdocs/lumen.levoo.com/resources/views/test.blade.php
<!-- 该视图存放 resources/views/greeting.php -->
<html>
<body>
<h1>Hello, {{ $name }}</h1>
<h1>Hello, {{ $name2 or 'Default' }}</h1>
<h1>Hello, {!! $name !!}</h1>
<h1>Array, {{ $results}}</h1>
<h1>Array, {!! $results !!}</h1>
Blade for each:<br>
<h1>
@foreach ($results as $user)
<ul>
<li>This is user {{ $user->id }}</li>
<li>This is user {{ $user->mobile }}</li>
<li>This is user {{ $user->fansmobile }}</li>
<li>This is user {{ $user->followedTime }}</li>
</ul>
@endforeach
</h1>
<h1>
@foreach ($results as $user)
<ul>
@if ($user->id == 1)
用户Id=1,标识一下:
@endif
<li>This is user {{ $user->id }}</li>
<li>This is user {{ $user->mobile }}</li>
<li>This is user {{ $user->fansmobile }}</li>
<li>This is user {{ $user->followedTime }}</li>
</ul>
@endforeach
</h1>
<h1>只显示id=1的区块:</h1>
<h1>
@foreach ($results as $user)
<ul>
@continue($user->id == 2)
<li>This is user {{ $user->id }}</li>
<li>This is user {{ $user->mobile }}</li>
<li>This is user {{ $user->fansmobile }}</li>
<li>This is user {{ $user->followedTime }}</li>
</ul>
@break($user->id == 1)
@endforeach
</h1>
</body>
</html>
模板输出:http://123.57.252.183/test/index
Hello, jackX
Hello, Default
Hello, jackX
Array, [{"id":1,"mobile":"1881**65108","fansmobile":"18810322234","followedTime":1211212121},{"id":2,"mobile":"1881**65108","fansmobile":"18810322232","followedTime":121212}]
Array, [{"id":1,"mobile":"1881**65108","fansmobile":"18810322234","followedTime":1211212121},{"id":2,"mobile":"1881**65108","fansmobile":"18810322232","followedTime":121212}]
Blade for each:
This is user 1
This is user 1881**65108
This is user 18810322234
This is user 1211212121
This is user 2
This is user 1881**65108
This is user 18810322232
This is user 121212
用户Id=1,标识一下:
This is user 1
This is user 1881**65108
This is user 18810322234
This is user 1211212121
This is user 2
This is user 1881**65108
This is user 18810322232
This is user 121212
只显示id=1的区块:
This is user 1
This is user 1881**65108
This is user 18810322234
This is user 1211212121
这个叫Blade的模板引擎解析成PHP的,也就是相当于没有啥大的损耗,如果它的算法还算先进的前提下,位置在:
/data/htdocs/lumen.levoo.com/storage/framework/views/9e3b647aebb6a248d1ae42408e87c3fc7f5bc520.php
为什么这么说呢,如下,我在想为何要搞成这样,PHP裸写不也一样么,像Ci框架啥的,思考思考,这样也算是能模板和程序分离罢:
<h1>只显示id=1的区块:</h1>
<h1>
<?php $__currentLoopData = $results; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $user): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<ul>
<?php if($user->id == 2) continue; ?>
<li>This is user <?php echo e($user->id); ?></li>
<li>This is user <?php echo e($user->mobile); ?></li>
<li>This is user <?php echo e($user->fansmobile); ?></li>
<li>This is user <?php echo e($user->followedTime); ?></li>
</ul>
<?php if($user->id == 1) break; ?>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</h1>
主要是对这个模板有一个大体理解,和Smarty啥的有一个初步了解,参考自:
http://laravelacademy.org/post/6780.html
======================================================================
Nginx配置文件:
server
{
listen 80 default_server;
server_name 101.200.189.210 lumen.levoo.com;
index index.html index.htm index.php;
root /data/htdocs/lumen.levoo.com/blog/public;
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
location ~ .*\.(php|php5)?$
{
fastcgi_pass unix:/dev/shm/php-fcgi.sock;
fastcgi_index index.php;
include fastcgi.conf;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
#if (!-f $request_filename){
# rewrite ^/(.+)$ /index.php?s=$1 last;
# break;
#}
}
access_log /data/logs/nginx/access_lumen_levoo.log;
}
上面location / {里被注释掉的也成,只是优雅度不够,这块好像手册有说明,我当时把 try_files $uri $uri/ /index.php?$query_string;放到location ~ .*\.(php|php5)?$ 里了,发现不对。
http://123.57.252.183/foo
Hello World
老外:
http://stackoverflow.com/questions/32281294/lumen-simple-route-request-doesnt-work
老外也有这个问题:
http://laravel.io/forum/05-08-2014-nginx-laravel-routing-shows-404?page=1
主从数据库配置(多台读库配置):
http://blog.sina.com.cn/s/blog_9bbafb790102win1.html
基于Lumen搭建一个OAUTH2认证的API框架:
http://www.bibihub.com/php/lumen-mobile-api-oauth-2-authentication/
========DB学习=========
基本使用
注意:如果你想要使用DB门面,应该取消bootstrap/app.php文件中$app->withFacades()调用前的注释
vi bootstrap/app.php
下面这个需要门面:
$app->get('/foo', function () use ($app) {
$results = app('db')->select("SELECT * FROM levoo_sns_user");
print_r($results);
$results = DB::select("SELECT * FROM levoo_sns_user");//这个需要门面
print_r($results);
return 'Hello World';
});
一些报错的日志:SQLSTATE[HY000] [2002] Connection refused
grep: ./survey/config_production/config_production: Too many levels of symbolic links
./survey/config_production/app.php: 'lumen_log_path'=>'/data/logs/lumen/survey.log', //框架日志
grep: ./survey/config/config_production: Too many levels of symbolic links
./survey/config/app.php: 'lumen_log_path'=>'/data/logs/lumen/survey.log', //框架日志
tail -f survey.log
Next Illuminate\Database\QueryException: SQLSTATE[HY000] [2002] Connection refused (SQL: select count(*) as aggregate from `survey` where `type` = 0 and `user` = 271 and `state` = 0) in /data/www/ms/lumen-clear-edition/vendor/illuminate/database/Connection.php:664
From:http://blog.csdn.net/wowkk/article/details/52104689
Lumen 5.5.*版本的Lumen,目录:lumen-clear-edition
composer create-project laravel/lumen lumen-clear-edition --prefer-dist "5.5.*" # proc_open,
vi ms/survey/bootstrap/app.php
require __DIR__.'/../config/providers.php'
vi ms/survey/config/providers.php
<?php
$app->register(Common\Providers\RedisServiceProvider::class);
$app->register(Common\Providers\MysqlServiceProvider::class);
$app->register(Common\Providers\KafkaServiceProvider::class);
$app->register(Common\Providers\EventServiceProvider::class);
$app->register(Common\Providers\QueueServiceProvider::class);
注册的文件在:
ls ./lumen-clear-edition/common/Providers
EventServiceProvider.php MysqlServiceProvider.php RedisServiceProvider.php
启动方法:
启动方法#服务提供者中注册一个视图 composer 则应该在 boot 方法中完成。此方法会在所有其它的服务提供者被注册后才被调用,意味着你能访问已经被框架注册的所有其它服务:https://lumen.laravel-china.org/docs/5.3/providers,ServiceProvider类,和绑定easy_kafka类:
lumen-clear-edition/common/Providers/KafkaServiceProvider.php
vi lumen-clear-edition/common/Service/Kafka/Kafka.php #自己写这个类的方法。
绑定的easy_kafka在这儿:
lumen-clear-edition/common/Facades/Kafka.php
ms/survey/app/Http/Controllers/Api/V1/ActivityController.php #路由@./ms/survey/routes/web.php
$router->group(['namespace'=>'Api\V1'], function () use ($router) {
$router->post('activity/form', ['uses' => 'ActivityController@form']);
ms/survey/app/Helpers/Client/SurveyClient.php
类的加载,common文件夹位置:
"autoload": {
"psr-4": {
"App\\": "app/",
"Common\\": "common/"
}
},
#composer dump-autoload --optimize
Do not run Composer as root/super user! See https://getcomposer.org/root for details
Generating optimized autoload files
生成文件在这儿(挪动一下文件放到新目录,建议重新运行一下这个:composer dump-autoload --optimize,再就是如果有PHP的OPcache得重新启动一下PHP-FPM或关闭掉Opcache,/usr/local/php/etc/php.d/opcache.ini ,opcache.enable=0):
./lumen-clear-edition/vendor/composer/autoload_psr4.php: 'Common\\' => array($baseDir . '/common'),
More:
#find ./ -mtime 0 -type f
./composer.json <== "Common\\": "common/"
./app/Http/Controllers/Api/V1/ActivityController.php
./app/Helpers/Client/SurveyClient.php
./common/Providers/UserServiceProvider.php
./common/Facades/User.php
./common/Services/User/User.php
./config/providers.php
composer dump-autoload --optimize改动的:
./vendor/autoload.php ==》return ComposerAutoloaderInit7d1969d6b0c0a5e119f2b7e0932178e2::getLoader();
./vendor/composer/autoload_psr4.php
./vendor/composer/autoload_static.php
./vendor/composer/autoload_classmap.php
./vendor/composer/autoload_files.php
./vendor/composer/ClassLoader.php
./vendor/composer/autoload_namespaces.php
./vendor/composer/autoload_real.php
访问URL: http://47.93.207.136/activity/survey
最后,这个Provider的类如何使用参考,但写得不是很明白,最新版本的和实际使用并不定一模一样的:http://www.cnblogs.com/cxscode/p/7569856.html
路由:https://lumen.laravel.com/docs/5.4
中文文档:http://laravelacademy.org/laravel-docs-5_4
5.4这个路由,老外写得很简单,这帮人可能是想你去看他的代码吧,有很多人在问:
http://www.thinksaas.cn/ask/question/22000/
class KafkaServiceProvider extends ServiceProvider{
return new \Common\Service\Kafka\Kafka(); #lumen-clear-edition/common/Service/Kafka/Kafka.php
lumen-clear-edition/common/Service/Kafka/Kafka.php 里:
做微服务:/usr/local/nginx/conf/vhosts/ms.conf
server_name 10.70.**.142;
root /data/www/ms/;
rewrite ^/(survey)/.*$ /$1/public/index.php last;
http://10.70.33.140/survey/public/index.php
/data/www/ms/survey/public/index.php
路由:
/data/www/ms/survey/routes/web.php
一)$app->group(['prefix' => 'private','namespace'=>'Api\V1'], function () use ($app) {
$app->get('survey/list', ['uses' => 'SurveyController@list']);
http://47.93.207.136/private/survey/list
app/Http/Controllers/Api/V1/SurveyController.php
二)$app->group(['namespace'=>'Api\V1'], function () use ($app) {
$app->get('activity/survey', ['uses' => 'ActivityController@survey']);
http://47.93.207.136/activity/survey
app/Http/Controllers/Api/V1/ActivityController.php 里有一行:
$client = new SurveyClient();
./app/Helpers/Client/SurveyClient.php:class SurveyClient{
Lumen (5.5.2) (Laravel Components 5.5.*),路由的写法有点不一样:
$router->group(['prefix' => 'private','namespace'=>'Api\V1'], function () use ($router) {
$router->get('survey/list', ['uses' => 'SurveyController@list']);
$router->group(['namespace'=>'Api\V1'], function () use ($router) {
$router->get('activity/survey', ['uses' => 'ActivityController@survey']);
调用层级及配置文件的一个情况,二是如何引入框架目录的入口:
./app/Http/Controllers/Api/V1/SurveyController.php:class SurveyController extends Controller{
/**
* 删除互动
*/
public function delete(Request $request){
$iid = intval($request->input('iid'));
$res = Survey::deleteSurvey($iid);#调用Models
return $this->out($res?1:0,$res?"success":"failed");
}
调用Models位置:
./app/Models/Survey.php: public static function deleteSurvey($iid){
配置文件:
/data/www/ms/survey/config_production/database.php
/data/www/ms/survey/config_production/kafka.php
/data/www/ms/survey/config_production/redis.php
vi /data/htdocs/lumen.levoo.com/bootstrap/app.php #引入框架目录
======================================================================================
Lumen 中可以使用的 Facades,查看源代码,可用清单如下(https://segmentfault.com/a/1190000002902055):
/survey/bootstrap/app.php:$app->withFacades(); $app->withFacades();
./lumen-clear-edition/vendor/laravel/lumen-framework/src/Application.php: public function withFacades($aliases = true, $userAliases = [])
./vendor/laravel/lumen-framework/src/Application.php
public function withAliases($userAliases = [])
if (! static::$aliasesRegistered) {
static::$aliasesRegistered = true;
$merged = array_merge($defaults, $userAliases);
foreach ($merged as $original => $alias) {
class_alias($original, $alias);
}
}
==========================================================================================
/usr/local/composer/composer.phar global require "laravel/lumen-installer"
https://lumen.laravel.com/docs/5.4#server-requirements 下面的:
chmod a+x /root/.config/composer/vendor/laravel/lumen-installer/lumen
/root/.config/composer/vendor/bin/lumen new lumen.levoo.com
/data/htdocs/lumen.levoo.com/blog/routes/web.php
你可以将所有路由都定义在routes/web.php中。最基本的 Lumen 路由接收:
http://laravelacademy.org/post/6337.html
$app->group(['prefix'=>'test'],function($app){
$app->get("/index",["uses" => "TestController@index"]);
});
【lumen】基础点记录使用:blog.csdn.net/imdingding/article/details/48679359
app/Http/routes.php中进行路由配置可以使用如下路由组的形式,在路由上lumen和laravel有一些区别
$app->group(['prefix' => 'scrollnews','namespace' => 'App\Http\Controllers'],function($app) {
$app->get('/','NewsController@showall');
$app->get('/{time}_{newpage}.htm','NewsController@showtime');
$app->get('/{newpage}.htm', 'NewsController@show');
});
http://123.57.252.183/test/index
hello Lumen (5.4.5) (Laravel Components 5.4.*)
/data/htdocs/lumen.levoo.com/app/Http/Controllers/TestController.php
<?php
namespace App\Http\Controllers;
use App\user; //新增部分
use Laravel\Lumen\Routing\Controller as BaseController;
use Illuminate\Http\Request;
class TestController extends BaseController
{
//直接传人sql方式操作数据库
function index(Request $request){
echo "hello Lumen (5.4.5) (Laravel Components 5.4.*)。";die;
return User::all();
}
}
以上实践来源及变通参看了:http://blog.5ibc.net/p/87952.html
PHP message: PHP Fatal error: Uncaught UnexpectedValueException: The stream or file "/data/htdocs/lumen.levoo.com/storage/logs/lumen.log" could not be opened: failed to open stream: Permission denied in /data/htdocs/lumen.levoo.com/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php:107
mkdir
chmod -R 755 /data/htdocs/lumen.levoo.com/storage
chown -R www /data/htdocs/lumen.levoo.com/storage
Controller类的写法:https://segmentfault.com/q/1010000002727820
/data/htdocs/lumen.levoo.com/blog/app/Http/Controllers/AccountController.php
关于数据库配置文件:
默认情况下, Lumen 使用单一的 .env 文件来配置你的应用, 然而, 你也可以使用 Laravel 风格 的配置方法.
/data/htdocs/lumen.levoo.com/vendor/laravel/lumen-framework/config/database.php
文件夹下对应的配置文件复制到根目录下的 config 文件里面就行.
https://lumen.laravel-china.org/docs/5.3/configuration#configuration-files
Redis:
CACHE_DRIVER=file
SESSION_DRIVER=redis
QUEUE_DRIVER=sync
REDIS_HOST=192.168.1.248
REDIS_PASSWORD=null
REDIS_PORT=6379
今天在部署服务器的时候,使用composer来安装依赖。遇到了如下情况,这块出错好像和Redis配置有关,得在.env里配置好并运行起来。
The Process class relies on proc_open, which is not available on your PHP installation.
[ErrorException]
proc_get_status() has been disabled for security reasons
开始的时候,我有些不知所措,于是冷静下来思考一番,然后goolge了一下
解决方法:
在php.ini中,找到disable_functions选项,看看后面是否有proc_open函数被禁用了,如果有的话,去掉即可
其实如果php的文档熟悉的话,你应该马上就能知道proc_open实际上是一个函数,是php用来和shell交互的函数,一般这种可以直接作用于操作系统的函数是非常不安全的,对于这种不安全的函数,总是要做一些措施来进行保护
php artisan make:migration create_table_cars --create=cars
php artisan make:migration create_table_cars --create=cars
Created Migration: 2017_03_04_160644_create_table_cars
/data/htdocs/lumen.levoo.com/database/migrations/2017_03_04_160644_create_table_cars.php
public function up()
{
Schema::create('cars', function (Blueprint $table) {
$table->increments('id');
$table->string('make');
$table->string('model');
$table->string('year');
$table->timestamps();
});
}
php artisan migrate
Migrated: 2017_03_04_161708_create_table_cars
migrations记录历史 /car 两个表:
id int(10) UNSIGNED
make varchar(255)
model varchar(255)
year varchar(255)
create d_attimestamp
问题实践来源:http://www.cnblogs.com/crisenchou/p/6237781.html
打开方法来自:http://www.codesec.net/view/497671.html?winzoom=1
Model这块和Controll层的配置:
1)Controll层, /data/htdocs/lumen.levoo.com/app/Http/Controllers/TestController.php
<?php
namespace App\Http\Controllers;
use App\Models\Information;
use App\Models\Collection;
//use App\User; //新增部分APP目录下
use App\Models\User; //App\Models\User目录下
use Laravel\Lumen\Routing\Controller as BaseController;
use Illuminate\Http\Request;
class TestController extends BaseController
{
//直接传人sql方式操作数据库
function index(Request $request){
/*
$UserModel = new User();
$result = $User::all(); //这样也成
$result2 = $UserModel::all2(); //这样也成
*/
$result = User::all();
$result2 = User::all2();//这个在Model自定义的all2也能被调用输出结果
print_r($result);
echo "<hr>";
print_r($result2);
}
}
2)Model层:/data/htdocs/lumen.levoo.com/app/Models/User.php
<?php
//namespace App; //这个得注释掉,容易和App/User.php发生错误引用。
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
//默认操作数据库的users表,需要定制的话请看文档,下面有自己的配置。
class User extends Model
{
/**
* The connection name for the model.
*
* @var string
*/
protected $connection = 'mysql';
/**
* 表名
*
* @var string
*/
protected $table = 'levoo_sns_user'; //指定操作表名
protected $primaryKey = "id"; //指定主键
public $timestamps = false;
protected $dateFormat = 'U';
static public function all2(){
$User = User::all();
return $User;
}
}
=================MVC模板学习=============================
/data/htdocs/lumen.levoo.com/app/Http/Controllers/TestController.php
<?php
namespace App\Http\Controllers;
use App\Models\Information;
use App\Models\Collection;
//use App\User; //新增部分APP目录下
use App\Models\User; //App\Models\User目录下
use Laravel\Lumen\Routing\Controller as BaseController;
use Illuminate\Http\Request;
class TestController extends BaseController
{
//直接传人sql方式操作数据库
function index(Request $request){
/*
$UserModel = new User();
$result = $User::all(); //这样也成
$result2 = $UserModel::all2(); //这样也成
*/
$result = User::all();
//$result2 = User::all2();//这个在Model自定义的all2也能被调用输出结果
/*
print_r($result);
echo "<hr>";
print_r($result2);
*/
//view()->exists('user');
return view('test', ['name' => 'jackX','results' => $result]);
}
}
vi /data/htdocs/lumen.levoo.com/resources/views/test.blade.php
<!-- 该视图存放 resources/views/greeting.php -->
<html>
<body>
<h1>Hello, {{ $name }}</h1>
<h1>Hello, {{ $name2 or 'Default' }}</h1>
<h1>Hello, {!! $name !!}</h1>
<h1>Array, {{ $results}}</h1>
<h1>Array, {!! $results !!}</h1>
Blade for each:<br>
<h1>
@foreach ($results as $user)
<ul>
<li>This is user {{ $user->id }}</li>
<li>This is user {{ $user->mobile }}</li>
<li>This is user {{ $user->fansmobile }}</li>
<li>This is user {{ $user->followedTime }}</li>
</ul>
@endforeach
</h1>
<h1>
@foreach ($results as $user)
<ul>
@if ($user->id == 1)
用户Id=1,标识一下:
@endif
<li>This is user {{ $user->id }}</li>
<li>This is user {{ $user->mobile }}</li>
<li>This is user {{ $user->fansmobile }}</li>
<li>This is user {{ $user->followedTime }}</li>
</ul>
@endforeach
</h1>
<h1>只显示id=1的区块:</h1>
<h1>
@foreach ($results as $user)
<ul>
@continue($user->id == 2)
<li>This is user {{ $user->id }}</li>
<li>This is user {{ $user->mobile }}</li>
<li>This is user {{ $user->fansmobile }}</li>
<li>This is user {{ $user->followedTime }}</li>
</ul>
@break($user->id == 1)
@endforeach
</h1>
</body>
</html>
模板输出:http://123.57.252.183/test/index
Hello, jackX
Hello, Default
Hello, jackX
Array, [{"id":1,"mobile":"1881**65108","fansmobile":"18810322234","followedTime":1211212121},{"id":2,"mobile":"1881**65108","fansmobile":"18810322232","followedTime":121212}]
Array, [{"id":1,"mobile":"1881**65108","fansmobile":"18810322234","followedTime":1211212121},{"id":2,"mobile":"1881**65108","fansmobile":"18810322232","followedTime":121212}]
Blade for each:
This is user 1
This is user 1881**65108
This is user 18810322234
This is user 1211212121
This is user 2
This is user 1881**65108
This is user 18810322232
This is user 121212
用户Id=1,标识一下:
This is user 1
This is user 1881**65108
This is user 18810322234
This is user 1211212121
This is user 2
This is user 1881**65108
This is user 18810322232
This is user 121212
只显示id=1的区块:
This is user 1
This is user 1881**65108
This is user 18810322234
This is user 1211212121
这个叫Blade的模板引擎解析成PHP的,也就是相当于没有啥大的损耗,如果它的算法还算先进的前提下,位置在:
/data/htdocs/lumen.levoo.com/storage/framework/views/9e3b647aebb6a248d1ae42408e87c3fc7f5bc520.php
为什么这么说呢,如下,我在想为何要搞成这样,PHP裸写不也一样么,像Ci框架啥的,思考思考,这样也算是能模板和程序分离罢:
<h1>只显示id=1的区块:</h1>
<h1>
<?php $__currentLoopData = $results; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $user): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<ul>
<?php if($user->id == 2) continue; ?>
<li>This is user <?php echo e($user->id); ?></li>
<li>This is user <?php echo e($user->mobile); ?></li>
<li>This is user <?php echo e($user->fansmobile); ?></li>
<li>This is user <?php echo e($user->followedTime); ?></li>
</ul>
<?php if($user->id == 1) break; ?>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</h1>
主要是对这个模板有一个大体理解,和Smarty啥的有一个初步了解,参考自:
http://laravelacademy.org/post/6780.html
======================================================================
Nginx配置文件:
server
{
listen 80 default_server;
server_name 101.200.189.210 lumen.levoo.com;
index index.html index.htm index.php;
root /data/htdocs/lumen.levoo.com/blog/public;
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
location ~ .*\.(php|php5)?$
{
fastcgi_pass unix:/dev/shm/php-fcgi.sock;
fastcgi_index index.php;
include fastcgi.conf;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
#if (!-f $request_filename){
# rewrite ^/(.+)$ /index.php?s=$1 last;
# break;
#}
}
access_log /data/logs/nginx/access_lumen_levoo.log;
}
上面location / {里被注释掉的也成,只是优雅度不够,这块好像手册有说明,我当时把 try_files $uri $uri/ /index.php?$query_string;放到location ~ .*\.(php|php5)?$ 里了,发现不对。
http://123.57.252.183/foo
Hello World
老外:
http://stackoverflow.com/questions/32281294/lumen-simple-route-request-doesnt-work
老外也有这个问题:
http://laravel.io/forum/05-08-2014-nginx-laravel-routing-shows-404?page=1
主从数据库配置(多台读库配置):
http://blog.sina.com.cn/s/blog_9bbafb790102win1.html
基于Lumen搭建一个OAUTH2认证的API框架:
http://www.bibihub.com/php/lumen-mobile-api-oauth-2-authentication/
========DB学习=========
基本使用
注意:如果你想要使用DB门面,应该取消bootstrap/app.php文件中$app->withFacades()调用前的注释
vi bootstrap/app.php
下面这个需要门面:
$app->get('/foo', function () use ($app) {
$results = app('db')->select("SELECT * FROM levoo_sns_user");
print_r($results);
$results = DB::select("SELECT * FROM levoo_sns_user");//这个需要门面
print_r($results);
return 'Hello World';
});
一些报错的日志:SQLSTATE[HY000] [2002] Connection refused
grep: ./survey/config_production/config_production: Too many levels of symbolic links
./survey/config_production/app.php: 'lumen_log_path'=>'/data/logs/lumen/survey.log', //框架日志
grep: ./survey/config/config_production: Too many levels of symbolic links
./survey/config/app.php: 'lumen_log_path'=>'/data/logs/lumen/survey.log', //框架日志
tail -f survey.log
Next Illuminate\Database\QueryException: SQLSTATE[HY000] [2002] Connection refused (SQL: select count(*) as aggregate from `survey` where `type` = 0 and `user` = 271 and `state` = 0) in /data/www/ms/lumen-clear-edition/vendor/illuminate/database/Connection.php:664
[实践OK]Linux下 php环境安装、配置composer,使用composer安装laravel/lumen、zan等框架,写一个读取数据库的。
Php/Js/Shell/Go jackxiang 2017-1-10 23:17
/usr/bin/env: PHP: No such file or directory报错
su www
[root@VM-0-15-centos ~]# curl -sS https://getcomposer.org/installer | php
#把composer.phar转移之bin目录以便全局使用
[root@VM-0-15-centos ~]# mv composer.phar /usr/local/bin/composer
#展示版本信息说明成功
[root@VM-0-15-centos ~]# composer -v
如果出现这个提示,是因为composer不建议root账号运行,可以输入y,或者切换账号
Do not run Composer as root/super user! See https://getcomposer.org/root for details
Continue as root/super user [yes]?
sudo -u www -H/usr/local/composer/bin/composer config repo.packagist composer https://mirrors.aliyun.com/composer/
[ErrorException]
touch(): Unable to create file /home/www/.config/composer/config.json because No such file or directory
#composer clear-cache
Do not run Composer as root/super user! See https://getcomposer.org/root for details
Continue as root/super user [yes]? yes
Cache directory does not exist (cache-vcs-dir):
Cache directory does not exist (cache-repo-dir):
Cache directory does not exist (cache-files-dir):
Clearing cache (cache-dir): /root/.cache/composer
如果是其它用户就是在它的家目录下面建立配置文件。
[root@nexus-repo-10-10-0-109:/data/www/l.levoo.com]
#sudo -u www -H /usr/local/composer/composer update
Loading composer repositories with package information
[root@nexus-repo-10-10-0-109:/data/www/l.levoo.com]
#sudo -u www -H /usr/local/composer/composer update
......
Package operations: 41 installs, 14 updates, 38 removals
Failed to download dragonmantank/cron-expression from dist: The zip extension is missing and unzip/7z commands cannot be called as proc_open is disabled, skipping.
Your command-line PHP is using multiple ini files. Run `php --ini` to show them.
Now trying to download from source
PHP的一些安全函数禁用了,打开就成功了:
- Upgrading easyswoole/task (1.0.5 => 1.1.2): Extracting archive
- Upgrading easyswoole/log (1.0.3 => 1.1.1): Extracting archive
Generating autoload files
28 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
然后执行compser up
或者备份composer.lock
==========================================================================
composer config -g repo.packagist composer https://packagist.phpcomposer.com #换国内镜像URL地址。
composer是一个可执行命令,你在一个空目录下写一个composer.json
然后执行composer update,就能生成。
====================两步:软链接composer/PATH/下载autoloader===========================
软链接加PATH:
easy swoole 3.0.9 官方并不是最新的,换换阿里云镜像:
全局替换:
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
composer clear-cache # 此步奏选泽性操作,清除所有 package 缓存。
composer clear-cache
Cache directory does not exist (cache-vcs-dir):
Clearing cache (cache-repo-dir): /data/www/.cache/composer/repo
Clearing cache (cache-files-dir): /data/www/.cache/composer/files
Clearing cache (cache-dir): /data/www/.cache/composer
当前项目替换: (注意:不让root用户运行,用www用户)
cd 项目目录
composer config repo.packagist composer https://mirrors.aliyun.com/composer/
不重新开终端不会生效,则可直接导入变量:
source /etc/profile.d/composer.sh
cd /usr/local/kafka-php
cat composer.json
{
"require": {
"nmred/kafka-php": "0.2.*"
}
}
composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 3 installs, 0 updates, 0 removals
- Installing amphp/amp (v1.2.2): Downloading (100%)
- Installing psr/log (1.0.2): Downloading (100%)
- Installing nmred/kafka-php (v0.2.0.8): Downloading (100%)
Writing lock file
Generating autoload files
cd /usr/local/kafka-php
composer.json composer.lock vendor
目的是看下同事所说的Kafka死光了,kafka-php会退出的问题:
https://github.com/weiboad/kafka-php
===========================================================================
cd /usr/local/composer ,sudo -u www -H composer.phar install ,会去读取:/usr/local/composer/composer.json文件。
chown -R www.www /data/htdocs/sd.levoo.com #否则会报:/data/htdocs/sd.levoo.com/vendor does not exist and could not be created.
sudo -u www -H composer.phar install
实践如下:
vi /etc/sudoers
Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/mysql/bin:/usr/local/composer:/usr/local/php/bin
#sudo -u www -H composer.phar config -g repo.packagist composer https://packagist.phpcomposer.com
[ErrorException]
touch(): Unable to create file /home/www/.composer/config.json because No such file or directory
#mkdir /home/www
#chown www.www /home/www
#chmod 755 /home/www
#sudo -u www -H composer.phar config -g repo.packagist composer https://packagist.phpcomposer.com
#sudo -u www -H composer.phar install
Composer could not find a composer.json file in /usr/local/composer
To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section
建立composer.json如下,可以根据需要添加你所依赖的库,但下面一定得包含在内,autoload必须要指定app和test的目录不得省略。
{
"require": {
"tmtbe/swooledistributed":">2.0.0"
},
"autoload": {
"psr-4": {
"app\\": "src/app",
"test\\": "src/test"
}
}
}
/usr/local/composer/composer.json
运行:
#sudo -u www -H composer.phar install
Loading composer repositories with package information
Updating dependencies (including require-dev)
[RuntimeException]
/usr/local/composer/vendor does not exist and could not be created.
[RuntimeException]
/usr/local/composer/vendor/symfony/intl does not exist and could not be created
- Installing symfony/intl (v3.3.8):
[Symfony\Component\Process\Exception\RuntimeException]
The Process class relies on proc_open, which is not available on your PHP installation.
PHP需有proc_open,得从PHP的php.ini里给去掉:
; disable_functions = chroot,chgrp,chown,shell_exec,proc_open,proc_get_status,ini_alter,ini_
restore,dl,openlog,syslog,readlink,symlink,popepassthru,stream_socket_server,fsocket
#sudo -u www -H composer.phar install
Composer could not find a composer.json file in /usr/local/php/etc
To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section
得cd到:/usr/local/composer 里,再执行:sudo -u www -H composer.phar install
#sudo -u www -H composer.phar install
[ErrorException]
proc_get_status() has been disabled for security reasons 和上面一样:得从PHP的php.ini里给去掉。
[RuntimeException]
Could not delete /usr/local/composer/vendor/symfony/intl:
chown -R www.www /usr/local/composer/vendor
[ErrorException]
file_put_contents(./composer.lock): failed to open stream: Permission denied #写入/usr/local/composer/composer.lock权限不够。
[root@gitlab-jenkins_php-redis_123.57.252.183:/usr/local]
#chown www.www composer
#sudo -u www -H composer.phar install
Loading composer repositories with package information
Updating dependencies (including require-dev)
Nothing to install or update
Writing lock file
Generating autoload files
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
From:https://getcomposer.org/download/
http://blog.csdn.net/yoywow/article/details/52074512
二、使用composer安装laravel/lumen:
遇到问题:
修改 composer 的全局配置文件(推荐方式)
打开命令行窗口(windows用户)或控制台(Linux、Mac 用户)并执行如下命令:
[root@a composer]# chtdocs
[root@a htdocs]# cd lumen.levoo.com/
[root@a lumen.levoo.com]# /usr/local/composer/composer.phar global require "laravel/lumen-installer"
Changed current directory to /root/.config/composer
Do not run Composer as root/super user! See https://getcomposer.org/root for details
compser 执行命令提示do not run composer as root/super !
这个是因为composer为了防止非法脚本在root下执行,解决办法随便切换到非root用户即可
su www
mkdir -p /home/www/.cache
chown -R www:www /home/www/.cache
composer require easyswoole/hot-reload
Cannot create cache directory /home/www/.cache/composer/repo/https---mirrors.aliyun.com-composer/, or directory is not writable. Proceeding without cache
Cannot create cache directory /home/www/.cache/composer/files/, or directory is not writable. Proceeding without cache
Using version ^0.1.2 for easyswoole/hot-reload
./composer.json has been updated
PATH变量设置Ok的方法如下:
打开~/.bashrc
sudo vim ~/.bashrc
添加行:
export PATH=$PATH:/home/lumen/.config/composer/vendor/bin
用Linux系统。比如要把/etc/apache/bin目录添加到PATH中,方法有三:
1.#PATH=c/etc/apache/bin
使用这种方法,只对当前会话有效,也就是说每当登出或注销系统以后,PATH 设置就会失效
2.#vi /etc/profile
在适当位置添加 PATH=$PATH:/etc/apache/bin (注意:= 即等号两边不能有任何空格)
这种方法最好,除非你手动强制修改PATH的值,否则将不会被改变
3.#vi ~/.bash_profile
修改PATH行,把/etc/apache/bin添加进去
这种方法是针对用户起作用的
From:http://opsmysql.blog.51cto.com/2238445/665990
lumen没有成功:
useradd lumen
su lumen
cd /data/htdocs/laravel.levoo.com
/usr/local/composer/composer.phar config -g repo.packagist composer https://packagist.phpcomposer.com
进行上述设置后,laravel有门,能下载了:
[lumen@a laravel.levoo.com]$ pwd
/data/htdocs/laravel.levoo.com
[lumen@a laravel.levoo.com]$ /usr/local/composer/composer.phar global require "laravel/lumen-installer"
Changed current directory to /home/lumen/.config/composer
Using version ^1.0 for laravel/lumen-installer
./composer.json has been created
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 10 installs, 0 updates, 0 removals
- Installing symfony/process (v3.2.1) Downloading: 100%
- Installing psr/log (1.0.2) Downloading: 100%
- Installing symfony/debug (v3.2.1) Downloading: 100%
- Installing symfony/polyfill-mbstring (v1.3.0) Downloading: 100%
- Installing symfony/console (v3.2.1) Downloading: 100%
- Installing guzzlehttp/promises (v1.3.1) Downloading: 100%
- Installing psr/http-message (1.0.1) Downloading: 100%
- Installing guzzlehttp/psr7 (1.3.1) Downloading: 100%
- Installing guzzlehttp/guzzle (6.2.2) Downloading: 100%
- Installing laravel/lumen-installer (v1.0.2) Downloading: 100%
symfony/console suggests installing symfony/event-dispatcher ()
symfony/console suggests installing symfony/filesystem ()
Writing lock file
Generating autoload files
生成文件如下:
[lumen@a composer]$ pwd
/home/lumen/.config/composer
[lumen@a composer]$ ls /home/lumen/.config/composer
auth.json composer.json composer.lock config.json vendor
开始学习数据库:
http://blog.csdn.net/wowkk/article/details/52104689
/data/htdocs/lumen.levoo.com/blog/.env
APP_ENV=local
APP_DEBUG=true
APP_KEY=
APP_TIMEZONE=UTC
DB_CONNECTION=mysql
DB_HOST=10.44.202.177
DB_PORT=3306
DB_DATABASE=levoo_egg
DB_USERNAME=levoo
DB_PASSWORD=new@levoo.com
CACHE_DRIVER=memcached
QUEUE_DRIVER=sync
/data/htdocs/lumen.levoo.com/blog/app/Http/Controllers/AccountController.PHP
/data/htdocs/lumen.levoo.com/blog/routes/web.php
<?php
$app->group(["namespace"=>"App\Http\Controllers"], function()use($app){
//账户控制器
$app->get("/AccountController",["uses" => "AccountController@accountController"]);
});
model:/data/htdocs/lumen.levoo.com/blog/app/Models/User.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
}
在app/Http/Controllers目录下AccountController.php,修改为
<?php
namespace App\Http\Controllers;
use App\user; //新增部分
use Laravel\Lumen\Routing\Controller as BaseController;
use Illuminate\Http\Request;
class AccountController extends BaseController
{
//直接传人sql方式操作数据库
function accountController(Request $request){
return User::all();
}
}
http://101.200.189.210/AccountController/accountController
su www
[root@VM-0-15-centos ~]# curl -sS https://getcomposer.org/installer | php
#把composer.phar转移之bin目录以便全局使用
[root@VM-0-15-centos ~]# mv composer.phar /usr/local/bin/composer
#展示版本信息说明成功
[root@VM-0-15-centos ~]# composer -v
如果出现这个提示,是因为composer不建议root账号运行,可以输入y,或者切换账号
Do not run Composer as root/super user! See https://getcomposer.org/root for details
Continue as root/super user [yes]?
sudo -u www -H/usr/local/composer/bin/composer config repo.packagist composer https://mirrors.aliyun.com/composer/
[ErrorException]
touch(): Unable to create file /home/www/.config/composer/config.json because No such file or directory
#composer clear-cache
Do not run Composer as root/super user! See https://getcomposer.org/root for details
Continue as root/super user [yes]? yes
Cache directory does not exist (cache-vcs-dir):
Cache directory does not exist (cache-repo-dir):
Cache directory does not exist (cache-files-dir):
Clearing cache (cache-dir): /root/.cache/composer
如果是其它用户就是在它的家目录下面建立配置文件。
[root@nexus-repo-10-10-0-109:/data/www/l.levoo.com]
#sudo -u www -H /usr/local/composer/composer update
Loading composer repositories with package information
[root@nexus-repo-10-10-0-109:/data/www/l.levoo.com]
#sudo -u www -H /usr/local/composer/composer update
......
Package operations: 41 installs, 14 updates, 38 removals
Failed to download dragonmantank/cron-expression from dist: The zip extension is missing and unzip/7z commands cannot be called as proc_open is disabled, skipping.
Your command-line PHP is using multiple ini files. Run `php --ini` to show them.
Now trying to download from source
PHP的一些安全函数禁用了,打开就成功了:
- Upgrading easyswoole/task (1.0.5 => 1.1.2): Extracting archive
- Upgrading easyswoole/log (1.0.3 => 1.1.1): Extracting archive
Generating autoload files
28 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
然后执行compser up
或者备份composer.lock
==========================================================================
composer config -g repo.packagist composer https://packagist.phpcomposer.com #换国内镜像URL地址。
composer是一个可执行命令,你在一个空目录下写一个composer.json
然后执行composer update,就能生成。
====================两步:软链接composer/PATH/下载autoloader===========================
软链接加PATH:
easy swoole 3.0.9 官方并不是最新的,换换阿里云镜像:
全局替换:
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
composer clear-cache # 此步奏选泽性操作,清除所有 package 缓存。
composer clear-cache
Cache directory does not exist (cache-vcs-dir):
Clearing cache (cache-repo-dir): /data/www/.cache/composer/repo
Clearing cache (cache-files-dir): /data/www/.cache/composer/files
Clearing cache (cache-dir): /data/www/.cache/composer
当前项目替换: (注意:不让root用户运行,用www用户)
cd 项目目录
composer config repo.packagist composer https://mirrors.aliyun.com/composer/
不重新开终端不会生效,则可直接导入变量:
source /etc/profile.d/composer.sh
cd /usr/local/kafka-php
cat composer.json
{
"require": {
"nmred/kafka-php": "0.2.*"
}
}
composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 3 installs, 0 updates, 0 removals
- Installing amphp/amp (v1.2.2): Downloading (100%)
- Installing psr/log (1.0.2): Downloading (100%)
- Installing nmred/kafka-php (v0.2.0.8): Downloading (100%)
Writing lock file
Generating autoload files
cd /usr/local/kafka-php
composer.json composer.lock vendor
目的是看下同事所说的Kafka死光了,kafka-php会退出的问题:
https://github.com/weiboad/kafka-php
===========================================================================
cd /usr/local/composer ,sudo -u www -H composer.phar install ,会去读取:/usr/local/composer/composer.json文件。
chown -R www.www /data/htdocs/sd.levoo.com #否则会报:/data/htdocs/sd.levoo.com/vendor does not exist and could not be created.
sudo -u www -H composer.phar install
实践如下:
vi /etc/sudoers
Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/mysql/bin:/usr/local/composer:/usr/local/php/bin
#sudo -u www -H composer.phar config -g repo.packagist composer https://packagist.phpcomposer.com
[ErrorException]
touch(): Unable to create file /home/www/.composer/config.json because No such file or directory
#mkdir /home/www
#chown www.www /home/www
#chmod 755 /home/www
#sudo -u www -H composer.phar config -g repo.packagist composer https://packagist.phpcomposer.com
#sudo -u www -H composer.phar install
Composer could not find a composer.json file in /usr/local/composer
To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section
建立composer.json如下,可以根据需要添加你所依赖的库,但下面一定得包含在内,autoload必须要指定app和test的目录不得省略。
{
"require": {
"tmtbe/swooledistributed":">2.0.0"
},
"autoload": {
"psr-4": {
"app\\": "src/app",
"test\\": "src/test"
}
}
}
/usr/local/composer/composer.json
运行:
#sudo -u www -H composer.phar install
Loading composer repositories with package information
Updating dependencies (including require-dev)
[RuntimeException]
/usr/local/composer/vendor does not exist and could not be created.
[RuntimeException]
/usr/local/composer/vendor/symfony/intl does not exist and could not be created
- Installing symfony/intl (v3.3.8):
[Symfony\Component\Process\Exception\RuntimeException]
The Process class relies on proc_open, which is not available on your PHP installation.
PHP需有proc_open,得从PHP的php.ini里给去掉:
; disable_functions = chroot,chgrp,chown,shell_exec,proc_open,proc_get_status,ini_alter,ini_
restore,dl,openlog,syslog,readlink,symlink,popepassthru,stream_socket_server,fsocket
#sudo -u www -H composer.phar install
Composer could not find a composer.json file in /usr/local/php/etc
To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section
得cd到:/usr/local/composer 里,再执行:sudo -u www -H composer.phar install
#sudo -u www -H composer.phar install
[ErrorException]
proc_get_status() has been disabled for security reasons 和上面一样:得从PHP的php.ini里给去掉。
[RuntimeException]
Could not delete /usr/local/composer/vendor/symfony/intl:
chown -R www.www /usr/local/composer/vendor
[ErrorException]
file_put_contents(./composer.lock): failed to open stream: Permission denied #写入/usr/local/composer/composer.lock权限不够。
[root@gitlab-jenkins_php-redis_123.57.252.183:/usr/local]
#chown www.www composer
#sudo -u www -H composer.phar install
Loading composer repositories with package information
Updating dependencies (including require-dev)
Nothing to install or update
Writing lock file
Generating autoload files
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
From:https://getcomposer.org/download/
http://blog.csdn.net/yoywow/article/details/52074512
二、使用composer安装laravel/lumen:
遇到问题:
修改 composer 的全局配置文件(推荐方式)
打开命令行窗口(windows用户)或控制台(Linux、Mac 用户)并执行如下命令:
[root@a composer]# chtdocs
[root@a htdocs]# cd lumen.levoo.com/
[root@a lumen.levoo.com]# /usr/local/composer/composer.phar global require "laravel/lumen-installer"
Changed current directory to /root/.config/composer
Do not run Composer as root/super user! See https://getcomposer.org/root for details
compser 执行命令提示do not run composer as root/super !
这个是因为composer为了防止非法脚本在root下执行,解决办法随便切换到非root用户即可
su www
mkdir -p /home/www/.cache
chown -R www:www /home/www/.cache
composer require easyswoole/hot-reload
Cannot create cache directory /home/www/.cache/composer/repo/https---mirrors.aliyun.com-composer/, or directory is not writable. Proceeding without cache
Cannot create cache directory /home/www/.cache/composer/files/, or directory is not writable. Proceeding without cache
Using version ^0.1.2 for easyswoole/hot-reload
./composer.json has been updated
PATH变量设置Ok的方法如下:
打开~/.bashrc
sudo vim ~/.bashrc
添加行:
export PATH=$PATH:/home/lumen/.config/composer/vendor/bin
用Linux系统。比如要把/etc/apache/bin目录添加到PATH中,方法有三:
1.#PATH=c/etc/apache/bin
使用这种方法,只对当前会话有效,也就是说每当登出或注销系统以后,PATH 设置就会失效
2.#vi /etc/profile
在适当位置添加 PATH=$PATH:/etc/apache/bin (注意:= 即等号两边不能有任何空格)
这种方法最好,除非你手动强制修改PATH的值,否则将不会被改变
3.#vi ~/.bash_profile
修改PATH行,把/etc/apache/bin添加进去
这种方法是针对用户起作用的
From:http://opsmysql.blog.51cto.com/2238445/665990
lumen没有成功:
useradd lumen
su lumen
cd /data/htdocs/laravel.levoo.com
/usr/local/composer/composer.phar config -g repo.packagist composer https://packagist.phpcomposer.com
进行上述设置后,laravel有门,能下载了:
[lumen@a laravel.levoo.com]$ pwd
/data/htdocs/laravel.levoo.com
[lumen@a laravel.levoo.com]$ /usr/local/composer/composer.phar global require "laravel/lumen-installer"
Changed current directory to /home/lumen/.config/composer
Using version ^1.0 for laravel/lumen-installer
./composer.json has been created
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 10 installs, 0 updates, 0 removals
- Installing symfony/process (v3.2.1) Downloading: 100%
- Installing psr/log (1.0.2) Downloading: 100%
- Installing symfony/debug (v3.2.1) Downloading: 100%
- Installing symfony/polyfill-mbstring (v1.3.0) Downloading: 100%
- Installing symfony/console (v3.2.1) Downloading: 100%
- Installing guzzlehttp/promises (v1.3.1) Downloading: 100%
- Installing psr/http-message (1.0.1) Downloading: 100%
- Installing guzzlehttp/psr7 (1.3.1) Downloading: 100%
- Installing guzzlehttp/guzzle (6.2.2) Downloading: 100%
- Installing laravel/lumen-installer (v1.0.2) Downloading: 100%
symfony/console suggests installing symfony/event-dispatcher ()
symfony/console suggests installing symfony/filesystem ()
Writing lock file
Generating autoload files
生成文件如下:
[lumen@a composer]$ pwd
/home/lumen/.config/composer
[lumen@a composer]$ ls /home/lumen/.config/composer
auth.json composer.json composer.lock config.json vendor
开始学习数据库:
http://blog.csdn.net/wowkk/article/details/52104689
/data/htdocs/lumen.levoo.com/blog/.env
APP_ENV=local
APP_DEBUG=true
APP_KEY=
APP_TIMEZONE=UTC
DB_CONNECTION=mysql
DB_HOST=10.44.202.177
DB_PORT=3306
DB_DATABASE=levoo_egg
DB_USERNAME=levoo
DB_PASSWORD=new@levoo.com
CACHE_DRIVER=memcached
QUEUE_DRIVER=sync
/data/htdocs/lumen.levoo.com/blog/app/Http/Controllers/AccountController.PHP
/data/htdocs/lumen.levoo.com/blog/routes/web.php
<?php
$app->group(["namespace"=>"App\Http\Controllers"], function()use($app){
//账户控制器
$app->get("/AccountController",["uses" => "AccountController@accountController"]);
});
model:/data/htdocs/lumen.levoo.com/blog/app/Models/User.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
}
在app/Http/Controllers目录下AccountController.php,修改为
<?php
namespace App\Http\Controllers;
use App\user; //新增部分
use Laravel\Lumen\Routing\Controller as BaseController;
use Illuminate\Http\Request;
class AccountController extends BaseController
{
//直接传人sql方式操作数据库
function accountController(Request $request){
return User::all();
}
}
http://101.200.189.210/AccountController/accountController
Laravel 扩展及调试利器 —— Laravel Debugbar 扩展包安装及使用教程,Laravel如何引用第三方(自定义)库。
Php/Js/Shell/Go jackxiang 2016-12-28 15:05
调试栏(Laravel Debug Bar)
PHP调试栏项目无疑是一个巨大的成功,你无需到处编写var_dump。Laravel调试栏对该组件作了扩展,包含了路由、视图、事件以及更多信息。
这使得调试变得更加简单、快速,提高你的开发效率。
Confide
认证模块,包含了登录、注册、退出、密码重置等功能。
代码生成器(Laravel Generators)
使用简单的命令行就可以自动根据代码模板生成Model/View/Controller代码以及模块(Module)。
HTML压缩器(Laravel HTML Minify)
让你的页面减小大概18%,提升性能必备
后台管理(Laravel Administrator)
Laravel Administrator帮助开发者快速构建后台管理界面,无需重复构建。
OAuth 4 Laravel:OAuth支持
OAuth 2服务器:安全和100%标准兼容的OAuth服务器
摘自下载量最高的 100 个 Laravel 扩展包推荐:
https://laravel-china.org/topics/2530
阅读全文
php解析url并得到url中的参数
Php/Js/Shell/Go jackxiang 2016-12-13 20:53
背景:像做点PHP给那个下位机,也就是现在的物联网芯片发送指令这种,用到这样的一个串,发送下去后,下位机解析后(解析到串里部分值修改后原样返回)再以串返回,自己想对串里作修改啥的用到这种url参数结构,如:framefd=4&fd=1&act=display&command=gettemp,解析在数组,同数组里的key=>value再解析成串。
parse_url
parse_str
From:http://www.cnblogs.com/freespider/p/4262244.html
parse_url
parse_str
From:http://www.cnblogs.com/freespider/p/4262244.html
PHP学习|PHP中的位运算和进制处理
Php/Js/Shell/Go jackxiang 2016-12-7 11:48
背景:像做一些标识位、状态位,在早期的c语言或c++里都是通过一个位运算符来做的,这块PHP也在上面作了一些借鉴,对于爱放在数据库里和从数据库取东西的php程序,如果状态位很多,你想多个数据库表字段实现是不灵活的,哪天再来一个状态怎么办?所以,本文的思想就是用位运算达到灵活性之目的,故而转载此文。
PHP中的位运算和进制是比较冷门的知识,感觉很简单也很好理解,但是在实际场景中却很少使用,本篇博文就是简单了解基本概念以及讲解如何去实际使用.
位运算
PHP中的位运算符是对整形进行的操作,比如对于十进制,二进制,八进制等数字的一些操作.
& (按位与 AND)
| (按位或 OR)
~ (按位取反 NOT)
^ (按位异或 XOR)
<< (bitwise left shift)
>> (bitwise right shift)
下面用一个实际例子来说明如何去使用它们,比如一个博客系统最重要的元素就是文章,而文章可以有很多状态,比如状态可以是删除,评论,收藏,喜欢,当然可以根据实际情况扩展,那在数据库表中如何进行设计呢?假如通过每个字段来存储文章的状态,一方面表的可扩展性很差,另外一方面查询效率很差.
这个时候可以通过一个status字段来保存这些状态,这个字段的类型是整形,可以存储十进制,八进制,二进制,十六进制.
那么这么多状态`如何在一个字段值中表示呢,可以进行如下规定:
整数(二进制) 状态 说明
0001 删除状态 第一位等于1
0010 评论状态 第二位等于1
0100 收藏状态 第三位等于1
1000 喜欢状态 第四位等于1
面临的第一个问题,如何给文章增加状态属性?
$status = $status | 0b0001 ; //文章被置为删除状态$status = $status | 0b0010 ; //文章被置为评论状态$status = $status | 0b1100 ; //文章同时被置为收藏和喜欢状态
面临的第二个问题,如何给文章取消状态属性?
$status = $status & ~0b0001 ; //文章从删除状态恢复$status = $status & ~0b0010 ; //文章从评论状态恢复$status = $status & ~0b1100 ; //文章同时从收藏和喜欢状态恢复
面临的第三个问题,如何检查文章的状态?
$status & 0b0001?true:false ; //查询文章是否是删除状态$status & 0b0010?true:false ; //查询文章是否是评论状态$status & 0b1100?true:false ; //查询文章是否是收藏和喜欢状态
希望通过上面的例子你能明白位运算符的作用,另外位运算符和逻辑运算符比较容易让人误解.可以这样去区分和理解:
位运算符是对两个整数的bits进行操作,然后返回结果,That means it's not a yes or no thing.
假如位运算符被用在条件语句中,他们将会进行逻辑比较.
逻辑操作符是比较多个表达式,然后返回true或者false.
进制运算
上面位运算符的例子中,作为操作符数的都是二进制,但是也可以是其它进制.
PHP中支持二进制(binary),八进制(octal),十进制(decimal),十六进制(hexadecimal).
它们都是整型,进制和编码密切相关,这里仅仅说明PHP中的进制是如何表达的,以及之间是如何转换的.
如何在整型变量定义进制:
$n = 0b10000 ; //二进制$n = 16; //十进制$n = 0x10; //十六进制$n = 020;//八进制在echo输出的时候,不管是什么类型的整数,最后输出的都是十进制
定义字符串的时候如何通过进制表示:
//\[0-7]{1,3} #八进制表达方式//\x[0-9A-Fa-f]{1,2} #十六进制表达方式$str = "\20";$str = "\x10";echo输出的时候,会输出字符DLE
PHP内部函数如何支持进制转换,共有二种转换方式:
$n = 16;echo dechex($n) . "_" . decbin($n);$n = base_convert('10',16,10 ); //'10'本身的进制由第二个参数决定$nn = base_convert($n, 10,2 );echo $n . "_" . $nn ;//以上的函数返回各进制的字符串表达形式,那么如何返回这些变量代表的字符呢.echo chr(base_convert('10',16,10 ));
sprintf如何在进制中使用:
这个函数实际上和进制没有非常耦合的关系,可以将不同进制的整型转换为不同进制的字符串表示
$n = sprintf("%x", 0b10000 );$n = sprintf("%x", 0x10 );$n = sprintf("%x", 020 );$n = sprintf("%x", 16 );$n = sprintf("%x", "a" );$n = sprintf("%s", 0b10000 );$n = sprintf("%c", 0b10000 );#返回ASCII值对应的字符
摘自:https://buluo.qq.com/p/detail.html?bid=13609&pid=5730935-1481030480&from=grp_sub_obj
PHP中的位运算和进制是比较冷门的知识,感觉很简单也很好理解,但是在实际场景中却很少使用,本篇博文就是简单了解基本概念以及讲解如何去实际使用.
位运算
PHP中的位运算符是对整形进行的操作,比如对于十进制,二进制,八进制等数字的一些操作.
& (按位与 AND)
| (按位或 OR)
~ (按位取反 NOT)
^ (按位异或 XOR)
<< (bitwise left shift)
>> (bitwise right shift)
下面用一个实际例子来说明如何去使用它们,比如一个博客系统最重要的元素就是文章,而文章可以有很多状态,比如状态可以是删除,评论,收藏,喜欢,当然可以根据实际情况扩展,那在数据库表中如何进行设计呢?假如通过每个字段来存储文章的状态,一方面表的可扩展性很差,另外一方面查询效率很差.
这个时候可以通过一个status字段来保存这些状态,这个字段的类型是整形,可以存储十进制,八进制,二进制,十六进制.
那么这么多状态`如何在一个字段值中表示呢,可以进行如下规定:
整数(二进制) 状态 说明
0001 删除状态 第一位等于1
0010 评论状态 第二位等于1
0100 收藏状态 第三位等于1
1000 喜欢状态 第四位等于1
面临的第一个问题,如何给文章增加状态属性?
$status = $status | 0b0001 ; //文章被置为删除状态$status = $status | 0b0010 ; //文章被置为评论状态$status = $status | 0b1100 ; //文章同时被置为收藏和喜欢状态
面临的第二个问题,如何给文章取消状态属性?
$status = $status & ~0b0001 ; //文章从删除状态恢复$status = $status & ~0b0010 ; //文章从评论状态恢复$status = $status & ~0b1100 ; //文章同时从收藏和喜欢状态恢复
面临的第三个问题,如何检查文章的状态?
$status & 0b0001?true:false ; //查询文章是否是删除状态$status & 0b0010?true:false ; //查询文章是否是评论状态$status & 0b1100?true:false ; //查询文章是否是收藏和喜欢状态
希望通过上面的例子你能明白位运算符的作用,另外位运算符和逻辑运算符比较容易让人误解.可以这样去区分和理解:
位运算符是对两个整数的bits进行操作,然后返回结果,That means it's not a yes or no thing.
假如位运算符被用在条件语句中,他们将会进行逻辑比较.
逻辑操作符是比较多个表达式,然后返回true或者false.
进制运算
上面位运算符的例子中,作为操作符数的都是二进制,但是也可以是其它进制.
PHP中支持二进制(binary),八进制(octal),十进制(decimal),十六进制(hexadecimal).
它们都是整型,进制和编码密切相关,这里仅仅说明PHP中的进制是如何表达的,以及之间是如何转换的.
如何在整型变量定义进制:
$n = 0b10000 ; //二进制$n = 16; //十进制$n = 0x10; //十六进制$n = 020;//八进制在echo输出的时候,不管是什么类型的整数,最后输出的都是十进制
定义字符串的时候如何通过进制表示:
//\[0-7]{1,3} #八进制表达方式//\x[0-9A-Fa-f]{1,2} #十六进制表达方式$str = "\20";$str = "\x10";echo输出的时候,会输出字符DLE
PHP内部函数如何支持进制转换,共有二种转换方式:
$n = 16;echo dechex($n) . "_" . decbin($n);$n = base_convert('10',16,10 ); //'10'本身的进制由第二个参数决定$nn = base_convert($n, 10,2 );echo $n . "_" . $nn ;//以上的函数返回各进制的字符串表达形式,那么如何返回这些变量代表的字符呢.echo chr(base_convert('10',16,10 ));
sprintf如何在进制中使用:
这个函数实际上和进制没有非常耦合的关系,可以将不同进制的整型转换为不同进制的字符串表示
$n = sprintf("%x", 0b10000 );$n = sprintf("%x", 0x10 );$n = sprintf("%x", 020 );$n = sprintf("%x", 16 );$n = sprintf("%x", "a" );$n = sprintf("%s", 0b10000 );$n = sprintf("%c", 0b10000 );#返回ASCII值对应的字符
摘自:https://buluo.qq.com/p/detail.html?bid=13609&pid=5730935-1481030480&from=grp_sub_obj
php5.5编译安装报错 struct flock
Php/Js/Shell/Go jackxiang 2016-10-31 21:48
背景:PHP5.5 在centos6 64位下编译报错,之前在另一台rpmbuild机上不存在这个问题。
解决办法:
vim /etc/ld.so.conf.d/local.conf # 编辑库文件
/usr/local/lib # 添加该行
:wq # 保存退出
ldconfig -v # 使之生效
注意事项:
这里添加的库文件路径一定要和你系统平台arch一致,32bit的系统直接添加/usr/local/lib即可,64bit系统要填加/usr/local/lib64.否则依旧会报错,我当时就是添加了/usr/local/lib死活编辑不了,后来更改为
/usr/local/lib64才可以。切记
http://lovelace.blog.51cto.com/1028430/1314571
解决办法:
vim /etc/ld.so.conf.d/local.conf # 编辑库文件
/usr/local/lib # 添加该行
:wq # 保存退出
ldconfig -v # 使之生效
注意事项:
这里添加的库文件路径一定要和你系统平台arch一致,32bit的系统直接添加/usr/local/lib即可,64bit系统要填加/usr/local/lib64.否则依旧会报错,我当时就是添加了/usr/local/lib死活编辑不了,后来更改为
/usr/local/lib64才可以。切记
http://lovelace.blog.51cto.com/1028430/1314571
[实践OK]相当有用之善用php-fpm的慢执行日志slow log,分析php性能问题
Php/Js/Shell/Go jackxiang 2016-8-25 10:23
背景:看PHP的慢日志一般来讲主要是看网络接口上的问题,有时间一台服务器会调用api接口,而该接口呢在另一吧机器上,而有人恶意透过这个接口频繁调用,飙高带宽,进而导致一堆TIME_WAIT,nginx出现白页,此时,这是现象,如何由现象看到本质,那就打开php-fpm的slow的日志吧,如何打开,接着向下看吧。
——————————————————————————————————————————————————————————————————————
众所周知,mysql有slow query log,根据慢查询日志,我们可以知道那些sql语句有性能问题。作为mysql的好搭档,php也有这样的功能。如果你使用php-fpm来管理php的话,你可以通过如下选项开启。
PHP 5.3.3 之前设置如下:
<value name="request_slowlog_timeout">5s</value>
<value name="slowlog">logs/php-fpm-slowlog.log</value>
说明:
request_slowlog_timeout 是脚本超过多长时间 就可以记录到日志文件
slowlog 是日志文件的路径
开启后,如果有脚本执行超过指定的时间,就会在指定的日志文件中写入类似如下的信息:
[19-Dec-2013 16:54:49] [pool www] pid 18575
script_filename = /home/web/htdocs/sandbox_canglong/test/tt.php
[0x0000000003a00dc8] curl_exec() /home/web/htdocs/sandbox_canglong/test/tt.php:2
[0x0000000003a00cd0] exfilter_curl_get() /home/web/htdocs/sandbox_canglong/test/tt.php:6
日志说明:
script_filename 是入口文件
curl_exec() : 说明是执行这个方法的时候超过执行时间的。
exfilter_curl_get() :说明调用curl_exec()的方法是exfilter_curl_get() 。
每行冒号后面的数字是行号。
开启后,在错误日志文件中也有相关记录。如下:
参考:http://www.bo56.com/%E5%96%84%E7%94%A8php-fpm%E7%9A%84%E6%85%A2%E6%89%A7%E8%A1%8C%E6%97%A5%E5%BF%97slow-log%EF%BC%8C%E5%88%86%E6%9E%90php%E6%80%A7%E8%83%BD%E9%97%AE%E9%A2%98/
——————————————————————————————————————————————————————————————————————
众所周知,mysql有slow query log,根据慢查询日志,我们可以知道那些sql语句有性能问题。作为mysql的好搭档,php也有这样的功能。如果你使用php-fpm来管理php的话,你可以通过如下选项开启。
PHP 5.3.3 之前设置如下:
<value name="request_slowlog_timeout">5s</value>
<value name="slowlog">logs/php-fpm-slowlog.log</value>
说明:
request_slowlog_timeout 是脚本超过多长时间 就可以记录到日志文件
slowlog 是日志文件的路径
开启后,如果有脚本执行超过指定的时间,就会在指定的日志文件中写入类似如下的信息:
[19-Dec-2013 16:54:49] [pool www] pid 18575
script_filename = /home/web/htdocs/sandbox_canglong/test/tt.php
[0x0000000003a00dc8] curl_exec() /home/web/htdocs/sandbox_canglong/test/tt.php:2
[0x0000000003a00cd0] exfilter_curl_get() /home/web/htdocs/sandbox_canglong/test/tt.php:6
日志说明:
script_filename 是入口文件
curl_exec() : 说明是执行这个方法的时候超过执行时间的。
exfilter_curl_get() :说明调用curl_exec()的方法是exfilter_curl_get() 。
每行冒号后面的数字是行号。
开启后,在错误日志文件中也有相关记录。如下:
参考:http://www.bo56.com/%E5%96%84%E7%94%A8php-fpm%E7%9A%84%E6%85%A2%E6%89%A7%E8%A1%8C%E6%97%A5%E5%BF%97slow-log%EF%BC%8C%E5%88%86%E6%9E%90php%E6%80%A7%E8%83%BD%E9%97%AE%E9%A2%98/
[实践OK]深入理解PHP原理之变量分离/引用(Variables Separation)
Php/Js/Shell/Go jackxiang 2016-8-11 15:41
背景: 深入理解PHP原理之变量分离/引用(Variables Separation) 之自己+1,这个refcount是否+1的问题。
Q:
有时候会在原有数值的基础上改变吧 比如$var++
A:两种情况,那个对象就不测试了:
情况1,字符:
---------- 调试PHP ----------
string(5) "jackX" refcount(2)
string(5) "jackY" refcount(2)
输出完成 (耗时 0 秒) - 正常终止
情况2,整数:
---------- 调试PHP ----------
long(1) refcount(2)
long(2) refcount(2)
输出完成 (耗时 0 秒) - 正常终止
说明,$var++; 并没有改变自己的refcount值。而像:$var_dup = $var;就会+1了哟:
---------- 调试PHP ----------
string(5) "jackX" refcount(2)
string(5) "jackY" refcount(3) <---看,这儿+1,等于3了,$var_dup = $var;会加1,得证。
输出完成 (耗时 0 秒) - 正常终止
实践来源:http://www.laruence.com/2008/09/19/520.html
疑问:
---------- 调试PHP ----------
string(8) "laruence" refcount(3)
string(8) "laruence" refcount(3)
long(1) refcount(2)
string(8) "laruence" refcount(2)
输出完成 (耗时 0 秒) - 正常终止
可能是:
作为函数的参数穿进去的时候,函数的实参使用了,所以+1,函数电用完,实参也回收了,所以变回2,应该是这样,实践如下:
---------- 调试PHP ----------
string(9) "jackxiang" refcount(2)
string(9) "jackxiang" refcount(2)
string(9) "jackxiang" refcount(2)
输出完成 (耗时 0 秒) - 正常终止
运行debug_zval_dump后不是又变回去了?按这样说,那前面的结论都TM错了,$var ++,其refcount也是加了1的。这就是结论。要看是这么玩的,得看PHP这块的源代码。
Q:
有时候会在原有数值的基础上改变吧 比如$var++
A:两种情况,那个对象就不测试了:
情况1,字符:
---------- 调试PHP ----------
string(5) "jackX" refcount(2)
string(5) "jackY" refcount(2)
输出完成 (耗时 0 秒) - 正常终止
情况2,整数:
---------- 调试PHP ----------
long(1) refcount(2)
long(2) refcount(2)
输出完成 (耗时 0 秒) - 正常终止
说明,$var++; 并没有改变自己的refcount值。而像:$var_dup = $var;就会+1了哟:
---------- 调试PHP ----------
string(5) "jackX" refcount(2)
string(5) "jackY" refcount(3) <---看,这儿+1,等于3了,$var_dup = $var;会加1,得证。
输出完成 (耗时 0 秒) - 正常终止
实践来源:http://www.laruence.com/2008/09/19/520.html
疑问:
---------- 调试PHP ----------
string(8) "laruence" refcount(3)
string(8) "laruence" refcount(3)
long(1) refcount(2)
string(8) "laruence" refcount(2)
输出完成 (耗时 0 秒) - 正常终止
可能是:
作为函数的参数穿进去的时候,函数的实参使用了,所以+1,函数电用完,实参也回收了,所以变回2,应该是这样,实践如下:
---------- 调试PHP ----------
string(9) "jackxiang" refcount(2)
string(9) "jackxiang" refcount(2)
string(9) "jackxiang" refcount(2)
输出完成 (耗时 0 秒) - 正常终止
运行debug_zval_dump后不是又变回去了?按这样说,那前面的结论都TM错了,$var ++,其refcount也是加了1的。这就是结论。要看是这么玩的,得看PHP这块的源代码。
Web端PHP代码函数覆盖率测试解决方案
Php/Js/Shell/Go jackxiang 2016-7-28 14:45
背景:在拿代码量算KPI...跟程序员来这一套。--西乔漫画。IT部门谈到:马上部署代码覆盖测试,PHP这块有查了一下还真有类似的工具。
Web端PHP代码函数覆盖率测试解决方案:
主要是结合xdebug和Spike PHPCoverage这两个工具进行统计:
原创网址:http://blog.csdn.net/httpnet/article/details/1707377
辅助参考:
http://www.cnblogs.com/xuning/archive/2015/11/09/4950110.html
http://blog.jobbole.com/97236/
Web端PHP代码函数覆盖率测试解决方案:
主要是结合xdebug和Spike PHPCoverage这两个工具进行统计:
原创网址:http://blog.csdn.net/httpnet/article/details/1707377
辅助参考:
http://www.cnblogs.com/xuning/archive/2015/11/09/4950110.html
http://blog.jobbole.com/97236/
php语法检测,sublime linter-php
Php/Js/Shell/Go jackxiang 2016-7-17 21:45
废话不多说,打开控制台,install package
搜 sublimelinter
先安装sublimelinter本体
安装完以后再搜索一下,安装sublimelinter-php
接下来,打开preferences-package settings-sublimeLinter-settings--user
如下配置:
{
"user": {
"linters": {
},
"paths": {
"linux": [],
"osx": [],
"windows": [
"D:\\xampp\\php"
]
},
}
}
就是添加一下 paths的参数值,指定一下你本地php目录。
然后关闭sublime,再次打开一个php脚本,试试吧。
有错误的地方在行号上会有红点提示在代码上会有红色方框,鼠标放红色方框上,错误信息在编辑器底部状态栏显示。
来自:http://my.oschina.net/cxz001/blog/204592
搜 sublimelinter
先安装sublimelinter本体
安装完以后再搜索一下,安装sublimelinter-php
接下来,打开preferences-package settings-sublimeLinter-settings--user
如下配置:
{
"user": {
"linters": {
},
"paths": {
"linux": [],
"osx": [],
"windows": [
"D:\\xampp\\php"
]
},
}
}
就是添加一下 paths的参数值,指定一下你本地php目录。
然后关闭sublime,再次打开一个php脚本,试试吧。
有错误的地方在行号上会有红点提示在代码上会有红色方框,鼠标放红色方框上,错误信息在编辑器底部状态栏显示。
来自:http://my.oschina.net/cxz001/blog/204592
owncloud打开出现:PHP is apparently set up to strip inline doc blocks. This will make several
Php/Js/Shell/Go jackxiang 2016-7-17 00:41
我的是独立出来的放在:/usr/local/php/etc/php.d/opcache.ini
opcache.enable_cli=0
opcache.enable=0
/bin/systemctl restart php-fpm.service
访问后再修改为1像上面这样restart一下即可。
打开页面看到如下错误:“PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible.”这可能是由缓存/加速器造成的,例如 Zend OPcache 或 eAccelerator。打开你的打开php.ini文件,找到:[opcache],设置为:opcache.enable=0 和 opcache.enable_cli=0。
[opcache]
opcache.enable=0
opcache.enable_cli=0
[root@iZ25dcp92ckZ etc]# php -v
PHP 5.6.20 (cli) (built: Jul 11 2016 11:15:33)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
with Zend OPcache v7.0.4-dev, Copyright (c) 1999-2015, by Zend Technologies
with Zend Guard Loader v3.3, Copyright (c) 1998-2014, by Zend Technologies
还没生效?
[root@iZ25dcp92ckZ php.d]# php -i|grep opcache
Additional .ini files parsed => /usr/local/php/etc/php.d/opcache.ini
找到:
/usr/local/php/etc/php.d/opcache.ini
[opcache]
zend_extension=/usr/local/php/ext/opcache.so
opcache.enable=0
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
opcache.save_comments=0
opcache.fast_shutdown=1
opcache.enable_cli=0
;opcache.optimization_level=0
[root@iZ25dcp92ckZ php.d]# service php-fpm restart
Gracefully shutting down php-fpm . done
Starting php-fpm done
opcache.enable_cli=0
opcache.enable=0
/bin/systemctl restart php-fpm.service
访问后再修改为1像上面这样restart一下即可。
打开页面看到如下错误:“PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible.”这可能是由缓存/加速器造成的,例如 Zend OPcache 或 eAccelerator。打开你的打开php.ini文件,找到:[opcache],设置为:opcache.enable=0 和 opcache.enable_cli=0。
[opcache]
opcache.enable=0
opcache.enable_cli=0
[root@iZ25dcp92ckZ etc]# php -v
PHP 5.6.20 (cli) (built: Jul 11 2016 11:15:33)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
with Zend OPcache v7.0.4-dev, Copyright (c) 1999-2015, by Zend Technologies
with Zend Guard Loader v3.3, Copyright (c) 1998-2014, by Zend Technologies
还没生效?
[root@iZ25dcp92ckZ php.d]# php -i|grep opcache
Additional .ini files parsed => /usr/local/php/etc/php.d/opcache.ini
找到:
/usr/local/php/etc/php.d/opcache.ini
[opcache]
zend_extension=/usr/local/php/ext/opcache.so
opcache.enable=0
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
opcache.save_comments=0
opcache.fast_shutdown=1
opcache.enable_cli=0
;opcache.optimization_level=0
[root@iZ25dcp92ckZ php.d]# service php-fpm restart
Gracefully shutting down php-fpm . done
Starting php-fpm done
30个php操作redis常用方法代码例子
Php/Js/Shell/Go jackxiang 2016-7-5 15:07
背景:redis这个新产品在sns时很火,而memcache早就存在, 但redis提供出来的功能,好多网站均把它当memcache使用,这是大才小用,这儿有30个方法来使用redis,值得了解。
这篇文章主要介绍了30个php操作redis常用方法代码例子,本文其实不止30个方法,可以操作string类型、list类型和set类型的数据,需要的朋友可以参考下
redis的操作很多的,以前看到一个比较全的博客,但是现在找不到了。查个东西搜半天,下面整理一下php处理redis的例子,个人觉得常用一些例子。下面的例子都是基于php-redis这个扩展的。
1,connect
描述:实例连接到一个Redis.
参数:host: string,port: int
返回值:BOOL 成功返回:TRUE;失败返回:FALSE
示例:
<?php
$redis = new redis();
$result = $redis->connect('127.0.0.1', 6379);
var_dump($result); //结果:bool(true)
?>
2,set
描述:设置key和value的值
参数:Key Value
返回值:BOOL 成功返回:TRUE;失败返回:FALSE
示例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$result = $redis->set('test',"11111111111");
var_dump($result); //结果:bool(true)
?>
3,get
描述:获取有关指定键的值
参数:key
返回值:string或BOOL 如果键不存在,则返回 FALSE。否则,返回指定键对应的value值。
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$result = $redis->get('test');
var_dump($result); //结果:string(11) "11111111111"
?>
4,delete
描述:删除指定的键
参数:一个键,或不确定数目的参数,每一个关键的数组:key1 key2 key3 … keyN
返回值:删除的项数
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->set('test',"1111111111111");
echo $redis->get('test'); //结果:1111111111111
$redis->delete('test');
var_dump($redis->get('test')); //结果:bool(false)
?>
5,setnx
描述:如果在数据库中不存在该键,设置关键值参数
参数:key value
返回值:BOOL 成功返回:TRUE;失败返回:FALSE
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->set('test',"1111111111111");
$redis->setnx('test',"22222222");
echo $redis->get('test'); //结果:1111111111111
$redis->delete('test');
$redis->setnx('test',"22222222");
echo $redis->get('test'); //结果:22222222
?>
6,exists
描述:验证指定的键是否存在
参数key
返回值:Bool 成功返回:TRUE;失败返回:FALSE
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->set('test',"1111111111111");
var_dump($redis->exists('test')); //结果:bool(true)
?>
7,incr
描述:数字递增存储键值键.
参数:key value:将被添加到键的值
返回值:INT the new value
实例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->set('test',"123");
var_dump($redis->incr("test")); //结果:int(124)
var_dump($redis->incr("test")); //结果:int(125)
?>
8,decr
描述:数字递减存储键值。
参数:key value:将被添加到键的值
返回值:INT the new value
实例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->set('test',"123");
var_dump($redis->decr("test")); //结果:int(122)
var_dump($redis->decr("test")); //结果:int(121)
?>
9,getMultiple
描述:取得所有指定键的值。如果一个或多个键不存在,该数组中该键的值为假
参数:其中包含键值的列表数组
返回值:返回包含所有键的值的数组
实例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->set('test1',"1");
$redis->set('test2',"2");
$result = $redis->getMultiple(array('test1','test2'));
print_r($result); //结果:Array ( [0] => 1 [1] => 2 )
?>
10,lpush
描述:由列表头部添加字符串值。如果不存在该键则创建该列表。如果该键存在,而且不是一个列表,返回FALSE。
参数:key,value
返回值:成功返回数组长度,失败false
实例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
var_dump($redis->lpush("test","111")); //结果:int(1)
var_dump($redis->lpush("test","222")); //结果:int(2)
?>
11,rpush
描述:由列表尾部添加字符串值。如果不存在该键则创建该列表。如果该键存在,而且不是一个列表,返回FALSE。
参数:key,value
返回值:成功返回数组长度,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
var_dump($redis->lpush("test","111")); //结果:int(1)
var_dump($redis->lpush("test","222")); //结果:int(2)
var_dump($redis->rpush("test","333")); //结果:int(3)
var_dump($redis->rpush("test","444")); //结果:int(4)
?>
12,lpop
描述:返回和移除列表的第一个元素
参数:key
返回值:成功返回第一个元素的值 ,失败返回false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->lpush("test","111");
$redis->lpush("test","222");
$redis->rpush("test","333");
$redis->rpush("test","444");
var_dump($redis->lpop("test")); //结果:string(3) "222"
?>
13,lsize,llen
描述:返回的列表的长度。如果列表不存在或为空,该命令返回0。如果该键不是列表,该命令返回FALSE。
参数:Key
返回值:成功返回数组长度,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->lpush("test","111");
$redis->lpush("test","222");
$redis->rpush("test","333");
$redis->rpush("test","444");
var_dump($redis->lsize("test")); //结果:int(4)
?>
14,lget
描述:返回指定键存储在列表中指定的元素。 0第一个元素,1第二个… -1最后一个元素,-2的倒数第二…错误的索引或键不指向列表则返回FALSE。
参数:key index
返回值:成功返回指定元素的值,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->lpush("test","111");
$redis->lpush("test","222");
$redis->rpush("test","333");
$redis->rpush("test","444");
var_dump($redis->lget("test",3)); //结果:string(3) "444"
?>
15,lset
描述:为列表指定的索引赋新的值,若不存在该索引返回false.
参数:key index value
返回值:成功返回true,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->lpush("test","111");
$redis->lpush("test","222");
var_dump($redis->lget("test",1)); //结果:string(3) "111"
var_dump($redis->lset("test",1,"333")); //结果:bool(true)
var_dump($redis->lget("test",1)); //结果:string(3) "333"
?>
16,lgetrange
描述:
返回在该区域中的指定键列表中开始到结束存储的指定元素,lGetRange(key, start, end)。0第一个元素,1第二个元素… -1最后一个元素,-2的倒数第二…
参数:key start end
返回值:成功返回查找的值,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->lpush("test","111");
$redis->lpush("test","222");
print_r($redis->lgetrange("test",0,-1)); //结果:Array ( [0] => 222 [1] => 111 )
?>
17,lremove
描述:从列表中从头部开始移除count个匹配的值。如果count为零,所有匹配的元素都被删除。如果count是负数,内容从尾部开始删除。
参数:key count value
返回值:成功返回删除的个数,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->lpush('test','a');
$redis->lpush('test','b');
$redis->lpush('test','c');
$redis->rpush('test','a');
print_r($redis->lgetrange('test', 0, -1)); //结果:Array ( [0] => c [1] => b [2] => a [3] => a )
var_dump($redis->lremove('test','a',2)); //结果:int(2)
print_r($redis->lgetrange('test', 0, -1)); //结果:Array ( [0] => c [1] => b )
?>
18,sadd
描述:为一个Key添加一个值。如果这个值已经在这个Key中,则返回FALSE。
参数:key value
返回值:成功返回true,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
var_dump($redis->sadd('test','111')); //结果:bool(true)
var_dump($redis->sadd('test','333')); //结果:bool(true)
print_r($redis->sort('test')); //结果:Array ( [0] => 111 [1] => 333 )
?>
19,sremove
描述:删除Key中指定的value值
参数:key member
返回值:true or false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->sadd('test','111');
$redis->sadd('test','333');
$redis->sremove('test','111');
print_r($redis->sort('test')); //结果:Array ( [0] => 333 )
?>
20,smove
描述:将Key1中的value移动到Key2中
参数:srcKey dstKey member
返回值:true or false
范例
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->delete('test1');
$redis->sadd('test','111');
$redis->sadd('test','333');
$redis->sadd('test1','222');
$redis->sadd('test1','444');
$redis->smove('test',"test1",'111');
print_r($redis->sort('test1')); //结果:Array ( [0] => 111 [1] => 222 [2] => 444 )
?>
21,scontains
描述:检查集合中是否存在指定的值。
参数:key value
返回值:true or false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->sadd('test','111');
$redis->sadd('test','112');
$redis->sadd('test','113');
var_dump($redis->scontains('test', '111')); //结果:bool(true)
?>
22,ssize
描述:返回集合中存储值的数量
参数:key
返回值:成功返回数组个数,失败0
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->sadd('test','111');
$redis->sadd('test','112');
echo $redis->ssize('test'); //结果:2
?>
23,spop
描述:随机移除并返回key中的一个值
参数:key
返回值:成功返回删除的值,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->sadd("test","111");
$redis->sadd("test","222");
$redis->sadd("test","333");
var_dump($redis->spop("test")); //结果:string(3) "333"
?>
24,sinter
描述:返回一个所有指定键的交集。如果只指定一个键,那么这个命令生成这个集合的成员。如果不存在某个键,则返回FALSE。
参数:key1, key2, keyN
返回值:成功返回数组交集,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->sadd("test","111");
$redis->sadd("test","222");
$redis->sadd("test","333");
$redis->sadd("test1","111");
$redis->sadd("test1","444");
var_dump($redis->sinter("test","test1")); //结果:array(1) { [0]=> string(3) "111" }
?>
25,sinterstore
描述:执行sInter命令并把结果储存到新建的变量中。
参数:
Key: dstkey, the key to store the diff into.
Keys: key1, key2… keyN. key1..keyN are intersected as in sInter.
返回值:成功返回,交集的个数,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->sadd("test","111");
$redis->sadd("test","222");
$redis->sadd("test","333");
$redis->sadd("test1","111");
$redis->sadd("test1","444");
var_dump($redis->sinterstore('new',"test","test1")); //结果:int(1)
var_dump($redis->smembers('new')); //结果:array(1) { [0]=> string(3) "111" }
?>
26,sunion
描述:
返回一个所有指定键的并集
参数:
Keys: key1, key2, … , keyN
返回值:成功返回合并后的集,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->sadd("test","111");
$redis->sadd("test","222");
$redis->sadd("test","333");
$redis->sadd("test1","111");
$redis->sadd("test1","444");
print_r($redis->sunion("test","test1")); //结果:Array ( [0] => 111 [1] => 222 [2] => 333 [3] => 444 )
?>
27,sunionstore
描述:执行sunion命令并把结果储存到新建的变量中。
参数:
Key: dstkey, the key to store the diff into.
Keys: key1, key2… keyN. key1..keyN are intersected as in sInter.
返回值:成功返回,交集的个数,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->sadd("test","111");
$redis->sadd("test","222");
$redis->sadd("test","333");
$redis->sadd("test1","111");
$redis->sadd("test1","444");
var_dump($redis->sinterstore('new',"test","test1")); //结果:int(4)
print_r($redis->smembers('new')); //结果:Array ( [0] => 111 [1] => 222 [2] => 333 [3] => 444 )
?>
28,sdiff
描述:返回第一个集合中存在并在其他所有集合中不存在的结果
参数:Keys: key1, key2, … , keyN: Any number of keys corresponding to sets in redis.
返回值:成功返回数组,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->sadd("test","111");
$redis->sadd("test","222");
$redis->sadd("test","333");
$redis->sadd("test1","111");
$redis->sadd("test1","444");
print_r($redis->sdiff("test","test1")); //结果:Array ( [0] => 222 [1] => 333 )
?>
29,sdiffstore
描述:执行sdiff命令并把结果储存到新建的变量中。
参数:
Key: dstkey, the key to store the diff into.
Keys: key1, key2, … , keyN: Any number of keys corresponding to sets in redis
返回值:成功返回数字,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->sadd("test","111");
$redis->sadd("test","222");
$redis->sadd("test","333");
$redis->sadd("test1","111");
$redis->sadd("test1","444");
var_dump($redis->sdiffstore('new',"test","test1")); //结果:int(2)
print_r($redis->smembers('new')); //结果:Array ( [0] => 222 [1] => 333 )
?>
30,smembers, sgetmembers
描述:
返回集合的内容
参数:Key: key
返回值:An array of elements, the contents of the set.
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->sadd("test","111");
$redis->sadd("test","222");
print_r($redis->smembers('test')); //结果:Array ( [0] => 111 [1] => 222 )
?>
php-redis当中,有很多不同名字,但是功能一样的函数,例如:lrem和lremove,这里就不例举
来自:http://m.jb51.net/article/51884.htm
这篇文章主要介绍了30个php操作redis常用方法代码例子,本文其实不止30个方法,可以操作string类型、list类型和set类型的数据,需要的朋友可以参考下
redis的操作很多的,以前看到一个比较全的博客,但是现在找不到了。查个东西搜半天,下面整理一下php处理redis的例子,个人觉得常用一些例子。下面的例子都是基于php-redis这个扩展的。
1,connect
描述:实例连接到一个Redis.
参数:host: string,port: int
返回值:BOOL 成功返回:TRUE;失败返回:FALSE
示例:
<?php
$redis = new redis();
$result = $redis->connect('127.0.0.1', 6379);
var_dump($result); //结果:bool(true)
?>
2,set
描述:设置key和value的值
参数:Key Value
返回值:BOOL 成功返回:TRUE;失败返回:FALSE
示例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$result = $redis->set('test',"11111111111");
var_dump($result); //结果:bool(true)
?>
3,get
描述:获取有关指定键的值
参数:key
返回值:string或BOOL 如果键不存在,则返回 FALSE。否则,返回指定键对应的value值。
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$result = $redis->get('test');
var_dump($result); //结果:string(11) "11111111111"
?>
4,delete
描述:删除指定的键
参数:一个键,或不确定数目的参数,每一个关键的数组:key1 key2 key3 … keyN
返回值:删除的项数
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->set('test',"1111111111111");
echo $redis->get('test'); //结果:1111111111111
$redis->delete('test');
var_dump($redis->get('test')); //结果:bool(false)
?>
5,setnx
描述:如果在数据库中不存在该键,设置关键值参数
参数:key value
返回值:BOOL 成功返回:TRUE;失败返回:FALSE
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->set('test',"1111111111111");
$redis->setnx('test',"22222222");
echo $redis->get('test'); //结果:1111111111111
$redis->delete('test');
$redis->setnx('test',"22222222");
echo $redis->get('test'); //结果:22222222
?>
6,exists
描述:验证指定的键是否存在
参数key
返回值:Bool 成功返回:TRUE;失败返回:FALSE
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->set('test',"1111111111111");
var_dump($redis->exists('test')); //结果:bool(true)
?>
7,incr
描述:数字递增存储键值键.
参数:key value:将被添加到键的值
返回值:INT the new value
实例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->set('test',"123");
var_dump($redis->incr("test")); //结果:int(124)
var_dump($redis->incr("test")); //结果:int(125)
?>
8,decr
描述:数字递减存储键值。
参数:key value:将被添加到键的值
返回值:INT the new value
实例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->set('test',"123");
var_dump($redis->decr("test")); //结果:int(122)
var_dump($redis->decr("test")); //结果:int(121)
?>
9,getMultiple
描述:取得所有指定键的值。如果一个或多个键不存在,该数组中该键的值为假
参数:其中包含键值的列表数组
返回值:返回包含所有键的值的数组
实例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->set('test1',"1");
$redis->set('test2',"2");
$result = $redis->getMultiple(array('test1','test2'));
print_r($result); //结果:Array ( [0] => 1 [1] => 2 )
?>
10,lpush
描述:由列表头部添加字符串值。如果不存在该键则创建该列表。如果该键存在,而且不是一个列表,返回FALSE。
参数:key,value
返回值:成功返回数组长度,失败false
实例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
var_dump($redis->lpush("test","111")); //结果:int(1)
var_dump($redis->lpush("test","222")); //结果:int(2)
?>
11,rpush
描述:由列表尾部添加字符串值。如果不存在该键则创建该列表。如果该键存在,而且不是一个列表,返回FALSE。
参数:key,value
返回值:成功返回数组长度,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
var_dump($redis->lpush("test","111")); //结果:int(1)
var_dump($redis->lpush("test","222")); //结果:int(2)
var_dump($redis->rpush("test","333")); //结果:int(3)
var_dump($redis->rpush("test","444")); //结果:int(4)
?>
12,lpop
描述:返回和移除列表的第一个元素
参数:key
返回值:成功返回第一个元素的值 ,失败返回false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->lpush("test","111");
$redis->lpush("test","222");
$redis->rpush("test","333");
$redis->rpush("test","444");
var_dump($redis->lpop("test")); //结果:string(3) "222"
?>
13,lsize,llen
描述:返回的列表的长度。如果列表不存在或为空,该命令返回0。如果该键不是列表,该命令返回FALSE。
参数:Key
返回值:成功返回数组长度,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->lpush("test","111");
$redis->lpush("test","222");
$redis->rpush("test","333");
$redis->rpush("test","444");
var_dump($redis->lsize("test")); //结果:int(4)
?>
14,lget
描述:返回指定键存储在列表中指定的元素。 0第一个元素,1第二个… -1最后一个元素,-2的倒数第二…错误的索引或键不指向列表则返回FALSE。
参数:key index
返回值:成功返回指定元素的值,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->lpush("test","111");
$redis->lpush("test","222");
$redis->rpush("test","333");
$redis->rpush("test","444");
var_dump($redis->lget("test",3)); //结果:string(3) "444"
?>
15,lset
描述:为列表指定的索引赋新的值,若不存在该索引返回false.
参数:key index value
返回值:成功返回true,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->lpush("test","111");
$redis->lpush("test","222");
var_dump($redis->lget("test",1)); //结果:string(3) "111"
var_dump($redis->lset("test",1,"333")); //结果:bool(true)
var_dump($redis->lget("test",1)); //结果:string(3) "333"
?>
16,lgetrange
描述:
返回在该区域中的指定键列表中开始到结束存储的指定元素,lGetRange(key, start, end)。0第一个元素,1第二个元素… -1最后一个元素,-2的倒数第二…
参数:key start end
返回值:成功返回查找的值,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->lpush("test","111");
$redis->lpush("test","222");
print_r($redis->lgetrange("test",0,-1)); //结果:Array ( [0] => 222 [1] => 111 )
?>
17,lremove
描述:从列表中从头部开始移除count个匹配的值。如果count为零,所有匹配的元素都被删除。如果count是负数,内容从尾部开始删除。
参数:key count value
返回值:成功返回删除的个数,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->lpush('test','a');
$redis->lpush('test','b');
$redis->lpush('test','c');
$redis->rpush('test','a');
print_r($redis->lgetrange('test', 0, -1)); //结果:Array ( [0] => c [1] => b [2] => a [3] => a )
var_dump($redis->lremove('test','a',2)); //结果:int(2)
print_r($redis->lgetrange('test', 0, -1)); //结果:Array ( [0] => c [1] => b )
?>
18,sadd
描述:为一个Key添加一个值。如果这个值已经在这个Key中,则返回FALSE。
参数:key value
返回值:成功返回true,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
var_dump($redis->sadd('test','111')); //结果:bool(true)
var_dump($redis->sadd('test','333')); //结果:bool(true)
print_r($redis->sort('test')); //结果:Array ( [0] => 111 [1] => 333 )
?>
19,sremove
描述:删除Key中指定的value值
参数:key member
返回值:true or false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->sadd('test','111');
$redis->sadd('test','333');
$redis->sremove('test','111');
print_r($redis->sort('test')); //结果:Array ( [0] => 333 )
?>
20,smove
描述:将Key1中的value移动到Key2中
参数:srcKey dstKey member
返回值:true or false
范例
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->delete('test1');
$redis->sadd('test','111');
$redis->sadd('test','333');
$redis->sadd('test1','222');
$redis->sadd('test1','444');
$redis->smove('test',"test1",'111');
print_r($redis->sort('test1')); //结果:Array ( [0] => 111 [1] => 222 [2] => 444 )
?>
21,scontains
描述:检查集合中是否存在指定的值。
参数:key value
返回值:true or false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->sadd('test','111');
$redis->sadd('test','112');
$redis->sadd('test','113');
var_dump($redis->scontains('test', '111')); //结果:bool(true)
?>
22,ssize
描述:返回集合中存储值的数量
参数:key
返回值:成功返回数组个数,失败0
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->sadd('test','111');
$redis->sadd('test','112');
echo $redis->ssize('test'); //结果:2
?>
23,spop
描述:随机移除并返回key中的一个值
参数:key
返回值:成功返回删除的值,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->sadd("test","111");
$redis->sadd("test","222");
$redis->sadd("test","333");
var_dump($redis->spop("test")); //结果:string(3) "333"
?>
24,sinter
描述:返回一个所有指定键的交集。如果只指定一个键,那么这个命令生成这个集合的成员。如果不存在某个键,则返回FALSE。
参数:key1, key2, keyN
返回值:成功返回数组交集,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->sadd("test","111");
$redis->sadd("test","222");
$redis->sadd("test","333");
$redis->sadd("test1","111");
$redis->sadd("test1","444");
var_dump($redis->sinter("test","test1")); //结果:array(1) { [0]=> string(3) "111" }
?>
25,sinterstore
描述:执行sInter命令并把结果储存到新建的变量中。
参数:
Key: dstkey, the key to store the diff into.
Keys: key1, key2… keyN. key1..keyN are intersected as in sInter.
返回值:成功返回,交集的个数,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->sadd("test","111");
$redis->sadd("test","222");
$redis->sadd("test","333");
$redis->sadd("test1","111");
$redis->sadd("test1","444");
var_dump($redis->sinterstore('new',"test","test1")); //结果:int(1)
var_dump($redis->smembers('new')); //结果:array(1) { [0]=> string(3) "111" }
?>
26,sunion
描述:
返回一个所有指定键的并集
参数:
Keys: key1, key2, … , keyN
返回值:成功返回合并后的集,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->sadd("test","111");
$redis->sadd("test","222");
$redis->sadd("test","333");
$redis->sadd("test1","111");
$redis->sadd("test1","444");
print_r($redis->sunion("test","test1")); //结果:Array ( [0] => 111 [1] => 222 [2] => 333 [3] => 444 )
?>
27,sunionstore
描述:执行sunion命令并把结果储存到新建的变量中。
参数:
Key: dstkey, the key to store the diff into.
Keys: key1, key2… keyN. key1..keyN are intersected as in sInter.
返回值:成功返回,交集的个数,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->sadd("test","111");
$redis->sadd("test","222");
$redis->sadd("test","333");
$redis->sadd("test1","111");
$redis->sadd("test1","444");
var_dump($redis->sinterstore('new',"test","test1")); //结果:int(4)
print_r($redis->smembers('new')); //结果:Array ( [0] => 111 [1] => 222 [2] => 333 [3] => 444 )
?>
28,sdiff
描述:返回第一个集合中存在并在其他所有集合中不存在的结果
参数:Keys: key1, key2, … , keyN: Any number of keys corresponding to sets in redis.
返回值:成功返回数组,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->sadd("test","111");
$redis->sadd("test","222");
$redis->sadd("test","333");
$redis->sadd("test1","111");
$redis->sadd("test1","444");
print_r($redis->sdiff("test","test1")); //结果:Array ( [0] => 222 [1] => 333 )
?>
29,sdiffstore
描述:执行sdiff命令并把结果储存到新建的变量中。
参数:
Key: dstkey, the key to store the diff into.
Keys: key1, key2, … , keyN: Any number of keys corresponding to sets in redis
返回值:成功返回数字,失败false
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->sadd("test","111");
$redis->sadd("test","222");
$redis->sadd("test","333");
$redis->sadd("test1","111");
$redis->sadd("test1","444");
var_dump($redis->sdiffstore('new',"test","test1")); //结果:int(2)
print_r($redis->smembers('new')); //结果:Array ( [0] => 222 [1] => 333 )
?>
30,smembers, sgetmembers
描述:
返回集合的内容
参数:Key: key
返回值:An array of elements, the contents of the set.
范例:
<?php
$redis = new redis();
$redis->connect('127.0.0.1', 6379);
$redis->delete('test');
$redis->sadd("test","111");
$redis->sadd("test","222");
print_r($redis->smembers('test')); //结果:Array ( [0] => 111 [1] => 222 )
?>
php-redis当中,有很多不同名字,但是功能一样的函数,例如:lrem和lremove,这里就不例举
来自:http://m.jb51.net/article/51884.htm
基于Laravel+Swoole开发智能家居后端
Php/Js/Shell/Go jackxiang 2016-6-30 11:09
背景:在本人用PHP和硬件进行交互的时候,用过dio_open这些,但硬件有硬件的特点,特别是一些位啥的,这儿就有一个问题涉及到串口16进制啥的,这位兄弟在实践中遇到的一些转化如:chr()、hexdec()、bin2hex()这3个函数,网上还提到了用pack()、unpack(),因为前面3个函数以及很好的解决了问题,所以就没有继续深入。 再就是用fiddler来看发送的十六进制,以及在进行十六进制转十进制的一些问题,很有价值:
一)转换函数:
二)再谈fiddler2的一个好处:
优雅的快速测试
由于PHP是弱类型,因此理解起来比较费解。接收数据和向硬件发送数据的数据类型是不一样的。用bin2hex()得到的是形如"11 00 00 FE"的字符串,用chr(hexdec())得到的是16进制的ASCII码,如果echo输出的话,会是乱码。那么如何测试(看到)自己生成的16进制ASCII码数据是否正确呢?1种是找一个TCP/IP工具发送过去,这种麻烦了点,我推荐用fiddler监听。
HexView中的黑色部分就是你发送的
你可以快速方便的用一个web页面输出你的ASCII码,在fiddler的HexView中,就可以看到原汁原味你发送的16进制数据了。另外,由于Swoole的监听类是CLI运行,因此我也非常推荐多写一点echo打印一下状态,在phpstorm的SSH客户端里可以快速的了解目前的情况,就像android-studio的Loger一样。
三)echo Carbon::now() . '/Device Numbers:' . $devNum . PHP_EOL;//老司机劝你多写点,最好packagist找个轮子或者自己写个Logger库
除开本人的一个眉批外,以上摘录自:
文/保安保安(简书作者)
原文链接:http://www.jianshu.com/p/b25e8b46bd02
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
一)转换函数:
二)再谈fiddler2的一个好处:
优雅的快速测试
由于PHP是弱类型,因此理解起来比较费解。接收数据和向硬件发送数据的数据类型是不一样的。用bin2hex()得到的是形如"11 00 00 FE"的字符串,用chr(hexdec())得到的是16进制的ASCII码,如果echo输出的话,会是乱码。那么如何测试(看到)自己生成的16进制ASCII码数据是否正确呢?1种是找一个TCP/IP工具发送过去,这种麻烦了点,我推荐用fiddler监听。
HexView中的黑色部分就是你发送的
你可以快速方便的用一个web页面输出你的ASCII码,在fiddler的HexView中,就可以看到原汁原味你发送的16进制数据了。另外,由于Swoole的监听类是CLI运行,因此我也非常推荐多写一点echo打印一下状态,在phpstorm的SSH客户端里可以快速的了解目前的情况,就像android-studio的Loger一样。
三)echo Carbon::now() . '/Device Numbers:' . $devNum . PHP_EOL;//老司机劝你多写点,最好packagist找个轮子或者自己写个Logger库
除开本人的一个眉批外,以上摘录自:
文/保安保安(简书作者)
原文链接:http://www.jianshu.com/p/b25e8b46bd02
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
[实践好文]PHP 死锁问题分析
Php/Js/Shell/Go jackxiang 2016-6-13 15:34
背景:对于死锁的问题,人们往往想到出现一些关于访问很缓慢,有白页现象,要是测试环境(我就真实遇到测试环境有本文谈及一样的问题)你也就重启一下PHP的php-fpm进程发现又好了,隔一段时间又出类似的问题,你会看下日志,你会发现有很多日志是“Max execution timeout of 60 seconds exceeded”,你会发现这可能是一些php的守护进程导致的,你为了解决测试环境的问题,于是觉得应该把那个php-fpm的进程数开多点,可能会好一些,于是你开多了,一直没有面对这个问题的原因,为什么呢,因为公司装PHP的是运维装的,你没有办法或时间去装一个debug版本的php,你说这个问题让运维的人来查,你觉得能查出来?So,这个问题一拖再拖,但就是没解决,但是有一天你发现磁盘满了,用du去看整体时发现满了,但是如果一个个目录去看发现并没有占用多少,也万万没有想到PHP的死锁还会导致磁盘空间占用太多,上面这种情况我就真实遇到过,后来重新reboot操作系统,磁盘又回来了,所以,我认为是一篇好文章,所以转了此文,也想说明对于PHP的扩展这方面代码质量把关需要严格,再就是PHP本身关于锁这块要弱化(除开cookie/session和cache锁外,其它能不用就不用),尽可能少用锁,这是博主一点小看法,同时把那些比如发短信啥的能异步的给用swoole异步了(这儿有点广告嫌疑),解放出php-fpm进程,防止因为阻塞导致hold住了PHP的php-fpm进程,像php下面的队列demon这种,能单独放就单独放一台机器隔离开,减少出现错误和问题的各种猜忌影响判断,下面言归正传。
引子:
本期我们邀请到了 云盘服务端 团队的技术达人- 徐铁成,一个隐蔽已久的PHP死锁问题被层层掘出,感谢铁成为我们带来这次畅快的体验,小伙伴们,准备好这次技术之旅了么?
---------------
发现问题
近期发现线上很多机器的磁盘空间报警, 且日志文件已经清理,但是磁盘空间没有释放。通过ps aux | grep php-cgi 发现, 很多进程的启动时间在几天到几周甚至几个月之前。我们线上的php-cgi都有最大执行次数的。一般在1天内都会重启一次。初步结论,这些cgi进程有问题。
通过lsof -p [pid] 发现, 启动时间很久的cgi进程中打开了一些日志文件句柄,并且没有关闭。这些日志文件在文件系统中已经删除了。但是句柄没关闭,导致磁盘空间没有释放。到此,磁盘空间异常的问题基本确定。是由于cgi没有关闭文件句柄造成的。
进一步分析进程, strace -p [pid], 发现所有异常的进程都阻塞与 fmutex 状态。换句话所,异常的cgi进程死锁了。进程死锁导致打开的文件句柄没有关闭,所以导致磁盘空间异常。
为什么cgi进程会死锁呢?
什么是死锁
学过操作系统的通同学,都了解多线程的概念。在多线程中访问公共资源,需要对资源加锁。访问结束后,释放锁。如果没有释放锁,那么下一个线程来获取资源的时候就会永远都无法获取资源的锁,于是这个线程死锁了。那么CGI是多线程的公共资源访问导致的死锁吗? 答案是NO。
1. CGI 是单线程进程,通过ps 就能看到。(进程状态 Sl的才是多线程进程)。
2. 即使是多线程的,死锁发生在PHP的shutdown过程中调用glibc 中time 函数的位置,不是php模块造成的。而glibc 中的time相关函数是线程安全的,不会产生死锁。
那是什么导致的死锁呢?
通过分析linux中死锁产生的机制,发现除了多线程会产生死锁外,信号处理函数同样会产生死锁。那么cgi是由于信号处理导致的死锁吗?在这之前介绍一个感念。
函数的可重入性与信号安全
函数可重入是指,无论第几次进入该函数,函数都能正常执行并返回结果。那么线程安全函数是可重入的吗?答案是NO。 线程安全函数,在第一次访问公共资源时,会获取全局锁。如果函数没有执行完成,锁还没释放,此时进程被中断。那么在中断处理函数中,再次访问该函数,就会产生死锁。那么什么样的函数才可以在中断处理函数中访问呢? 除了没有使用全局锁的函数,还有一些signal safe的系统调用可以使用。调用任何其他的非signal safe的函数都会产生不可预知的后果(比如 死锁)。 详见 man signal。在分析死锁的原因前,我们先看看cgi执行的流程,分析其中有没有产生死锁的可能。
PHP-CGI的执行流程
Glibc中的时间函数使用到了全局锁,保证函数的线程安全,但没有保证信号安全(signal safe)。经过之前的分析,我们初步怀疑死锁是由于PHP-CGI进程接收到了一个信号,然后在signal handle中执行了非signal safe的函数。主流程在中断前,正在执行glibc中的时间函数。在函数获取的锁没释放前,进入中断流程。而中断过程中又访问了glibc中的时间函数。于是导致了死锁。
PHP-CGI的执行流程,如下图所示:
进一步分析发现,所有死锁的cgi进程的sapi_global中都记录了一个错误信息
“Max execution timeout of 60 seconds exceeded”.
60s 是我们php-cgi中设置执行超时。所以我们确认了,cig在执行过程中的确产生了超时异常,然后由于longjmp进入了shutdown过程。在shutdown过程中访问了glibc中的时间函数。导致了死锁。
void zend_set_timeout(long seconds)
{
TSRMLS_FETCH();
EG(timeout_seconds) = seconds;
if(!seconds) {
return;
}
……
setitimer(ITIMER_PROF, &t_r, NULL);
signal(SIGPROF, zend_timeout); // 此处会调用zend异常处理函数
sigemptyset(&sigset);
sigaddset(&sigset, SIGPROF);
……
}
通过gdb调试发现,所有PHP-CGI都阻塞在zend_request_shutdown中。zend_request_shutdown会调用用户自定义的php脚本中实现的shutdown函数。如果CGI执行超市,那么定时器会产生SIGPROF信号使执行流程中断。如果此时脚本刚好处于调用时间函数的状态,且还没有释放锁资源。然后执行流程进入了 timeout 函数,继续跳转到zend_request_shutdown。此时如果自定义的shutdown函数中访问了时间函数。就会产生死锁。我们从代码中找到了证据:
register_shutdown_function ('SimpleWebSvc:: shutdown’);
我们在php代码中使用qalarm系统,qalarm系统会在cgi执行结束(shutdown)的时候,注入一个钩子函数,来分析cgi执行是否正常,如果不正常,则发送报警信息。而刚好qalarm的报警处理函数中访问了时间函数。于是就有一定的概率产生死锁。
结论
通过上面的分析,我们找到了cgi死锁产生的原因,是应为在signal handler中使用了非signal safe的函数,导致了死锁。
解决办法
去掉或简化qalarm注册到shutdown中的钩子函数。避免不安全的函数调用。
来自:http://www.v2gg.com/lady/shishangzixun/20140924/57266.html
引子:
本期我们邀请到了 云盘服务端 团队的技术达人- 徐铁成,一个隐蔽已久的PHP死锁问题被层层掘出,感谢铁成为我们带来这次畅快的体验,小伙伴们,准备好这次技术之旅了么?
---------------
发现问题
近期发现线上很多机器的磁盘空间报警, 且日志文件已经清理,但是磁盘空间没有释放。通过ps aux | grep php-cgi 发现, 很多进程的启动时间在几天到几周甚至几个月之前。我们线上的php-cgi都有最大执行次数的。一般在1天内都会重启一次。初步结论,这些cgi进程有问题。
通过lsof -p [pid] 发现, 启动时间很久的cgi进程中打开了一些日志文件句柄,并且没有关闭。这些日志文件在文件系统中已经删除了。但是句柄没关闭,导致磁盘空间没有释放。到此,磁盘空间异常的问题基本确定。是由于cgi没有关闭文件句柄造成的。
进一步分析进程, strace -p [pid], 发现所有异常的进程都阻塞与 fmutex 状态。换句话所,异常的cgi进程死锁了。进程死锁导致打开的文件句柄没有关闭,所以导致磁盘空间异常。
为什么cgi进程会死锁呢?
什么是死锁
学过操作系统的通同学,都了解多线程的概念。在多线程中访问公共资源,需要对资源加锁。访问结束后,释放锁。如果没有释放锁,那么下一个线程来获取资源的时候就会永远都无法获取资源的锁,于是这个线程死锁了。那么CGI是多线程的公共资源访问导致的死锁吗? 答案是NO。
1. CGI 是单线程进程,通过ps 就能看到。(进程状态 Sl的才是多线程进程)。
2. 即使是多线程的,死锁发生在PHP的shutdown过程中调用glibc 中time 函数的位置,不是php模块造成的。而glibc 中的time相关函数是线程安全的,不会产生死锁。
那是什么导致的死锁呢?
通过分析linux中死锁产生的机制,发现除了多线程会产生死锁外,信号处理函数同样会产生死锁。那么cgi是由于信号处理导致的死锁吗?在这之前介绍一个感念。
函数的可重入性与信号安全
函数可重入是指,无论第几次进入该函数,函数都能正常执行并返回结果。那么线程安全函数是可重入的吗?答案是NO。 线程安全函数,在第一次访问公共资源时,会获取全局锁。如果函数没有执行完成,锁还没释放,此时进程被中断。那么在中断处理函数中,再次访问该函数,就会产生死锁。那么什么样的函数才可以在中断处理函数中访问呢? 除了没有使用全局锁的函数,还有一些signal safe的系统调用可以使用。调用任何其他的非signal safe的函数都会产生不可预知的后果(比如 死锁)。 详见 man signal。在分析死锁的原因前,我们先看看cgi执行的流程,分析其中有没有产生死锁的可能。
PHP-CGI的执行流程
Glibc中的时间函数使用到了全局锁,保证函数的线程安全,但没有保证信号安全(signal safe)。经过之前的分析,我们初步怀疑死锁是由于PHP-CGI进程接收到了一个信号,然后在signal handle中执行了非signal safe的函数。主流程在中断前,正在执行glibc中的时间函数。在函数获取的锁没释放前,进入中断流程。而中断过程中又访问了glibc中的时间函数。于是导致了死锁。
PHP-CGI的执行流程,如下图所示:
进一步分析发现,所有死锁的cgi进程的sapi_global中都记录了一个错误信息
“Max execution timeout of 60 seconds exceeded”.
60s 是我们php-cgi中设置执行超时。所以我们确认了,cig在执行过程中的确产生了超时异常,然后由于longjmp进入了shutdown过程。在shutdown过程中访问了glibc中的时间函数。导致了死锁。
void zend_set_timeout(long seconds)
{
TSRMLS_FETCH();
EG(timeout_seconds) = seconds;
if(!seconds) {
return;
}
……
setitimer(ITIMER_PROF, &t_r, NULL);
signal(SIGPROF, zend_timeout); // 此处会调用zend异常处理函数
sigemptyset(&sigset);
sigaddset(&sigset, SIGPROF);
……
}
通过gdb调试发现,所有PHP-CGI都阻塞在zend_request_shutdown中。zend_request_shutdown会调用用户自定义的php脚本中实现的shutdown函数。如果CGI执行超市,那么定时器会产生SIGPROF信号使执行流程中断。如果此时脚本刚好处于调用时间函数的状态,且还没有释放锁资源。然后执行流程进入了 timeout 函数,继续跳转到zend_request_shutdown。此时如果自定义的shutdown函数中访问了时间函数。就会产生死锁。我们从代码中找到了证据:
register_shutdown_function ('SimpleWebSvc:: shutdown’);
我们在php代码中使用qalarm系统,qalarm系统会在cgi执行结束(shutdown)的时候,注入一个钩子函数,来分析cgi执行是否正常,如果不正常,则发送报警信息。而刚好qalarm的报警处理函数中访问了时间函数。于是就有一定的概率产生死锁。
结论
通过上面的分析,我们找到了cgi死锁产生的原因,是应为在signal handler中使用了非signal safe的函数,导致了死锁。
解决办法
去掉或简化qalarm注册到shutdown中的钩子函数。避免不安全的函数调用。
来自:http://www.v2gg.com/lady/shishangzixun/20140924/57266.html
shell检查输入的字符串是不是ip
Php/Js/Shell/Go jackxiang 2016-6-12 16:16
每天早上2-3小时shell论坛,今天终于把精华帖子恳完了,放点好脚本给各位,学shell上cu,没事逛逛论坛,心情好的时候看看精华贴.进步那真是飞一般的感觉.
不过新手最好还是先潜水一个月,在开始发帖回帖.最近论坛帖子质量严重下降都是1+1=?.
zj@zj:~/Script/cushell/08.11.04$ cat checkip.sh
解释下:
grep -Eq '[^0-9.]|^\.|\.$|^0*\.|\.\.'
[^0-9.]是不是有除了0-9与.之外的字符
^\.|\.$ 以.开头 or 以.结尾
^0*\.|\.\. 以0开头 or 连续两个.
以上三种情况都是错误的哦,所以就printerr
echo -e "${IP//./\n}" | wc -l说实话前面那种替换我也是first time.就是讲.替换为换行,3个点就是4行了哦.不是3个点也就printerr
$((10#$i/8)) -gt 31 这个就是判断是不是<=255的了,当然你也可以自己修改成$i -gt 255
OK解释完毕^_^
zj@zj:~/Script/cushell/08.11.04$ ./checkip.sh 1.2.3.4
1.2.3.4 is
zj@zj:~/Script/cushell/08.11.04$ ./checkip.sh 01.2.3.4
incorrect IP format.
Your IP: a.b.a.d
incorrect IP format.
Your IP: 266.1.1.1
incorrect IP format.
Your IP: 244.255.255.255
244.255.255.255 is
来自:http://blog.chinaunix.net/uid-9950859-id-98351.html
更复杂的且更精确的判断:http://www.shangxueba.com/jingyan/1898546.html
不过新手最好还是先潜水一个月,在开始发帖回帖.最近论坛帖子质量严重下降都是1+1=?.
zj@zj:~/Script/cushell/08.11.04$ cat checkip.sh
解释下:
grep -Eq '[^0-9.]|^\.|\.$|^0*\.|\.\.'
[^0-9.]是不是有除了0-9与.之外的字符
^\.|\.$ 以.开头 or 以.结尾
^0*\.|\.\. 以0开头 or 连续两个.
以上三种情况都是错误的哦,所以就printerr
echo -e "${IP//./\n}" | wc -l说实话前面那种替换我也是first time.就是讲.替换为换行,3个点就是4行了哦.不是3个点也就printerr
$((10#$i/8)) -gt 31 这个就是判断是不是<=255的了,当然你也可以自己修改成$i -gt 255
OK解释完毕^_^
zj@zj:~/Script/cushell/08.11.04$ ./checkip.sh 1.2.3.4
1.2.3.4 is
zj@zj:~/Script/cushell/08.11.04$ ./checkip.sh 01.2.3.4
incorrect IP format.
Your IP: a.b.a.d
incorrect IP format.
Your IP: 266.1.1.1
incorrect IP format.
Your IP: 244.255.255.255
244.255.255.255 is
来自:http://blog.chinaunix.net/uid-9950859-id-98351.html
更复杂的且更精确的判断:http://www.shangxueba.com/jingyan/1898546.html
Swoole在实际项目中的应用
Php/Js/Shell/Go jackxiang 2016-6-7 17:14
Swoole在实际项目中的应用
[PHPer]Swoole在实际项目中的应用(不讲入门,只有实战)
2016年6月18日 13:30 ~ 2016年6月18日 17:00
(北京海淀)中关村海龙大厦办公楼17层(星巴克咖啡北侧办公大厅入口)
限额100人
本次活动由Swoole框架内核开发者王晶(网名半桶水,人称桶哥)发起,由优才学院、内聘网联合主办。
[活动对象]
本次活动针不讲入门只讲实战,我们希望你:
1、PHPer,一年以上
2、对Swoole了解或者应用过
3、对开源项目感兴趣,并持续关注开源项目
发起当天就有70多人参加,欢迎你的加入。
报名链接:
http://www.huodongxing.com/event/5337738177600
[PHPer]Swoole在实际项目中的应用(不讲入门,只有实战)
2016年6月18日 13:30 ~ 2016年6月18日 17:00
(北京海淀)中关村海龙大厦办公楼17层(星巴克咖啡北侧办公大厅入口)
限额100人
本次活动由Swoole框架内核开发者王晶(网名半桶水,人称桶哥)发起,由优才学院、内聘网联合主办。
[活动对象]
本次活动针不讲入门只讲实战,我们希望你:
1、PHPer,一年以上
2、对Swoole了解或者应用过
3、对开源项目感兴趣,并持续关注开源项目
发起当天就有70多人参加,欢迎你的加入。
报名链接:
http://www.huodongxing.com/event/5337738177600