這一章主要講解PHP操做數據庫的應用。須要具有一些數據庫前置知識,至少掌握mysql和redis的crud操做。就算不懂數據庫的知識也無所謂,數據庫語言都很是簡單,從字面意義就能明白是在作什麼。php
PHP鏈接數據庫的方式有2種:mysql
MySQLi extension ("i" 意爲 improved)laravel
PDO (PHP Data Objects)redis
二者的區別在於MySQLi只支持mysql,而PDO支持12種數據庫。sql
爲了方便,咱們只學習PDO的使用便可。由於咱們不能只會鏈接MySQL。這樣會讓咱們投入的時間性價比更高。數據庫
PDO和go的go-sql-driver,Java的JDBC做用是同樣的,連使用方法幾乎都很是一致。作法都是建立一個鏈接實例,經過鏈接實例執行sql。api
PHP7以後,php自動具有了PDO,可使用phpinfo函數查看是否開啓了PDO。數組
利用上一章學習到的路由和控制器知識,寫一個RESTfulAPI來查看php環境。瀏覽器
建立路由composer
Route::get('phpinfo', 'EnvironmentController');
建立控制器
class EnvironmentController extends Controller { public function __invoke() { // 注意須要鏈接一個空字符串,由於phpinfo沒有toString return phpinfo() . ''; } }
而後在瀏覽器訪問http://homestead.test/api/v1/phpinfo
。你應該會看到很是多的數據,能夠直接搜索PDO關鍵字,看到以下內容就表示當前運行環境的PDO是支持的。
建立一個PDO實例,傳入3個構造參數。第1個是數據庫鏈接,第2個是用戶名,第3個是用戶密碼。
function connDB($dbname = 'test') { $servername = "localhost"; $username = "homestead"; $password = "secret"; try { $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password); } catch (PDOException $e) { return $e->getMessage(); } }
使用建立出來的PDO實例conn來調用query方法,傳入要執行的sql做爲參數。
query方法返回bool值,成功爲true,失敗爲false。
失敗時還能夠經過conn訪問errorCode和errorInfo來獲取錯誤信息。
$sql = "CREATE DATABASE test"; if ($conn->query($sql) == true) { return "數據庫建立成功"; } else { return [ 'errorCode' => $conn->errorCode(), 'errorInfo:' => $conn->errorInfo() ]; }
建立表和建立數據庫的操做同樣,只是執行的sql不一樣。
插入insert、查詢select、修改update、刪除delete四種操做均可以使用exec
方法來執行,可是這個方法不返回任何值。只能經過try/catch
來捕獲異常來驗證是否成功。
$conn->exec($sql);
設置錯誤模式,用於拋出異常。若是不設置,sql執行失敗也不會拋出異常。
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
開啓事務$conn->beginTransaction();
提交事務$conn->commit();
回滾事務$conn->rollback();
開啓事務後開始執行sql語句,執行完畢提交事務。開啓異常捕獲,若是出現異常,執行回滾操做。
預處理語句就是定義模板,預留?
標記。例如:
insert into user (name, age, email) VALUES(?, ?, ?)
使用方法:
1.使用conn的prepare方法建立模板並返回一個對象stmt。其中字符串模板的填充字段用:前綴來修飾。
2.調用stmt的bindParam方法來綁定字段和值。接受2個參數,第1個參數是字段,第2個參數是值的變量名。
3.綁定後,執行stmt的方法execute來執行模板sql。
4.以後再次修改值時,直接修改變量的值,再次執行stmt的方法execute便可。
try { $stmt = $conn->prepare("insert into user (name, age, email, gender) VALUES(:name, :age, :email, :gender)"); $name = "張三"; $age = 134; $email = "@@@.@"; $gender = "男"; $stmt->bindParam(':name', $name); $stmt->bindParam(':age', $age); $stmt->bindParam(':email', $email); $stmt->bindParam(':gender', $gender); $stmt->execute(); // 再次插入行 $name = "李四"; $age = 22; $email = "lisi@gmail.com"; $stmt->execute(); return "插入成功"; } catch (PDOException $e) { return $e->getMessage(); }
這部分其實沒什麼可講的東西,框架作的事,無非就是在PDO或mysqli基礎上進行封裝,簡化咱們的操做而已。若是你是一直讀過來的同窗,應該發現了一個問題。從學框架應用開始,講的內容愈來愈含糊了。其實,這些框架的API我並非死記硬背的。大多數狀況下,我都是先讀一遍官方文檔,而後針對經常使用的API寫一些Demo測試。以後就是實戰了。在實戰中,若是發現有些需求處理的不夠優雅,就會在去官方文檔和社區尋找對應的更優解決方案。對我來說,學習框架的各類API是一件吃力不討好的事。
Laravel 能使用原生 SQL、流暢的查詢構造器 和 Eloquent ORM 在各類數據庫後臺與數據庫進行很是簡單的交互。
使用DBuse Illuminate\Support\Facades\DB;
.
執行查詢DB::select('select * from users where active = ?', [1]);
,返回值始終是數組。
執行插入DB::insert('insert into users (id, name) values (?, ?)', [1, 'Dayle']);
執行更新$affected = DB::update('update users set votes = 100 where name = ?', ['John']);
,返回更新的行數。
執行刪除$deleted = DB::delete('delete from users');
,返回刪除的行數。
運行普通語句DB::statement('drop table users');
無返回值。
使用db的transaction方法,參數是個函數,在裏面執行sql。
DB::transaction(function () { DB::table('users')->update(['votes' => 1]); // 這裏寫sql DB::table('posts')->delete(); });
看到這裏,你應該發現,咱們用框架作的事,和前面學的PDO作的事基本上是同樣的,區別只是寫法不一樣。
那爲何還要再學一遍呢?由於咱們要使用框架,框架幫助咱們處理了不少異常問題和邊界問題,簡化咱們的操做。
這裏我不想再講下去了,由於我不必把官方文檔的API挨個演示一遍。至於更高級的操做,如構造器和eloquent ORM,若是感興趣,建議你去中文社區進行學習這一部分的內容。https://learnku.com/docs/laravel/5.8/database/3925
其實在咱們目前的項目中,關於redis的使用頗有限。這裏不說redis集羣的使用方式,只說下redis的單機應用。
這裏假設你已經在本機安裝好redis。
關於redis的可視化管理工具,推薦 Redis Desktop Manager。
首先在項目中安裝predis包
composer require predis/predis
安裝predis的過程當中可能會遇到一個異常信息:
the requested PHP extension fileinfo is missing from your system
意思是沒有開啓fileinfo擴展,須要在你PHP環境的php.ini文件中修改一行配置,若是沒有這行配置那麼就添加上。
extension=php_fileinfo.dll
若是你的redis默認配置沒有修改,那麼項目中的配置也都不須要修改。
若是你的redis不是本機的,或者修改了端口等,須要在項目中的config/database.php和.env文件中分別修改配置。
database.php相關配置
'redis' => [
'client' => env('REDIS_CLIENT', 'predis'),
'options' => [
'cluster' => env('REDIS_CLUSTER', 'predis'),
'prefix' => Str::slug(env('APP_NAME', 'laravel'), '_').'_database_',
],
'default' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_DB', 0),
],
'cache' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_CACHE_DB', 1),
],
],
.evn相關配置。
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
predis的相關操做仍是很是簡單的,基本上都和redis的原生操做一致。
存值Redis::set('key', 'value');
取值Redis::get('key');
檢測某值是否存在Redis::exists('user_key')
設置過時時間Redis::setex('str', 10, 'bar');
刪除Redis::del('key');
redis的操做多達十幾種,這裏就再也不繼續羅列,更多操做可查閱:https://packagist.org/packages/predis/predis
這一章學習了在原生PHP和框架中操做mysql和redis的方式