PHP中对象的深拷贝与浅拷贝

先说一下深拷贝和浅拷贝通俗理解

深拷贝:赋值时值完全复制,完全的copy,对其中一个作出改变,不会影响另一个

浅拷贝:赋值时,引用赋值,相当于取了一个别名。对其中一个修改,会影响另一个

PHP中, = 赋值时,普通对象是深拷贝,但对对象来说,是浅拷贝。也就是说,对象的赋值是引用赋值。(对象作为参数传递时,也是引用传递,无论函数定义时参数前面是否有&符号)

 

php4中,对象的 = 赋值是实现一份副本,这样存在很多问题,在不知不觉中我们可能会拷贝很多份副本。

php5中,对象的 = 赋值和传递都是引用。要想实现拷贝副本,php提供了clone函数实现。

clone完全copy了一份副本。但是clone时,我们可能不希望copy源对象的所有内容,那我们可以利用__clone来操作。

在__clone()中,我们可以进行一些操作。注意,这些操作,也就是__clone函数是作用于拷贝的副本对象上的

<?php
//普通对象赋值,深拷贝,完全值复制
$m = 1;
$n = $m;
$n = 2;
echo $m;//值复制,对新对象的改变不会对m作出改变,输出 1.深拷贝
echo PHP_EOL;
/*==================*/
 
//对象赋值,浅拷贝,引用赋值
class Test{
    public $a=1;
}
$m = new Test();
$n = $m;//引用赋值
$m->a = 2;//修改m,n也随之改变
echo $n->a;//输出2,浅拷贝
echo PHP_EOL;
?>

由于对象的赋值时引用,要想实现值复制,php提供了clone函数来实现复制对象。

但是clone函数存在这么一个问题,克隆对象时,原对象的普通属性能值复制,但是源对象的对象属性赋值时还是引用赋值,浅拷贝。

<?php
class Test{
    public $a=1;
}
 
class TestOne{
    public $b=1;
    public $obj;
    //包含了一个对象属性,clone时,它会是浅拷贝
    public function __construct(){
        $this->obj = new Test();
    }
}
$m = new TestOne();
$n = $m;//这是完全的浅拷贝,无论普通属性还是对象属性
 
$p = clone $m;
 
//普通属性实现了深拷贝,改变普通属性b,不会对源对象有影响
$p->b = 2;
echo $m->b;//输出原来的1
echo PHP_EOL;
 
//对象属性是浅拷贝,改变对象属性中的a,源对象m中的对象属性中a也改变
 
$p->obj->a = 3;
echo $m->obj->a;//输出3,随新对象改变
?>

要想实现对象真正的深拷贝,有下面两种方法:

写clone函数:如下

<?php
class Test{
    public $a=1;
}
 
class TestOne{
    public $b=1;
    public $obj;
    //包含了一个对象属性,clone时,它会是浅拷贝
    public function __construct(){
        $this->obj = new Test();
    }
     
    //方法一:重写clone函数
    public function __clone(){
        $this->obj = clone $this->obj;
    }
}
 
$m = new TestOne();
$n = clone $m;
 
$n->b = 2;
echo $m->b;//输出原来的1
echo PHP_EOL;
//可以看到,普通属性实现了深拷贝,改变普通属性b,不会对源对象有影响
 
//由于改写了clone函数,现在对象属性也实现了真正的深拷贝,对新对象的改变,不会影响源对象
$n->obj->a = 3;
echo $m->obj->a;//输出1,不随新对象改变,还是保持了原来的属性
 
?>

改写__clone()函数不太方便,而且你得在每个类中把这个类里面的对象属性都在__clone()中 一一 clone

第二种方法,利用序列化反序列化实现,这种方法实现对象的深拷贝简单,不需要修改类。

<?php
class Test{
    public $a=1;
}
 
class TestOne{
    public $b=1;
    public $obj;
    //包含了一个对象属性,clone时,它会是浅拷贝
    public function __construct(){
        $this->obj = new Test();
    }
     
}
 
$m = new TestOne();
//方法二,序列化反序列化实现对象深拷贝
$n = serialize($m);
$n = unserialize($n);
 
$n->b = 2;
echo $m->b;//输出原来的1
echo PHP_EOL;
//可以看到,普通属性实现了深拷贝,改变普通属性b,不会对源对象有影响
 
 
$n->obj->a = 3;
echo $m->obj->a;//输出1,不随新对象改变,还是保持了原来的属性,可以看到,序列化和反序列化可以实现对象的深拷贝
 
?>

还有第三种方法,其实和第二种类似,json_encode之后再json_decode,实现赋值

 

smarty笔记-徐老师,xuduowei,徐多蔚,合肥php老师

