2013年4月27日星期六

京华时报:法国富豪捐赠兽首是场精明的买卖

  法国富豪捐赠兽首的时机很有意义。首先,此时正好是法国总统来华访问期间,捐赠兽首则给了中国一件大礼,有助于加强中法关系;其次,这也是一场精明的买卖。
  4月26日上午,国家文物局副局长宋新潮在北京会晤了法国PPR集团董事长兼首席执行官弗朗索瓦·亨利·皮诺。皮诺代表皮诺家族表示,将向中国政府捐赠流失海外的圆明园十二大水法中的青铜鼠首和兔首。
  皮诺先生称,将在9、10月份完成两件圆明园兽首的回归。而宋新潮副局长表示,中方希望能提前至7月份,这说明国家文物局对两件兽首归来的重视。
  据此,人们马上会想起2009年巴黎佳士得拍卖的这两件圆明园丢失的兽首。当年,佳士得拍卖行在法国巴黎大皇宫举办的拍卖会上,上拍了这两件兽首。在此之前,中国国家文物局以及国内民众一致要求巴黎佳士得撤拍两件兽首,但佳士得方面考虑整个专场是一个委托拍卖合同,虽然只撤拍两件,也是对整个专场拍卖协议的违约,法国方面过于强调遵守商业规则,没有顾及到中国人的情感。因此佳士得在与国家文物局多次交涉之后,最终没有撤拍。
  拍卖会上,拍卖师分别以1400万欧元将鼠首和兔首拍卖成交。中国商人蔡铭超竞买成功后马上宣布不付款,理由是:因为拍卖品是非法流失,故无法申报把兽首带入中国境内。这场一波三折的拍卖过程引起了国人的极大兴趣和广泛讨论,进而一度影响了佳士得在中国业务的发展。
  这次法国富豪捐赠兽首的时机很有意义。首先,此时正好是法国总统来华访问期间,捐赠兽首则给了中国一件大礼,有助于加强中法关系;其次,这也是一场精明的买卖。
  许多人也许不知道,亨利·皮诺除了是古驰、彪马等著名品牌的控制人以外,还在1998年成为了国际佳士得拍卖行的大股东,并保有至今。而佳士得公司刚刚在上海成立了独资拍卖公司,捐赠这两件礼物是明显向中国示好的动作。佳士得在步步争取获得中国的好感和支持,并有利于最终取得在国内的文物拍卖权!2009年以后,皮诺家族从兽首原持有人手中买下了这两件兽首,这次很好地抓住时机做成了觐见礼。

2013年4月26日星期五

PHP写文件函数file_put_contents确实给力


最近有个项目需要用file_put_contents函数写txt文件,由于需要频繁操作,所以经常出现前半截内容缺失的情况,非常苦恼。

后来查询资料发现,file_put_contents函数有个参数LOCK_EX非常有用,加上它之后,再也没有出现过内容缺失的情况了。

这个参数LOCK_EX的意思很直白,就是写文件时,先锁上这个文件,这样只允许某个客户端访问的时候写,其他客户端访问不能写了。

我的用法如下:
file_put_contents($file, $content, FILE_APPEND|LOCK_EX)
解释:
$file=>这个是写入文件的路径+文件名
$content=>这个是写入文件的内容
FILE_APPEND=>直接在该文件已有的内容后面追加内容
LOCK_EX=>写文件的时候先锁定,防止多人同时写入造成内容丢失

PHP操作ini配置文件



