你真的了解現(xiàn)在的PHP嗎涂炎?(2)

良好實踐忠聚,這次主要挑了一些開發(fā)PHP應用時應該運用上的良好實踐進行詳細記錄,特別是良好實踐部分中密碼和流兩個點唱捣。關于代碼風格两蟀、(我個人)常用或者常見的做法會簡單帶過。

二震缭、標準 如果你了解PHP-FIG和PSR可以跳過這部分

PHP組件和框架的數(shù)量很多赂毯,隨之產(chǎn)生的問題就是:單獨開發(fā)的框架沒有考慮到與其他框架的通信。這樣對開發(fā)者和框架本身都是不利的拣宰。

打破舊局面的PHP-FIG
多位PHP框架的開發(fā)者認識到了這個問題党涕,在2009年的 php|tek(一個受歡迎的PHP會議)上談論了這個問題。經(jīng)過討論后得出:我們需要一個標準巡社,用來提高框架的互操作性膛堤。于是這幾位在php|tek意外碰頭的PHP框架開發(fā)者組織了PHP Framework Interop Group,簡稱PHP-FIG晌该。

PHP-FIG是框架代表自發(fā)組織的肥荔,其成員不是選舉產(chǎn)生的绿渣,任何人都可以申請加入PHP-FIG,并且能對處于提議階段的推薦規(guī)范提交反饋燕耿。另外中符,PHP-FIG發(fā)布的是推薦規(guī)范,而不是強制規(guī)定誉帅。

1.PSR是什么淀散?

PSR是PHP Standards Recommendation(PHP推薦標準)的簡稱。截至今日堵第,PHP-FIG發(fā)布了五個推薦規(guī)范:

你會發(fā)現(xiàn)只有四個吧凉,沒錯,因為第一份推薦規(guī)范PSR-0廢棄了踏志,新發(fā)布的PSR-4替代了阀捅。

2.PSR-1:基本的代碼風格

如果想編寫符合社區(qū)標準的PHP代碼,首先要遵守PSR-1针余。遵守這個標準非常簡單饲鄙,可能你已經(jīng)再使用了。標準的細節(jié)就不寫啦圆雁,點鏈接就能看忍级。

3.PSR-2:嚴格的代碼風格

PSR-2是在PSR-1的基礎上更進一步的定義PHP代碼規(guī)范。這個標準解決了很多世紀問題哈伪朽,比如縮進轴咱,大括號等等。細節(jié)也不多記錄啦烈涮。

另外朴肺,現(xiàn)在很多IDE(比如,PHPStorm)會有代碼格式化功能坚洽,設置代碼格式化的標準戈稿,編寫完代碼,然后全部格式化讶舰,可以幫助你遵循推薦規(guī)范鞍盗,修復一些換行、縮進跳昼、大括號等細節(jié)般甲。

設置標準

4.PSR-3:日志記錄器接口

這個推薦規(guī)范與前兩個不同,這是一個接口庐舟,規(guī)定PHP日志記錄器組件可以實現(xiàn)的方法欣除。符合PSR-3推薦規(guī)范的PHP日志記錄器組件,必須包含一個實現(xiàn)Psr\Log\LoggerInterface接口的PHP類挪略。PSR-3接口復用了RFC 5424系統(tǒng)日志協(xié)議历帚,規(guī)定要實現(xiàn)的九個方法:

<?php
namespace Psr\Log;

interface LoggerInterface
{
  public function emergency($message, array $context = array());
  public function alert($message, array $context = array());
  public function critical($message, array $context = array());
  public function error($message, array $context = array());
  public function warning($message, array $context = array());
  public function notice($message, array $context = array());
  public function info($message, array $context = array());
  public function debug($message, array $context = array());
  public function log($level, $message, array $context = array());
}

每個方法對應RFC 5424協(xié)議的一個日志級別。

使用PRS-3日志記錄器
如果你正在編寫自己的PSR-3日志記錄器杠娱,可以停下來了挽牢。因為已經(jīng)有一些十分出色的日志記錄器組件。比如:monolog/monolog摊求,直接用就可以了禽拔。如果不能滿足要求,也建議在此基礎上做擴展室叉。

