日志

MySQL添加用户、授权和访问控制

  • 有哪些方式?

你可以通过两种方式创建MySQL用户:

  1. 通过账户管理语句,例如GRANT、CREATE USER等.
  2. 直接用INSERT、UPDATE、DELETE等语句操作MySQL的授权表(mysql.user、mysql.host、mysql.db、mysql.tables_priv、mysql.columns_priv)

显然方式1比方式2更简洁和有助于减少错误

另外你也可以通过GUI工具(如:MySQL WorkBench)或第三方程序(如:phpmyadmin)

  • 通过账户管理语句实现

a) 通过root用户(或具备CREATE USER 权限的用户)连接mysql

mysql -u root -p 你的用户密码

b) CREATE USER 语句用法

# 创建一个名为 alice 密码为 alicepass 的用户,该用户只能从 localhost 连接

CREATE USER 'alice'@'localhost' IDENTIFIED BY 'alicepass';
# 创建一个名为 bob 密码为 bobpass 的用户,允许该用户从任意host连接

CREATE USER 'bob'@'%' IDENTIFIED BY 'bobpass';
# 创建一个名为 chris 密码为 chrispass 的用户,该用户允许从任何 example.com 域名下的host来连接

CREATE USER 'chris'@'%.example.com' IDENTIFIED BY 'chrispass';

c) GRANT 语句用法

# 给 alice 用户分配所有权限,必须要从 localhost 连接

GRANT ALL PRIVILEGES ON *.* TO 'alice'@'localhost' WITH GRANT OPTION;
# 给  bob 用户分配所有数据库的 RELOAD、PROCESS 权限,并且可以把这些权限授权给其他用户(WITH GRANT OPTION的作用)

GRANT RELOAD,PROCESS ON *.* TO 'bob'@'%' WITH GRANT OPTION;
# 给 chris 用户分配 customer 数据库的 SELECT,INSERT,UPDATE,DELETE,CREATE,DROP 权限,必须从任何 example.com 域名下的host来连接

GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ON customer.* TO 'chris'@'%.example.com';

d) REVOKE 语句用法

# 撤销 david 用户所有数据库的所有权限

REVOKE ALL PRIVILEGES ON *.* FROM 'david'@'%';

e) DROP USER 语句用法

# 删除 alice 用户,不再允许该用户从localhost连接,不指定host时默认为 '%' ,DROP USER不会自动关闭任何已经打开的用户SESSION,一旦SESSION被关闭则该用户即被移除

DROP USER 'alice'@'localhost';
转载请注明出处:

© http://hejunhao.me

日志

Nginx与Apache的区别

可以举一个简单的例子来说明Apache的工作流程,我们平时去餐厅吃饭.餐厅的工作模式是一个服务员全程服务客户,流程是这样,服务员在门口等候客人(listen),客人到了就接待安排的餐桌上(accept),等着客户点菜(request uri),去厨房叫师傅下单做菜(磁盘I/O),等待厨房做好(read),然后给客人上菜(send),整个下来服务员(进程)很多地方是阻塞的.这样客人一多(HTTP请求一多),餐厅只能通过叫更多的服务员来服务(fork进程),但是由于餐厅资源是有限的(CPU),一旦服务员太多管理成本很高(CPU上下文切换),这样就进入一个瓶颈.

再来看看Nginx得怎么处理?餐厅门口挂个门铃(注册epoll模型的listen),一旦有客人(HTTP请求)到达,派一个服务员去接待(accept),之后服务员就去忙其他事情了(比如再去接待客人),等这位客人点好餐就叫服务员(数据到了read()),服务员过来拿走菜单到厨房(磁盘I/O),服务员又做其他事情去了,等厨房做好了菜也喊服务员(磁盘I/O结束),服务员再给客人上菜(send()),厨房做好一个菜就给客人上一个,中间服务员可以去干其他事情.整个过程被切分成很多个阶段,每个阶段都有相应的服务模块.我们想想,这样一旦客人多了,餐厅也能招待更多的人.

日志

PHP中使用cURL请求