<?php
include_once("libs/Smarty.class.php"); //包含smarty类文件

$smarty = new Smarty(); //建立smarty实例对象$smarty

//$smarty->config_dir="libs/Config_File.class.php"; // 目录变量,新版本可以去掉。老版本也可以去掉

$smarty->caching=false; //是否使用缓存,项目在调试期间,不建议启用缓存
$smarty->cache_lifetime = 20;

$smarty->template_dir = "./templates"; //设置模板目录

$smarty->compile_dir = "./templates_c"; //设置编译目录

$smarty->cache_dir = "./smarty_cache"; //缓存文件夹

//----------------------------------------------------

//左右边界符,默认为{},但实际应用当中容易与JavaScript相冲突

//----------------------------------------------------

$smarty->left_delimiter = "{";

$smarty->right_delimiter = "}";


?>

 

 

笔记:

smarty是一款基于php面向对象编程基础上开发的框架系统【模板引擎框架】
官方网址:smarty.net
基于smarty开发的一款非常经典的程序项目:www.phpyun.com【大型人才招聘系统】
smarty的目的:使得php程序和美工分离!
特点:
1、速度快!
2、缓存技术;【页面缓存】
3、编译!!!就是把视图中的标签替换成php。
如何配置smarty?
配置参考xdw.php
===========================
如何设置模板变量?$smarty->assign(“title”,$name);
其中 title就是模板变量
如何渲染模板?$smarty->display(“1.0.htm”);
模板中又该如何调用模板变量呢?
{$title}
注意:$不能少,{}边界付不能少!
{} 在配置文件中进行了定义!
{}和我们的js中的函数主体冲突!解决方法是:
{literal}
js
{/literal}
==============================================
模板中,标签的值的传递【模板方法的应用!】
模板方法的应用:
{$name|substr:’1′:’2′}
若我们需要自定义函数。则可以再配置文件中定义!
===========================================方案一:
第一步:
xdw.php
function abc($arr){ //这个参数是一个数组。
print_r($arr[‘con2’]);
}
中设置好函数;
第二步:在php页面中,如1.0.php中注册模板函数!
$smarty->register_function(“abc1″,”abc”);
视图中调用的方式如下:
{函数名 con=$title}
{abc1 con=$title con2=2 con3=3}
function abc($arr){ //这个参数是一个数组。
$arr[‘con’]
}
=========================================方案二:
到smarty核心文件夹下的plugins文件夹创建一个名为
function.xxx.php的文件。注意:xxx可以自定义。
如:xxx为xdw  function.xdw.php文件
code:
<?php
function smarty_function_xdw($c, &$smarty){
return $c[‘con’];
}
?>
模板中的引用:
{函数名 con=666}
{xdw con=666}
提示:方案二定义的函数在模板中可直接被调用,不需要在控制器中注册。因为方案二中的函数都被默认注册了。
==================================================
smarty中数组值的传递和显示。
PHP:
$arr=array(“张三”,”李四”,”王五”);
$smarty->assign(“arr”,$arr);
HTML:
{foreach from=$arr item=t}
{$t}
{/foreach}
二维数组!
若定义的时候是键名=>值的方式定义!
则html中引用的时候按如下格式:
{foreach from=$arr item=t}
{$t.name}  提示若{$t[‘name’]}就报错了。
{/foreach}
{foreach key=i from=$arr item=t}
{$t.name}——-{$i}
{/foreach}
文件的包含!
{include file=”head.htm”}
{php}
    php代码。
{/php}

WordPress 代码高亮插件:Pure-Highlightjs(支持可视化下插入代码)

Pure-Highlightjs 一个基于 Highlightjs 实现的 WordPress 代码高亮插件,支持 N 多种语言高亮,还提供多种主题。支持在 WordPress 可视化编辑模式下插入代码。

Pure-Highlightjs 依赖于以下开源项目

highlight.js https://highlightjs.org

highlight.js 是一个用于在任何 web 页面上着色显示各种示例源代码语法的 JS 项目

安装说明

1.  下载

点击下载 https://github.com/icodechef/…/Pure-Highlightjs_1.0.zip

2. 安装

进入 WordPress 后台管理页面,“插件 》安装插件 》上传插件”,上传刚才下载的 ZIP 文件,然后安装。

或者解压安装包,上传到插件目录,/wp-content/plugins/。

3. 启用

安装完毕后,在已经安装的插件里启用 “Pure Highlightjs”。

如何使用

可直接在可视化编辑界面点击“插入代码”按钮,然后选择代码类型,粘贴代码插入即可:

GitHub 地址:Pure-Highlightjs

PHP设计模式-单例模式