5.PSR-4:自動加載器

這個推薦規(guī)范描述了一個標準的自動加載器策略睹栖。自動加載器策略是指,在運行時按需查找PHP類茧痕,接口或性狀野来,并將其載入PHP解釋器。

為什么自動加載很重要
在PHP文件的頂部你是不是經(jīng)匙倏酰看到類似下面的代碼曼氛?

<?php
include 'path/to/file1.php';
include 'path/to/file2.php';
include 'path/to/file3.php';

如果只需載入幾個PHP腳本,使用這些函數(shù)(include()令野、include_once()舀患、require()、require_once())能很好的完成工作气破×那常可是如果你要引入一千個PHP腳本呢?

在PSR-4推薦規(guī)范之前现使,PHP組件和框架的作者使用__autoload()和spl_autoload_register()函數(shù)注冊自定義的自動加載器策略低匙。可是朴下,每個PHP組件和框架的自動加載器都使用獨特的自動加載器努咐。因此,使用的組件多的時候殴胧,也是很麻煩的事情渗稍。

推薦使用PSR-4自動加載器規(guī)范,就是解決這個問題团滥,促進組件實現(xiàn)互操作性竿屹。

PSR-4自動加載器策略
PSR-4推薦規(guī)范不要求改變代碼的實現(xiàn)方式,只建議如何使用文件系統(tǒng)目錄結(jié)構(gòu)和PHP命名空間組織代碼灸姊。PSR-4的精髓是把命名空間的前綴和文件系統(tǒng)中的目錄對應起來拱燃。比如,我可以告訴PHP力惯,\Oreilly\ModernPHP命名空間中的類碗誉、接口和性狀在物理文件系統(tǒng)的src/目錄中召嘶,這樣PHP就知道,前綴為\Oreilly\ModernPHP的命名空間中的類哮缺、接口和性狀對應的src/目錄里的目錄和文件弄跌。

如何編寫PSR-4自動加載器
如果你在寫自己的PSR-4自動加載器,請停下來尝苇。我們可以使用依賴管理器Composer自動生成的PSR-4自動加載器枢贿。

三足绅、良好實踐

1.過濾族购、驗證和轉(zhuǎn)義

過濾HTML

使用htmlentities()函數(shù)過濾輸入旁瘫。

<?php
$input = '<p><script>alert("You won the Nigerian lottery!");</script></p>';
echo htmlentities($input, ENT_QUOTES, 'UTF-8');

需要注意的是:默認情況下,htmlentities()函數(shù)不會轉(zhuǎn)義單引號非竿,而且也檢測不出輸入字符串的字符集蜕着。正確的使用方式是:第一個參數(shù)輸入字符串;第二個參數(shù)設為ENT_QUOTES常量汽馋,轉(zhuǎn)移單引號侮东;第三個參數(shù)設為輸入字符串的字符集

更多過濾HTML輸入的方式豹芯,可以使用HTML Purifier庫悄雅。這個庫強健且安全,缺點:慢铁蹈,且可能難以配置宽闲。

SQL查詢

構(gòu)建SQL查詢不好的方式:

$sql = sprintf(
  'UPDATE users SET password = "%s" WHERE id = %s',
  $_POST['password'],
  $_GET['id']
);

如果 psasword=abc";-- ,則導致修改了整個users表的記錄password都未abc握牧。如果需要在SQL查詢中使用輸入數(shù)據(jù)容诬,要使用PDO預處理語句

用戶資料信息

A.過濾用戶資料中的電子郵件地址
這里會刪除除字符沿腰、數(shù)字和!#$%&'*+-/=?^_{|}~@.[]`之外的所有其他符號览徒。

<?php
$email = 'beckjiang@meijiabang.cn';
$emailSafe = filter_var($email, FILTER_SANITIZE_EMAIL);

B.過濾用戶資料中的外國字符