cURL是一个非常强大的工具,它支持多种多样的协议(HTTP,FTP,TELNET等等)进行数据传输.因而cURL不受限于它能干什么,不管是基本的HTTP请求还是复杂的FTP上传或者是与需要验证处理的HTTPS网站进行交互,cURL都可以胜任。PHP通过cURL函数库对cURL提供了支持,下面主要介绍PHP cURL中使用最频繁的GET、POST方法和返回数据的处理,以及一些有用的cURL设置项。

  • 基本

在我们通过cURL请求进行各样操作之前,首先我们需要初始化一个cURL的实例对象,我们可以通过调用curl_init()这个方法来完成,它返回一个cURL的句柄。该方法提供一个可选参数,可以通过该参数设置要发送请求的URL地址,在此我们先不传参,下面会用另一种方式进行设置。

  • 设置

当我们拿到cURL的句柄后,我们就可以对其进行一系列的参数设定,下面是一些主要的设置项:

CURLOPT_RETURNTRANSFER

true:将返回的数据以文件流的形式返回;false:将返回的数据直接输出显示;

CURLOPT_CONNECTTIMEOUT

发起连接时等待的时间(秒);

CURLOPT_TIMEOUT

请求超时时间(秒);

CURLOPT_USERAGENT

设置请求的用户代理;

CURLOPT_URL

设置请求的URL地址

CURLOPT_POST

是否以POST方式发起请求

CURLOPT_POSTFIELDS

POST参数值

我们可以通过调用curl_setopt()方法设定指定的cURL参数值,该方法接收三个参数,分别是cURL句柄设置项(例如CURLOPT_URL)和设置值

<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://hejunhao.me');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);

当我们需要设置大量参数时,显然重复使用大量curl_setopt并不方便,我们可以通过curl_setopt_array(),一次性设置大量参数。

<?php
$ch = curl_init();
$options = array(
    CURLOPT_URL => 'http://hejunhao.me',
    CURLOPT_HEADER => 0,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_NOPROGRESS => False,
    CURLOPT_TIMEOUT => 5
);
curl_setopt_array($ch, $options);
  • 发送请求

当我们设置好所有参数,准备发起请求时,我们通过调用curl_exec()方法来执行我们的请求,该方法接收一个cURL句柄参数。请求执行后会有三种可能的返回情况:
阅读全文

日志

Memcache 和 Memcached 的区别

很多人都无法分辨这两者的区别,甚至有人会认为Memcached是服务器的daemon进程
从手册中可以看到这两个扩展:memcache | memcached

显然,Memcached 比 Memcache 多了更多的实现,关于两者的区别可以简单理解如下:
1.Memcached 是基于 libmemcached 库的比 Memcache 实现了更多的协议(eg. Multigets and multisets allow you to get/set multiple items at the same time.)
2.Memcached 相比 Memcache 作了更多的优化
3.Memcached 支持 Binary Protocol,因此有更高的性能体现

日志

PHP类的访问控制

PHP的类属性、方法的可见性通过三个关键词来定义,即public、protected和private

  • 关键词

  1. public

    类成员(方法、属性)可以随处访问;
    以var声明的类属性会被定义为public性质;
    为了兼容PHP4,如果没有指定访问控制,属性和方法默认为公有的;

  2. protected

    类成员可以被自身、继承类和父类访问。(注意:类实例对象不可访问)

  3. private

    类成员只允许自身访问

  • 例子

PHP version: PHP5.5

<?php
class obj{
    public $obj_pub = 'obj_pub';
    protected $obj_protected = 'obj_protected';
    private $obj_private = 'obj_private';

    public function print_data(){
        echo $this->obj_private;
	echo $this->obj_protected;
	echo $this->obj_private;
    }

    protected function method_protected(){}

    private function method_private(){}
}

$o = new obj();
echo $o->obj_pub;//公有属性调用
echo $o->obj_protected; //报错,实例对象不可访问受保护的类属性
echo $o->obj_private; //报错,实例对象不可访问私有属性
echo $o->print_data();//调用公有方法

class animal extends obj{
    
    public function print_1(){
	echo $this->obj_pub;//调用父类公有属性
	echo $this->obj_protected;//调用父类受保护的属性
    }

    public function print_2(){
	echo $this->obj_privatje;//报错,父类私有属性禁止子类访问
    }