单例模式(Singleton Pattern 单件模式或单元素模式)

单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

单例模式是一种常见的设计模式,在计算机系统中,线程池、缓存、日志对象、对话框、打印机、数据库操作、显卡的驱动程序常被设计成单例。

单例模式分3种:懒汉式单例、饿汉式单例、登记式单例。

单例模式有以下3个特点:

1.只能有一个实例。

2.必须自行创建这个实例。

3.必须给其他对象提供这一实例。

那么为什么要使用PHP单例模式?

PHP一个主要应用场合就是应用程序与数据库打交道的场景,在一个应用中会存在大量的数据库操作,针对数据库句柄连接数据库的行为,使用单例模式可以避免大量的new操作。因为每一次new操作都会消耗系统和内存的资源。

在以往的项目开发中,没使用单例模式前的情况如下:

//初始化一个数据库句柄
$db = new DB(...);
//比如有个应用场景是添加一条用户信息
$db->addUserInfo();
......
//然而我们要在另一地方使用这个用户信息,这时要用到数据库句柄资源,可能会这么做
......
function test() {
   $db = new DB(...);
   $db->getUserInfo();
......
有些朋友也许会说,可以直接使用global关键字!
   global $db;
......

的确global可以解决问题,也起到单例模式的作用,但在OOP中,我们拒绝这种编码。因为global存在安全隐患(全局变量不受保护的本质)。

全局变量是面向对象程序员遇到的引发BUG的主要原因之一。这是因为全局变量将类捆绑于特定的环境,破坏了封装。如果新的应用程序无法保证一开始就定义了相同的全局变量,那么一个依赖于全局变量的类就无法从一个应用程序中提取出来并应用到新应用程序中。

确切的讲,单例模式恰恰是对全局变量的一种改进,避免那些存储唯一实例的全局变量污染命名空间。你无法用错误类型的数据覆写一个单例。这种保护在不支持命名空间的PHP版本里尤其重要。因为在PHP中命名冲突会在编译时被捕获,并使脚本停止运行。

PHP单例模式实例:

先看图:

上面的对象图中,有一个“单例对象”,而“客户甲”、“客户乙”和“客户丙”是单例对象的三个客户对象。可以看到,所有的客户对象共享一个单例对象。而且从单例对象到自身的连接线可以看出,单例对象持有对自己的引用。

<?php
class User {
//静态变量保存全局实例
static private $_instance=null;
//私有构造函数,防止外界实例化对象
private function __construct() {
echo "构造了";
}
//私有克隆函数,防止外办克隆对象
private function __clone() {
}
//静态方法,单例统一访问入口
//用于访问类的实例的公共的静态方法
static public function getInstance(){
if(!(self::$_instance instanceof User)){
echo "实例化<br>";
self::$_instance = new self;
}
return self::$_instance;
}
public function getName() {
echo "hello world!";
}
}
$obj=User::getInstance();
$obj->getName();
$obj2=User::getInstance();
$obj2->getName();
?>

 

单例模式的优缺点:

优点:

1. 改进系统的设计

2. 是对全局变量的一种改进

缺点:

1. 难于调试

2. 隐藏的依赖关系

3. 无法用错误类型的数据覆写一个单例

Ajax同步和异步的区别

jquery的async:false,这个属性
默认是true:异步,false:同步。

 

async默认的设置值为true,这种情况为异步方式,就是说当ajax发送请求后,在等待server端返回的这个过程中,前台会继续 执行ajax块后面的脚本,直到server端返回正确的结果才会去执行success,也就是说这时候执行的是两个线程,ajax块发出请求后一个线程 和ajax块后面的脚本(另一个线程)例:

 

$.ajax({

type:"POST",

url:"Venue.aspx?act=init",

dataType:"html",

success:function(result){ //function1()

f1();

f2();

}

failure:function (result) {

alert('Failed');

},

}

function2();

 

在上例中,当ajax块发出请求后,他将停留function1(),等待server端的返回,但同时(在这个等待过程中),前台会去执行function2(),也就是说,在这个时候出现两个线程,我们这里暂且说为function1() 和function2()。

当把asyn设为false时,这时ajax的请求时同步的,也就是说,这个时候ajax块发出请求后,他会等待在function1()这个地方,不会去执行function2(),知道function1()部分执行完毕。

提示:其实如果同步就失去了ajax的意义.

 

 

ajax返回的数据类型中常见常用的有哪些?

通常如果用jquery实现的话有Html,text,xml和json四种类型,但事实上Ajax可以传回任意的数据类型。

type

(默认: “GET“) 请求方式 (“POST” 或 “GET“), 默认为 “GET

 

dataType

类型:String

预期服务器返回的数据类型。如果不指定,jQuery 将自动根据 HTTP 包 MIME 信息来智能判断,比如 XML MIME 类型就被识别为 XML。在 1.4 中,JSON 就会生成一个 JavaScript 对象,而 script 则会执行这个脚本。随后服务器端返回的数据会根据这个值解析后,传递给回调函数。可用值:

  • “xml”: 返回 XML 文档,可用 jQuery 处理。
  • “html”: 返回纯文本 HTML 信息;包含的 script 标签会在插入 dom 时执行。
  • “script”: 返回纯文本 JavaScript 代码。不会自动缓存结果。除非设置了 “cache” 参数。注意:在远程请求时(不在同一个域下),所有 POST 请求都将转为 GET 请求。(因为将使用 DOM 的 script标签来加载)
  • “json”: 返回 JSON 数据 。
  • “jsonp”: JSONP 格式。使用 JSONP 形式调用函数时,如 “myurl?callback=?” jQuery 将自动替换 ? 为正确的函数名,以执行回调函数。
  • “text”: 返回纯文本字符串

 

 

ajax:html

jQuery.ajax({
url:”×××”,
dataType:”html”,
async: true,
type: “post”,
success: function (data){
var aa=$(data).find(‘#id’).val();
alert(aa);
}
});

 

ajax:json

JS:

$.ajax({
type: “POST”,
url: “jk.php”,
// data: “name=John&location=Boston”,
success: function(msg){
// alert( “Data Saved: ” + msg );
var obj=JSON.parse(msg);
alert(obj[0].username);

}
});

 

php:

include(“DB.class.php”);
$obj=new DB(“127.0.0.1″,”root”,”root”);
$arr=$obj->Select(“select * from obj_users order by id desc”);
echo json_encode($arr);

 

 

 

 

http://www.w3school.com.cn/jquery/ajax_ajax.asp

https://www.cnblogs.com/bujianchenxi/p/6060799.html

本文实例讲述了php对象和数组相互转换的方法。分享给大家供大家参考

===========================方案一:$变量=(数据类型)值;

项目开发中,对象与数组的转换。

$变量=(数据类型)值; //将执行把值按指定的数据类型进行转换。

//数组转对象
$obj=(object)array("name"=>'张三22','password'=>'123456');
echo $obj->name;

//对象转数组
$arr=(array)$obj;
echo $arr['password'];

//自定义对象,然后转成数组
$obj2=(object)"";
$obj2->xingming="李四";
$obj2->shengao="177";
$arr2=(array)$obj2;
echo $arr2['shengao'];

 

===========================方案二:直接使用自定义函数

这里定义2个php匿名对象和数组相互转换的函数,代码如下:

<?php

function array2object($array) {
if(is_array( $array)) {
$obj= new  StdClass();
foreach($array  as  $key=> $val){
$obj->$key= $val;
}
}
else{ $obj= $array; }
return $obj;
}
function object2array($object) {
if(is_object($object)) {
foreach($object  as  $key=> $value) {
$array[$key] = $value;
}
}
else{
$array= $object;
}
return $array;
}
//用法示例如下:
$array= array('foo'=> 'bar','one'=> 'two','three'=> 'four');
$obj= array2object($array);
print$obj->one; // output's "two"

$arr= object2array($obj);
print$arr['foo']; // output's bar
?>
 

 

 

批量更新记录2种方案分析

表结构:
/* 方案一:
foreach($arr as $k=>$v){
$sql=”update obj_config2 set content='”.$v.”‘ where title2='”.$k.”‘”;
mysqli_query($conn,$sql);
}
*/
/*
上面即是循环一条一条的更新记录。一条记录update一次,这样性能很差,也很容易造成阻塞。
那么能不能一条sql语句实现批量更新呢?mysql并没有提供直接的方法来实现批量更新,但是可以用点小技巧来实现。
UPDATE categories
    SET 字段1 = CASE 字段2
        WHEN 1 THEN 3
        WHEN 2 THEN 4
        WHEN 3 THEN 5
    END
WHERE 字段2 IN (1,2,3)
这句sql的意思是,更新 字段1 字段,如果‘字段2‘=1 则‘字段1’ 的值为3,如果‘字段2‘=2 则‘字段1’ 的值为4,如果‘字段2‘=3 则‘字段1’ 的值为5。
*/
//方案二:推荐使用,这个效率更高,因为是拼装成一个完成的sql更新的。
$sql=”update obj_config2 set content = CASE title2  “;
foreach($arr as $k=>$v){
$sql.=”WHEN ‘”.$k.”‘ THEN ‘”.$v.”‘ “;
}
$sql.=”END”;