<?php
$string = "外國字符";
$safeString = filter_var(
  $string,
  FILTER_SANITIZE_STRING,
  FILTER_FLAG_STRIP_LOW|FILTER_FLAG_ENCODE_HIGH
);

驗證數(shù)據(jù)

驗證數(shù)據(jù)與過濾不同,驗證不會從輸入數(shù)據(jù)中刪除信息颂龙,而是只確認輸入數(shù)據(jù)是否符合預期习蓬。

驗證電子郵件地址
我們可以把某個FILTER_VALIDATE_*標志傳給filter_var()函數(shù),除了電子郵件地址措嵌,還可以驗證布爾值躲叼、浮點數(shù)、整數(shù)企巢、IP地址枫慷、正則表達式和URL。

<?php
$input = 'beckjiang@meijiabang.cn';
$isEmail = filter_var($input, FILTER_VALIDAE_EMAIL);
if ($isEmail !== false) {
  echo "Success";
} else {
  echo "Fail";
}

2.密碼

哈希算法有很多種,例如:MD5或听、SHA1探孝、bcrypt和scrypt。有些算法的速度很快神帅,用于驗證數(shù)據(jù)完整性再姑;有些算法速度則很慢萌抵,旨在提高安全性找御。生成密碼和存儲密碼時需要使用速度慢、安全性高的算法绍填。

目前霎桅,經(jīng)同行審查,最安全的哈希算法是bcrypt讨永。與MD5和SHA1不同滔驶,bcrypt是故意設計的很慢。bcrypt算法會自動加鹽卿闹,防止?jié)撛诘牟屎绫砉艚腋狻crypt算法永不過時,如果計算機的運算速度變快了锻霎,我們只需提高工作因子的值著角。

重新計算密碼的哈希值
下面是登錄用戶的腳本:

<?php
session_start();
try {
  // 從請求主體中獲取電子郵件地址
  $email = filter_input(INPUT_POST, 'email');

  // 從請求主體中獲取密碼
  $password = filter_input(INPUT_POST, 'password');
  
  // 使用電子郵件地址獲取用戶(注意,這是虛構(gòu)代碼)
  $user = User::findByEmail($email);

  // 驗證密碼和賬戶的密碼哈希值是否匹配
  if (password_verify($password, $user->password_hash) === false) {
    throw new Exception('Invalid password');
  }

  // 如果需要旋恼,重新計算密碼的哈希值
  $currentHashAlgorithm = PASSWORD_DEFAULT;
  $currentHashOptions = array('cost' => 15);
  $passwordNeedRehash = password_needs_rehash(
    $user->password_hash,
    $currentHashAlgorithm,
    $currentHashOptions
  );
  if ($passwordNeedsRehash === true) {
    // 保存新計算得出的密碼哈希值(注意吏口,這是虛構(gòu)代碼)
    $user->password_hash = password_hash(
      $password,
      $currentHashAlgorithm,
      $currentHashOptions
    );
    $user->save();
  }
  // 把登錄狀態(tài)保存到回話中
  ...
  // 重定向到個人資料頁面
  ...

} catch (Exception $e) {
  //異常處理
  ...
}

值得注意的是:在登錄前,一定要使用password_needs_rehash()函數(shù)檢查用戶記錄中現(xiàn)有的密碼哈希值是否過期冰更。如果過期了产徊,要重新計算密碼哈希值

PHP5.5.0之前的密碼哈希API
如果無法使用PHP5.5.0或以上版本蜀细,可以使用安東尼·費拉拉開發(fā)的ircmaxell/password-compat組件舟铜。這個組件實現(xiàn)了PHP密碼哈希API中的所有函數(shù):

  • password_hash()
  • password_get_info()
  • password_needs_rehash()
  • password_verify()

3.日期、時間和時區(qū)

DateTime類

DateTime類提供一個面向?qū)ο蠼涌诘煜危糜诠芾砣掌诤蜁r間谆刨。

沒有參數(shù),創(chuàng)建的是一個表示當前日期和時間的實例:

<?php
$datetime = new DateTime();

傳入?yún)?shù)創(chuàng)建實例:

<?php
$datetime = new DateTime('2017-01-28 15:27');

指定格式涣觉,靜態(tài)構(gòu)造:

<?php
$datetime = DateTime::createFromFormat('M j, Y H:i:s', 'Jan 2, 2017 15:27:30');

DateInterval類

DateInterval實例表示長度固定的時間段(比如痴荐,“兩天”),或者相對而言的時間段(比如官册,“昨天”)生兆。DateInterval實例用于修改DateTime實例。

使用DateInterval類:

<?php
// 創(chuàng)建DateTime實例
$datetime = new DateTime();

// 創(chuàng)建長度為兩周的間隔
$interval = new DateInterval('P2W');

// 修改DateTime實例
$datetime->add($interval);
echo $datetime->format('Y-m-d H:i:s');

創(chuàng)建反向的DateInterval實例:

<?php
// 過去一天
$interval = new DateInterval('-1 day');

DateTimeZone類

如果應用要迎合國際客戶,可能要和時區(qū)斗爭鸦难。

創(chuàng)建根吁、使用時區(qū):

<?php
$timezone = new DateTimeZone('America/New_York');
$datetime = new DateTime('2017-01-28', $timezone);

實例化之后,也可以使用setTimeZone()函數(shù)設置市區(qū):

$datetime->setTimeZone(new DateTimeZone('Asia/Hong_Kong'));

DatePeriod類

有時我們需要迭代處理一段時間內(nèi)反復出現(xiàn)的一系列日期和時間合蔽,DatePeriod類可以解決這種問題击敌。DatePeriod類的構(gòu)造方法接受三個參數(shù),而且都必須提供:

  • 一個Datetime實例拴事,表示迭代開始時的日期和時間沃斤。
  • 一個DateInterval實例,表示到下個日期和時間的間隔刃宵。
  • 一個整數(shù)衡瓶,表示迭代的總次數(shù)。

DatePeriod實例是迭代器牲证,每次迭代時都會產(chǎn)出一個DateTime實例哮针。

使用DatePeriod類:

<?php
$start = new DateTime();
$interval = new DateInterval('P2W');
$period = new DatePeriod($start, $interval, 3);

foreach ($period as $nextDateTime) {
  echo $nextDateTime->format('Y-m-d H:i:s'), PHP_EOL;
}

4.數(shù)據(jù)庫

PHP應用可以在很多種數(shù)據(jù)庫中持久保存信息,比如:MySQL坦袍、SQLite十厢、Oracle等。如果在項目中使用多種數(shù)據(jù)庫捂齐,需要安裝并學習多種PHP數(shù)據(jù)庫擴展和接口蛮放,這增加了認知和技術負擔。

正是基于這個原因辛燥,PHP原生提供了PDO擴展(PHP Data Objects筛武,意思是PHP數(shù)據(jù)對象),PDO是一系列PHP類挎塌,抽象了不同數(shù)據(jù)庫的具體實現(xiàn)徘六。PDO的介紹和使用就不寫了,比較常用榴都。

5.流

在現(xiàn)代的PHP特性中待锈,流或許是最出色但最少使用的。雖然PHP4.3.0就引入了流嘴高,但很多開發(fā)者不知道流的存在竿音,因為很少人提及流,而且流的文檔也匱乏拴驮。官方的解釋比較難理解春瞬,一句話說就是:流的作用是在出發(fā)地和目的地之間傳輸數(shù)據(jù)

我把流理解為管道套啤,相當于把水從一個地方引到另一個地方宽气。在水從出發(fā)地流到目的地的過程中,我們可以過濾水,可以改變水質(zhì)萄涯,可以添加水绪氛,也可以排出水(提示:水是數(shù)據(jù)的隱喻)。

流封裝協(xié)議