<?php
//写ini文件
function write_ini_file($assoc_arr, $path, $has_sections=FALSE)
{
    $content = "";
    if ($has_sections)
    {
        foreach ($assoc_arr as $key=>$elem)
        {
            $content .= "[".$key."]\n";
            foreach ($elem as $key2=>$elem2)
            {
                if(is_array($elem2))
                {
                    for($i=0;$i<count($elem2);$i++)
                    {
                        $content .= $key2."[] = \"".$elem2[$i]."\"\n";
                    }
                }
                else if($elem2=="") $content .= $key2." = \n";
                else $content .= $key2." = \"".$elem2."\"\n";
            }
        }
    }
    else
    {
        foreach ($assoc_arr as $key=>$elem)
        {
            if(is_array($elem))
            {
                for($i=0;$i<count($elem);$i++)
                {
                    $content .= $key2."[] = \"".$elem[$i]."\"\n";
                }
            }
            else if($elem=="") $content .= $key2." = \n";
            else $content .= $key2." = \"".$elem."\"\n";
        }
    }
    if (!$handle = fopen($path, 'w'))
    {
        return false;
    }
    if (!fwrite($handle, $content))
    {
        return false;
    }
    fclose($handle);
    return true;
}
 
//用法
//
$sampleData = array(
                'first' => array(
                    'first-1' => 1,
                    'first-2' => 2,
                    'first-3' => 3,
                    'first-4' => 4,
                    'first-5' => 5,
                ),
                'second' => array(
                    'second-1' => 1,
                    'second-2' => 2,
                    'second-3' => 3,
                    'second-4' => 4,
                    'second-5' => 5,
                ));
write_ini_file($sampleData, './data.ini', true);
 
//读ini文件
public function readini($name)
{
    if (file_exists(SEM_PATH.'init/'.$name))
    {
        $data = parse_ini_file(SEM_PATH.'init/'.$name,true);
        if ($data)
        {
        return $data;
        }
    }
    else
    {
        return false;
    }
}

PHP parse_ini_file() 函数