    public function foo(){
	$this->print_data();//调用父类公有方法
	$this->method_protected();//调用父类受保护的方法
	$this->method_private();//报错,父类私有方法禁止子类访问
    }
}

$a = new animal();
$a->print_1();
$a->print_2();
$a->foo();
转载请注明出处:

© http://hejunhao.me

日志

PHP的__construct和__destruct

__construct

__construct是PHP的构造函数,在对象创建时首先被调用,如果子类没有定义构造函数则会从父类继承其构造函数(非私有时),如果子类已经定义了构造函数则不会隐式调用父类的构造函数,子类可以通过parent::__construct(..)的方式调用父类构造函数.构造函数主要在对象创建时进行必要的初始化工作.

特别地,子类的构造函数的参数不需要与父类的构造函数一致,即覆盖时不会报E_STRICT错误

如果子类没有定义__construct(),也没有从父类继承,那么会尝试寻找旧式构造函数(与类同名的函数)(注意:从PHP5.3.3起,在命名空间中,与类同名的方法不再作为构造函数

__destruct

__destruct是PHP的析构函数,在对象被删除或隐式销毁时被调用. (since PHP5)

例子

<?php
class obj{
    public $name = '';
	
    function __construct($name){
	echo 'obj_construct call' . PHP_EOL;
	$this->name = $name;
    }

    function __toString(){
	return $this->name . PHP_EOL;
    }

    function __destruct(){
	echo 'obj_destruct call' . PHP_EOL;
    }
}

class animal extends obj{
    public $name = '';
    public $height = '';
	
    function __construct($name, $height){
	parent::__construct($name);
	echo 'animal_construct call' . PHP_EOL;
	$this->name = $name;
	$this->height = $height;
    }

    function __toString(){
	return $this->name . ': ' . $this->height . PHP_EOL;
    }
}

class dog extends animal{

    function __destruct(){
	echo 'dog_destruct call'.PHP_EOL;
    }
}

$d = new dog('dog','90cm');
echo $d;
unset($d);
echo '--------分割线-----' . PHP_EOL;
$a = new animal('animal', '100cm');
echo $a;
unset($a);

/********输出********

obj_construct call
animal_construct call
dog: 90cm
dog_destruct call
--------分割线-----
obj_construct call
animal_construct call
animal: 100cm
obj_destruct call

*********************/
日志

PHP中this、self和parent的区别

this

this是指向类实例化对象的指针,因此它指向的不是类而是类实例化后的对象,例如 $obj = new Animal(); 此时类内部定义的$this指的就是$obj这个对象,而不是Animal这个类.

self

self是类自身的引用,通常指向类的静态成员常量,在类体内引用静态成员和常量时不能用$this->var / $this->foo() 的形式.

parent

parent是指向父类的引用,通过parent可以访问父类方法(不管是否为静态)、父类静态成员父类常量,但不可以访问父类的非静态属性.(注意:$this也可以调用父类方法,但是如果继承类覆盖了父类方法A,那么$this->A()指的是继承类的A()方法,而parent::A()指的依然是父类的A()方法,不受覆盖影响

例子

<?php
class Object{
    public $name = '';
	
    public function __construct($name){
	$this->name = $name;
    }

    protected function foo(){
	echo 'Object foo function'.PHP_EOL;
    }
}

class Animal extends Object{
    public static $count = 0;
    const OBJECT_ID = 999;

    public function __construct($name){
	parent::__construct($name);
	self::count();
	parent::foo();
	$this->foo();
    }

    protected function foo(){
	echo 'Animal foo function'.PHP_EOL;
    }

    private static function count(){
	self::$count += 1;
    }
}

$a = new Animal('dog');
echo $a->name;
echo PHP_EOL;
echo Animal::$count;
echo PHP_EOL;
echo Animal::OBJECT_ID;
echo PHP_EOL;

$c = new Animal('cat');
echo $c->name;
echo PHP_EOL;
echo Animal::$count;
echo PHP_EOL;
echo Animal::OBJECT_ID;

/*****Output*****
 
Object foo function
Animal foo function
dog
1
999
Object foo function
Animal foo function
cat
2
999

*******************/
转载请注明出处:

© http://hejunhao.me

第 6 页,共 6 页123456