流式數(shù)據(jù)的種類各異涝影,每種類型需要獨特的協(xié)議枣察,以便讀寫數(shù)據(jù)。我們稱這些協(xié)議為流封裝協(xié)議燃逻。比如序目,我們可以讀寫文件系統(tǒng),可以通過HTTP唆樊、HTTPS或SSH與遠程Web服務器通信宛琅,還可以打開并讀寫ZIP、RAR或PHAR壓縮文件逗旁。這些通信方式都包含下述相同的過程:

  1. 開始通信。
  2. 讀取數(shù)據(jù)舆瘪。
  3. 寫入數(shù)據(jù)片效。
  4. 結(jié)束通信。

雖然過程一樣的英古,但是讀寫文件系統(tǒng)中文件的方式與手法HTTP消息的方式有所不同淀衣。流封裝協(xié)議的作用是使用通用的幾口封裝這些差異。

每個流都有一個協(xié)議和一個目標召调。格式如下:

<scheme>://<target>

說這么多有點懵膨桥,先看例子,使用HTTP流封裝協(xié)議與Flickr API通信:

<?php
$json = file_get_contents(
  'http://api.flickr.com/services/feeds/photos_public.gne?format=json'
);

不要誤以為這是普通的網(wǎng)頁URL唠叛,file_get_contents()函數(shù)的字符串參數(shù)其實是一個流標識符只嚣。http協(xié)議會讓PHP使用HTTP流封裝協(xié)議∫照樱看起來像是普通的網(wǎng)頁URL册舞,是因為HTTP流封裝協(xié)議就是這樣規(guī)定的:)。其他流封裝協(xié)議可能不是這樣障般。

file://流封裝協(xié)議

我們使用file_get_contents()调鲸,fopen()fwrite()fclose()函數(shù)讀寫文件系統(tǒng)挽荡。因為PHP默認使用的流封裝協(xié)議是file://藐石,所以我們很少認為這些函數(shù)使用的是PHP流。

隱式使用file://流封裝協(xié)議:

<?php
$handle = fopen('/etc/hosts', 'rb');
while (feof($handle) !== true) {
  echo fgets($handle);
}
fclose($handle);

顯式使用file://流封裝協(xié)議:

<?php
$handle = fopen('file:///etc/hosts', 'rb');
while (feof($handle) !== true) {
  echo fgets($handle);
}
fclose($handle);

流上下文

有些PHP流能接受一些列可選的參數(shù)定拟,這些參數(shù)叫流上下文于微,用于定制流的行為。流上下文使用stream_context_create()函數(shù)創(chuàng)建。

比如角雷,你知道可以使用file_get_contents()函數(shù)發(fā)送HTTP POST請求嗎祸穷?如果想這么做,可以使用一個流上下文對象:

<?php
$requestBody = '{"username": "beck"}';
$context = stream_context_create(array(
  'http' => array(
    'method' => 'POST',
    'header' => "Content-Type: application/json;charset=utf-8;\r\n" . 
                "Content-Length: " . mb_strlen($requestBody),
    "content" => $requestBody
  )
));
$response = file_get_contents('https://my-api.com/users', false, $context);

流過濾器

關于PHP的流勺三,其實真正強大的地方在于過濾雷滚、轉(zhuǎn)換、添加或刪除流中傳輸?shù)臄?shù)據(jù)吗坚。

注意:PHP內(nèi)置了幾個流過濾器:string.rot13祈远、string.toupper、string.tolower和string.strp_tags商源。這些過濾器沒什么用车份,我們要使用自定義的過濾器。

若想把過濾器附加到現(xiàn)有的流上牡彻,要使用stream_filter_append()函數(shù)扫沼。比如,想要把文件中的內(nèi)容轉(zhuǎn)換成大寫字母庄吼,可以使用string.toupper過濾器缎除。書中不建議使用這個過濾器,這里只是演示如何把過濾器附加到流上:

<?php
$handle = fopen('data.txt', 'rb');
stream_filter_append($handle, 'string.toupper');
while (feof($handle) !== true) {
  echo fgets($handle); // <-- 輸出的全是大寫字母
}
fclose($handle);

使用php://filter流封裝協(xié)議把過濾器附加到流上:

<?php
$handle = fopen('php://filter/read=string.toupper/resource=data.txt', 'rb');
while (feof($handle) !== true) {
  echo fgets($handle); // <-- 輸出的全是大寫字母
}
fclose($handle);

來看個更實際的流過濾?器示例总寻,假如我們nginx訪問日志保存在rsync.net器罐,一天的訪問情況保存在一個日志文件中,而且會使用bzip2壓縮每個日志文件渐行,名稱格式為:YYYY-MM-DD.log.bz2轰坊。某天,領導讓我提取過去30天某個域名的訪問數(shù)據(jù)祟印。使用DateTime類和流過濾器迭代bzip壓縮的日志文件

<?php
$dateStart = new \DateTime();
$dateInterval = \DateInterval::createFromDateString('-1 day');
$datePeriod = new \DatePeriod($dateStart, $dateInterval, 30);//創(chuàng)建迭代器
foreach ($datePeriod as $date) {
  $file = 'sftp://USER:PASS@rsync.net/' . $date->format('Y-m-d') . 'log.bz2';
  if (file_exists($file)) {
    $handle = fopen($file, 'rb');
    stream_filter_append($handle, 'bzip2.decompress');
    while (feof($handle) !== true) {
      $line = fgets($handle);
      if (strpos($line, 'www.example.com') !== false) {
        fwrite(STDOUT, $line);
      }
    }
    fclose($handle);
  }
}

計算日期范圍肴沫,確定日志文件的名稱,通過FTP連接rsync.net旁理,下載文件樊零,解壓縮文件,逐行迭代每個文件孽文,把相應的行提取出來驻襟,然后把訪問數(shù)據(jù)寫入一個輸出目標。使用PHP流芋哭,不到20行代碼就能做完所有這些事情沉衣。

自定義流過濾器

其實大多數(shù)情況下都要使用自定義的流過濾器。自定義的流過濾器是個PHP類减牺,繼承內(nèi)置的php_user_filter類豌习。這個類必須實現(xiàn)filter()存谎、onCreate()onClose()方法。而且肥隆,必須使用stream_filter_register()函數(shù)注冊自定義的流過濾器既荚。

PHP流會把數(shù)據(jù)分成按次序排列的桶,一個桶中盛放的流數(shù)據(jù)量是固定的栋艳。一定時間內(nèi)過濾器接收到的桶叫做桶隊列恰聘。桶隊列中的每個桶對象都有兩個公開屬性:data和datalen,分別是桶中的內(nèi)容和內(nèi)容的長度吸占。

下面定義一個處理臟字的流過濾器

<?php
class DirtyWordsFilter extends php_user_filter
{
  /**
   * @param resource $in         流來的桶隊列
   * @param resource $out        流走的桶隊列
   * @param resource $consumed   處理的字節(jié)數(shù)
   * @param resource $closing    是流中最后一個桶隊列嗎晴叨?
   */
  public function filter()
  {
    $words = array('grime', 'dirt', 'grease');
    $wordData = array();
    foreach ($words as $word) {
      $replacement = array_fill(0, mb_strlen($word), '*');
      $wordData[$word] = implode(' ', $replacement);
    }
    $bad = array_keys($wordData);
    $goods = array_values($wordData);

    // 迭代流來的桶隊列中的每個桶
    while ($bucket = stream_bucket_make_writeable($in)) {
      // 審查桶數(shù)據(jù)中的臟字
      $bucket->data = str_replace($bad, $goods, $bucket->data);

      // 增加已處理的數(shù)據(jù)量
      $consumed += $bucket->datalen;

      // 把桶放入流向下游的隊列中
      stream_bucket_append($out, $bucket);
    }

    return PSFS_PASS_ON;
  }
}

filter()方法的作用是接受、處理再轉(zhuǎn)運桶中的流數(shù)據(jù)矾屯。這個方法的返回值是PSFS_PASS_ON常量兼蕊,表示操作成功。