定义和用法
parse_ini_file() 函数解析一个配置文件,并以数组的形式返回其中的设置。
语法
parse_ini_file(file,process_sections)
参数 描述
file 必需。规定要检查的 ini 文件。
process_sections 可选。如果设置为 true,则返回一个多维数组,包括了配置文件中每一节的名称和设置。默认是 false。
说明
ini 文件的结构和 php.ini 的相似。
常量也可以在 ini 文件中被解析,因此如果在运行 parse_ini_file() 之前定义了常量作为 ini 的值,将会被集成到结果中去。只有 ini 的值会被求值。
由数字组成的键名和小节名会被 PHP 当作整数来处理,因此以 0 开头的数字会被当作八进制而以 0x 开头的会被当作十六进制。
提示和注释
注释:本函数可以用来读取你自己的应用程序的配置文件。本函数与 php.ini 文件没有关系,该文件在运行脚本时就已经处理过了。
注释:如果 ini 文件中的值包含任何非字母数字的字符,需要将其括在双引号中(")。
注释:有些保留字不能作为 ini 文件中的键名,包括:null,yes,no,true 和 false。值为 null,no 和 false 等效于 "",值为 yes 和 true 等效于 "1"。字符 {}|"~![()" 也不能用在键名的任何地方,而且这些字符在选项值中有着特殊的意义。
注释:自 PHP 5.0 版本开始,该函数也处理选项值内的新行。
例子
例子 1
"test.ini" 的内容:
[names]
me = Robert
you = Peter

[urls]
first = "http://www.example.com"
second = "http://www.w3school.com.cn"
PHP 代码:
<?php
print_r(parse_ini_file("test.ini"));
?>
输出:
Array
(
[me] => Robert
[you] => Peter
[first] => http://www.example.com
[second] => http://www.w3school.com.cn
)
例子 2
"test.ini" 的内容:
[names]
me = Robert
you = Peter

[urls]
first = "http://www.example.com"
second = "http://www.w3school.com.cn"
PHP 代码(process_sections 设置为 true):
<?php
print_r(parse_ini_file("test.ini",true));
?>
输出:
Array
(
[names] => Array
  (
  [me] => Robert
  [you] => Peter
  )
[urls] => Array
  (
  [first] => http://www.example.com
  [second] => http://www.w3school.com.cn
  )
)

2013年4月25日星期四

[教程] PHPCMS教程:PHP错误日志


错误日志的记录,可以帮助开发人员或者治理人员查看系统是否存在问题。在调试的时候可开启此功能。

建议不开启,影响速度。

一、开启错误日志

修改修改文件 根目录下面的 config.inc.php 文件,

找到 $CONFIG['enablephplog'] = '0'; //是否启用php错误日志

修改为:

$CONFIG['enablephplog'] = '1'; //是否启用php错误日志

二、查看错误日志

系统设置--系统工具 --php 错误日志

级别为:Notice 错误 为正常。

级别为: E_ERROR | E_WARNING | E_PARSE 中的任何一个,表示存在问题。



phpcms v9错误日志记录怎样清理?????????

直接删除error_log.php文件就可以了

MySQLi for Beginners

Introduction

Nearly every site that you visit nowadays has some sort of database storage in place, many sites opt to use MySQL databases when using PHP. However, many people haven't yet taken the step to interacting with databases properly in PHP. Here we guide you through what you should be doing - using PHP's MySQLi class - with a hat-tip to the one way that you definitely shouldn't be doing it.

The Wrong Way

If you're using a function called mysql_connect() or mysql_query() you really need to take note and change what you're doing. I understand that it's not easy to change current large projects, but look to change future ones.
Any of the functions that are prefixed with mysql_ are now being discouraged by PHP themselves as visible on this doc page, instead you should look to use one of the following:
  • MySQLi - The i standing for 'improved'.
  • PDO
Each has its advantages, PDO for example will work with various different database systems, where as MySQLi will only work with MySQL databases. Both are object oriented, but MySQLi allows procedural usage as well. There are other minor differences between the two, but it's up to you to choose which you want to use, here we'll be looking at MySQLi.

PHP MySQLi

Here we'll mostly be looking at the object oriented implementation, however, there is no reason you can't use this in a procedural format, but again no reason you shouldn't use the OO implementation.

Connecting

Connecting is as simple as just instantiating a new instance of MySQLi, we'll be using a username of user with a password of pass connecting to the demo database on the localhosthost:
$db = new mysqli('localhost', 'user', 'pass', 'demo');

if($db->connect_errno > 0){
    die('Unable to connect to database [' . $db->connect_error . ']');
}
Obviously, the database name is optional and can be omitted. If you omit the database name you must be sure to prefix your tables with the database in all of your queries.

Querying

Let's go ahead and pull out all of the users from the users table where they have live = 1:
$sql = <<<SQL
    SELECT *
    FROM `users`
    WHERE `live` = 1 
SQL;

if(!$result = $db->query($sql)){
    die('There was an error running the query [' . $db->error . ']');
}
We now have a variable that contains a mysqli_result object, we can now go ahead and do various things with this such as looping through the results, displaying how many there are and freeing the result.

Output query results

To loop through the results and output the username for each row on a new line we'd do the following:
while($row = $result->fetch_assoc()){
    echo $row['username'] . '<br />';
}
As you can see from this, the syntax isn't too dissimilar to the old mysql_ syntax that you're probably used to, this is just better and improved!

Number of returned rows

Each mysqli_result object that is returned has a variable defined which is called $num_rows, so all we need to do is access that variable by doing:
<?php
echo 'Total results: ' . $result->num_rows;
?>

Number of affected rows

When running an UPDATE query you sometimes want to know how many rows have been updated, or deleted if running a DELETE query, this is a variable which is inside the mysqliobject.
<?php
echo 'Total rows updated: ' . $db->affected_rows;
?>

Free result

It's advisable to free a result when you've finished playing with the result set, so in the above example we should put the following code after our while() loop:
$result->free();
This will free up some system resources, and is a good practice to get in the habit of doing.

Escaping characters

When inserting data into a database, you'll have been told (I hope) to escape it first, so that single quotes get preceeded be a backslash. This will mean that any quotes won't break out of any that you use in your SQL. This is still the case - and you should look to use the below method:
$db->real_escape_string('This is an unescaped "string"');
However, because this is a commonly used function, there is an alias function that you can use which is shorter and less to type:
$db->escape_string('This is an unescape "string"');
This string should now be safer to insert into your database through a query.

Close that connection

Don't forget, when you've finished playing with your database to make sure that you close the connection:
$db->close();

Prepared Statements

Prepared statements are complex to get your head around, but are really useful and can help alleviate a lot of the potential issues that you might have with escaping. Prepared statements basically work by you playing a ? where you want to substitute in a string,integerblob or double. Prepared statements don't substitute the value into the SQL so the issues with SQL injections are mostly removed.

Define a statement

Let's try to grab all of the users from the users table where they have a username of bob. We'd firstly define the SQL statement that we'd use:
$statment = $db->prepare("SELECT `name` FROM `users` WHERE `username` = ?");
That question mark there is what we're going to be assigning the word 'bob' to.

Bind parameters

We simply use the method bind_param to bind a parameter. You must specify the type as the first parameter then the variable as the second - so for instance we'd use s as the first parameter (for string), and our $name variable as the second:
$name = 'Bob';
$statement->bind_param('s', $name);
If we had 3 parameters to bind which are of varying types we could use bind_param('sdi', $name, $height, $age); for example. Note the types are not separated at all as the first parameter.

Execute the statement

No fuss, no mess, just execute the statement so that we can play with the result:
$statement->execute();

Iterating over results

Firstly we'll bind the result to variables, we do this using the bind_result() method which allow us specify some variables to assign the result to. So if we assign the returned name to the variable $returned_name we'd use:
$statement->bind_result($returned_name);
As before, if you have multiple variables to assign, just comma separate them - simple as that.
Now we have to actually fetch the results, this is just as simple as the earlier mysqli requests that we were doing - we'd use the method fetch(), which returns will assign the returned values into the binded variables - if we'd binded some.
while($statement->fetch()){
    echo $returned_name . '<br />';
}

Close statement

Don't forget to forgo a few seconds of your time to free the result - keep your code neat, clean and lean:
$statement->free_result();

MySQLi Transactions

One of the major improvements that MySQLi brings is the ability to use transactions. A transaction is a group of queries that execute but don't save their effects in the database. The advantage of this is if you have 4 inserts that all rely on each other, and one fails, you can roll back the others so that none of the data is inserted, or if updating fields relies on fields being inserted correctly.
You need to ensure that the database engine that you're using supports transactions.

Disable auto commit

Firstly you need to make it so that any query you submit doesn't automatically commit in the database. It's a simple one line boolean value:
$db->autocommit(FALSE);

Commit the queries

After a few queries that you've ran using $db->query() we can call a simple function to commit the transaction:
$db->commit();
Pretty simple stuff so far, and it's meant to be easy and approachable so that you have no reason to not use it.

Rollback

Just as easy as it is to commit something, it's just as simple to roll something back:
$db->rollback();
Take a look at the PHP documentation for an example of how to use rollbacks. I personally haven't found a scenario where I would use them, but they're worth knowing about so that you are aware they're there to be used.

Final Thoughts

Using mysql_ functions is a foolish move to make, don't use these outdated and useless methods because they're easier, or quicker. Man up and tackle one of the new forms of database interaction - MySQLi or PDO - you'll make @mfrost503 happier, and have better code too.

PHP and MySQLi quick tutorial / how to example



Here is a quick tutorial to get  you up in running with mysqli

<?php


// CONNECT TO THE DATABASE
$DB_NAME = 'DATABASE_NAME';
$DB_HOST = 'DATABASE_HOST';
$DB_USER = 'DATABASE_USER';
$DB_PASS = 'DATABASE_PASSWORD';
$mysqli = new mysqli($DB_HOST, $DB_USER, $DB_PASS, $DB_NAME);
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n"mysqli_connect_error());
exit();
}

// A QUICK QUERY ON A FAKE USER TABLE
$query = "SELECT * FROM `users` WHERE `status`='bonkers'";
$result = $mysqli->query($query) or die($mysqli->error.__LINE__);

// GOING THROUGH THE DATA
if($result->num_rows > 0{
while($row $result->fetch_assoc()) {
echo stripslashes($row['username']);
}
}
else {
echo 'NO RESULTS';
}
// CLOSE CONNECTION
mysqli_close($mysqli);

?>

This will work for 90% of your querying needs.