注冊流過濾器
接著件蚕,我們必須使用stream_filter_register()函數(shù)注冊這個自定義的DirtWordsFilter流過濾器:

<?php
stream_filter_register('dirty_words_filter', 'DirtWordsFilter');

第一個參數(shù)是用于識別這個自定義過濾器的過濾器名孙技,第二個參數(shù)是自定義過濾器的類名。

使用DirtWordsFilter流過濾器

<?php
$handle = fopen('data.txt', 'rb');
stream_filter_append($handle, 'dirty_words_filter');
while (feof($handle) !== true) {
  echo fgets($handle); // <-- 輸出審查后的文本
}
fclose($handle);

6.錯誤與異常

對錯誤和異常的處理骤坐,一定要遵守四個規(guī)則:

  • 一定要讓PHP報告錯誤绪杏。
  • 在開發(fā)環(huán)境中要顯示錯誤。
  • 在生產(chǎn)環(huán)境中不能顯示錯誤纽绍。
  • 在開發(fā)環(huán)境和生產(chǎn)環(huán)境中都要記錄錯誤。

錯誤與異常在日常使用的比較多势似,就不記錄啦拌夏。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市履因,隨后出現(xiàn)的幾起案子障簿,更是在濱河造成了極大的恐慌,老刑警劉巖栅迄,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件站故,死亡現(xiàn)場離奇詭異,居然都是意外死亡毅舆,警方通過查閱死者的電腦和手機西篓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來憋活,“玉大人岂津,你說我怎么就攤上這事≡眉矗” “怎么了吮成?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵橱乱,是天一觀的道長。 經(jīng)常有香客問我粱甫,道長泳叠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任茶宵,我火速辦了婚禮危纫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘节预。我一直安慰自己叶摄,他們只是感情好,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布安拟。 她就那樣靜靜地躺著蛤吓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪糠赦。 梳的紋絲不亂的頭發(fā)上会傲,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天,我揣著相機與錄音拙泽,去河邊找鬼淌山。 笑死,一個胖子當著我的面吹牛顾瞻,可吹牛的內(nèi)容都是我干的泼疑。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼荷荤,長吁一口氣:“原來是場噩夢啊……” “哼退渗!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蕴纳,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤会油,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后古毛,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體翻翩,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年稻薇,在試婚紗的時候發(fā)現(xiàn)自己被綠了嫂冻。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡颖低,死狀恐怖絮吵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情忱屑,我是刑警寧澤蹬敲,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布暇昂,位于F島的核電站,受9級特大地震影響伴嗡,放射性物質(zhì)發(fā)生泄漏急波。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一瘪校、第九天 我趴在偏房一處隱蔽的房頂上張望澄暮。 院中可真熱鬧,春花似錦阱扬、人聲如沸泣懊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽馍刮。三九已至,卻和暖如春窃蹋,著一層夾襖步出監(jiān)牢的瞬間卡啰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工警没, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留匈辱,地道東北人。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓杀迹,卻偏偏與公主長得像亡脸,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子树酪,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理梗掰,服務發(fā)現(xiàn),斷路器嗅回,智...
    卡卡羅2017閱讀 134,629評論 18 139
  • Composer Repositories Composer源 Firegento - Magento模塊Comp...
    零一間閱讀 3,956評論 1 66
  • Welcome 目前網(wǎng)絡上充斥著大量的陳舊信息,讓PHP新手誤入歧途摧茴,傳播著錯誤的實踐和糟糕的代碼绵载,這必須得到糾正...
    layjoy閱讀 21,663評論 7 118
  • 今天是星期天,本來想睡個懶覺的苛白,可是不知怎么了娃豹,我五點半就睡醒了。我跑去媽媽的房間购裙,看到媽媽還在睡夢中懂版,我就悄悄地...
    張高赫閱讀 216評論 0 0
  • 求變----沒有人可以改變你,除非你發(fā)自內(nèi)心想改變躏率; 求長----沒有人有義務幫助你躯畴,除非你主動尋求幫助民鼓; 求路-...
    Tracy_zhang閱讀 139評論 0 0