每日一些小技巧

A_aliane發表於2019-04-10

跨域請求api,使用自封裝的類

自封裝curl類

  /**
     * @param $url 請求網址
     * @param bool $params 請求引數
     * @param int $ispost 請求方式
     * @param int $https https協議
     * @return bool|mixed
     */
    public static  function get($url, $params = false, $ispost = 0, $https = 0)
    {
        $httpInfo = array();
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36');
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        if ($https) {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // 對認證證照來源的檢查
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); // 從證照中檢查SSL加密演算法是否存在
        }
        if ($ispost) {
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
            curl_setopt($ch, CURLOPT_URL, $url);
        } else {
            if ($params) {
                if (is_array($params)) {
                    $params = http_build_query($params);
                }
                curl_setopt($ch, CURLOPT_URL, $url . '?' . $params);
            } else {
                curl_setopt($ch, CURLOPT_URL, $url);
            }
        }
        $response = curl_exec($ch);
        if ($response === FALSE) {
            //echo "cURL Error: " . curl_error($ch);
            return false;
        }
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $httpInfo = array_merge($httpInfo, curl_getinfo($ch));
        curl_close($ch);
        return $response;
    }

原文連結:部落格:好用的 CURL 類

呼叫

   $result = curl::get("http://172.16.112.3/api.php",'', true);
    $index=json_decode($result);
    return $index;

原生ajax實現跨域

 $.ajax({
                async: true,
                url: "http://172.16.112.3/api.php",
                type: "GET",
                dataType: "jsonp", // 返回的資料型別,設定為JSONP方式
                jsonp: 'callback', //指定一個查詢引數名稱來覆蓋預設的 jsonp 回撥引數名 callback
                jsonpCallback: 'handleResponse', //設定回撥函式名
                success: function (response, status, xhr) {
                    console.log('狀態為:' + status + ',狀態是:' + xhr.statusText);
                    console.log(response);
                }
            });

原生js實現跨域

 window.onload = function () {
        function jsonp(obj) {
            //定義一個處理Jsonp返回資料的回撥函式
            window["callback"] = function (object) {
                obj.success(object);
            }
            var script = document.createElement("script");
            //組合請求URL
            script.src = obj.url + "?callback=callback";
            for (key in obj.data) {
                script.src += "&" + key + "=" + obj.data[key];
            }
            //將建立的新節點新增到BOM樹上
            document.getElementsByTagName("body")[0].appendChild(script);
        }
        jsonp({
            url: "http://172.16.112.3/api.php",
            success: function (obj) {
                console.log(obj);
            }
        });
    }

使用Guzzle

參考文件: https://guzzle-cn.readthedocs.io/zh_CN/lat...

具體的實現

setAttribute() 這一行是強制性的,它會告訴 PDO 禁用模擬預處理語句,並使用 real parepared statements 。這可以確保SQL語句和相應的值在傳遞到mysql伺服器之前是不會被PHP解析的(禁止了所有可能的惡意SQL隱碼攻擊)。雖然你可以配置檔案中設定 字符集的屬性(charset=utf8),但是需要格外注意的是,老版本的 PHP( < 5.3.6)在DSN中是忽略字元引數的。

我們來看一段完整的程式碼使用例項:

  $user=$_POST['user']; $pass=$_POST['pass'];
  $dbh = new \PDO("mysql:host=localhost; dbname=zz", "root", "root");
  $dbh->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
  //禁用prepared statements的模擬效果
//        $dbh->exec    ("set names 'utf8'");
  $sql="select * from test where user=? and pass=?";
  $stmt = $dbh->prepare($sql);
  $exeres = $stmt->execute(array($user, $pass));
  if ($exeres) {
  //while條件為真時,輸出$row,
  while
  ($row = $stmt->fetch(\PDO::FETCH_ASSOC)){
  print_r($row);die();
 }  //失敗輸出登入失敗
  print_r("登入失敗");die();
 }

當呼叫 prepare() 時,查詢語句已經傳送給了資料庫伺服器,此時只有佔位符 ? 傳送過去,沒有使用者提交的資料;當呼叫到 execute()時,使用者提交過來的值才會傳送給資料庫,他們是分開傳送的,兩者獨立的,SQL攻擊者沒有一點機會。

注意事項

以下幾種情況,PDO並不能幫助你防範SQL隱碼攻擊

你不能讓佔位符 ? 代替一組值,如:

SELECT * FROM blog WHERE userid IN ( ? );

你不能讓佔位符代替資料表名或列名,如:

SELECT * FROM blog ORDER BY ?;

你不能讓佔位符 ? 代替任何其他SQL語法,如:

SELECT EXTRACT( ? FROM datetime_column) AS variable_datetime_element FROM blog;

模擬請求

   $postData=file_get_contents('C:\Users\ASUS\Pictures\Saved Pictures\2.jpg');
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, 'http://www.think.hk/upload1');
        curl_setopt($curl, CURLOPT_USERAGENT,'Opera/9.80 (Windows NT 6.2; Win64; x64) Presto/2.12.388 Version/12.15');
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // stop verifying certificate
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));//注意加這行程式碼
        curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
        $r = curl_exec($curl);
        curl_close($curl);
        print_r($r);

接收二進位制

 $xmlstr = file_get_contents('php://input') ? file_get_contents('php://input') : gzuncompress($GLOBALS['HTTP_RAW_POST_DATA']);//得到post過來的二進位制原始資料
//echo $xmlstr;die;
        $filename=time().'.png';
        $info=file_put_contents($filename,$xmlstr);
        if ($info) {
            $result = [
                'error' => '成功',
                'url'   => $filename
            ];
        } else {
            $result = ['error'   => 1,
                'message' => 404
            ];
        }
        return json_encode($result);

生成資源

php artisan make:resource Product
php artisan make:resource Admin

建立model以及遷移檔案

php artisan make:model Product -mc
php artisan make:model Admin -mc

遷移表

php artisan migrate

生成控制器

php artisan make:controller ProductController

資源類的操作

<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
use App\Http\Resources\Admin as Adminss;
use App\Admin as AdminModel;
class Product extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public $preserveKeys = true;
    public function toArray($request)
    {
        return [
            'data' => [
                'id' => $this->id,
                'name' => $this->name,
                'price' => $this->price,
                'username'=>Adminss::collection(AdminModel::where('id',$this->id)->get()),//獲取id相同的amdin表欄位
                'created_at' => $this->created_at,
                'updated_at' => $this->updated_at,
            ],
        ];
    }
}

封裝json返回資料格式 我使用了trait 並沒有使用api那個

<?php
namespace App\Http\api\messages;
trait ApiMessages{
    public function backSuccessMsg($data,$SuccessStatus,$falseStatus){
        if ($data){
            return response()->json([
                'status' => 'success',
                'status_code'=>$SuccessStatus,
                'msg' => '呼叫成功',
                'data'=>[
                    "status"=>100,
                    "data"=>$data]
            ]);
        }else{
            return response()->json([
                'status' => 'false',
                'status_code'=>$falseStatus,
                'msg' => '呼叫失敗',
                'data'=>[
                    "status"=>101]
            ]);
        }
    }
}

路由書寫 api.php編寫

Route::get('/products/{id}', 'ProductController@show');

控制器的書寫

<?php
namespace App\Http\Controllers;
use App\Product;
use Illuminate\Http\Request;
use App\Http\Resources\Product as ProductResource;
class ProductController extends Controller
{
    use \App\Http\api\messages\ApiMessages;
    public function show ()
    {
        $data=ProductResource::collection(Product::all()->keyBy->id);
        return $this->backSuccessMsg($data,$SuccessStatus=100,$FalseStatus=101);
    }
}

觸發父級的時間戳

在子模型更新時,可以觸發父模型的時間戳。例如 Comment 屬於 Post,有時更新子模型導致更新父模型時間戳非常有用。

例如,當 Comment 模型被更新時,您要自動觸發父級 Post 模型的 updated_at 時間戳的更新。Eloquent 讓它變得簡單,只需新增一個包含子模型關係名稱的 touch 屬性。

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
    /**
     * 涉及到的所有關聯關係。
     *
     * @var array
     */
    protected $touches = ['post'];
    /**
     * 獲取評論所屬的文章。
     */
    public function post()
    {
        return $this->belongsTo('App\Post');
    }
}

預載入精確的列

在使用預載入時,可以從關係中獲取指定的列。

$users = App\Book::with('author:id,name')->get();

為單個請求驗證使用者身份

你可以使用 Auth::once() 來為單個請求驗證使用者的身份,此方法不會使用 Cookie 會話。這意味著此方法可能有助於構建無狀態 API 。

if (Auth::once($credentials)) {
    //
}

重定向到帶有引數的控制器方法中

你不僅可以將 redirect() 方法用於使用者特定的 URL 或者路由中,還可以用於控制器中帶有引數的方法中

return redirect()->action('SomeController@method', ['param' => $value]);

如何使用 withDefault() 避免在關係中出現的錯誤

當一個關係被呼叫時,如果它不存在,則會出現致命的錯誤,例如 $post->user->name ,可以使用withDefault() 來避免。

/** 獲取文章作者 */
public function user()
{    
    return $this->belongsTo('App\User')->withDefault();
}

在模版中兩個平級的 $loop 變數

在 blade 的 foreach 中,即使在兩次迴圈中,依然可以通過使用 $loop 變數來獲取父級變數。

@foreach ($users as $user)    
    @foreach ($user->posts as $post)        
        @if ($loop->parent->first)            
            This is first iteration of the parent loop.        
        @endif    
    @endforeach
@endforeach

修改查詢結果

在執行 Eloqument 查詢後,你可以使用 map() 來修改行。

$users = User::where('role_id', 1)->get()->map(function (User $user) {
    $user->some_column = some_function($user);
    return $user;
});

輕鬆的使用 dd()

在 Eloqument 的最後加上 $test->dd(),來代替 dd($result)

// 優化前
$users = User::where('name', 'Taylor')->get();
dd($users);
// 優化後
$users = User::where('name', 'Taylor')->get()->dd();

Use hasMany to saveMany.

如果有 hasMany() 關聯關係,和想要從父類物件中儲存許多子類物件,可以使用 saveMany() 來達到你想要的效果。

$post = Post::find(1);
$post->comments()->saveMany([
    new Comment(['message' => 'First comment']),
    new Comment(['message' => 'Second comment']),
]);

在 Model::all() 中指定列

當你使用 Eloqument 的 Model::all() 時,你可以指定要返回的列。

$users = User::all(['id', 'name', 'email']);

Blade 中的 @auth

你可以使用 @auth 指令來代替 if 語句來檢查使用者是否經過身份驗證。

典型的方法:

@if(auth()->user())     // The user is authenticated. @endif

簡短的方法:

@auth   
 // The user is authenticated.
@endauth

預覽郵件而不傳送

如果你使用 Mailables 來傳送你的郵件,你可以預覽它們而不傳送出去。

Route::get('/mailable', function () {
    $invoice = App\Invoice::find(1);
    return new App\Mail\InvoicePaid($invoice);
});

hasMany 的特定檢查

在 Eloquent 的 hasMany() 關係中,你可以篩選出具有 n 個子記錄數量的記錄。

// Author -> hasMany(Book::class)
$authors = Author::has('books', '>', 5)->get();

恢復多個軟刪除

如果記錄使用了軟刪除,那麼你就可以一次恢復多條軟刪除記錄。

Post::withTrashed()->where('author_id', 1)->restore();

帶時區的遷移列

遷移檔案不僅有 timestamps() 時間戳,還有 timestampsTz() 帶有時區的時間戳。

Schema::create('employees', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->string('email');
    $table->timestampsTz();
});

檢視檔案是否存在?

你知道還可以檢查檢視檔案是否存在嗎?

if (view()->exists('custom.page')) {
    // Load the view
}

組中的路由組

在路由檔案中,你可以為一個路由組創造一個組,還可以為其指定特定的中介軟體。

Route::group(['prefix' => 'account', 'as' => 'account.'], function() {
    Route::get('login', 'AccountController@login');    
    Route::get('register', 'AccountController@register');
    Route::group(['middleware' => 'auth'], function() {        
        Route::get('edit', 'AccountController@edit');    
    });
});

Eloquent 中的日期時間方法

whereDay() , whereMonth() , whereYear() , whereDate() , whereTime() 這些方法皆為Eloquent 中檢查日期的方法。

$products = Product::whereDate('created_at', '2018-01-31')->get();
$products = Product::whereMonth('created_at', '12')->get();
$products = Product::whereDay('created_at', '31')->get();
$products = Product::whereYear('created_at', date('Y'))->get();
$products = Product::whereTime('created_at', '=', '14:13:58')->get();

在 Eloquent 關係中使用 orderBy()

你可以在 Eloquent 關係中直接指定 orderBy() 。

public function products()
{
    return $this->hasMany(Product::class);
}
public function productsByName()
{
    return $this->hasMany(Product::class)->orderBy('name');
}

無符號整型

對於遷移的外來鍵,不要使用 integer() , 而是使用 unsignedInteger() 或者是 integer()->unsigned() ,否則將會出現一系列的錯誤。

Schema::create('employees', function (Blueprint $table) {    
    $table->unsignedInteger('company_id');    
    $table->foreign('company_id')->references('id')->on('companies');    
});

轉自微信公眾號 : php中文網最新課程

一些符號

PHP中.=和+=

.=通俗的說,就是累積。

$a = 'a'; //賦值
$b = 'b'; //賦值
$c = 'c'; //賦值
$c .= $a;
$c .= $b;
echo $c; 就會顯示 cab

+=意思是:左邊的變數的值加上右邊的變數的值再賦給左邊的變數。

??和?:的區別

$a=$c??$b;
等同於 $a=isset($c)?$c:$b;
$a=$c?:$b;
等同於 $a=$c?$c:$b;

swoole

安裝swoole擴充

php擴充套件包地址:pecl.php.net\
swoole是一個PHP的非同步、並行、高效能網路通訊引擎,使用純C語言編寫,提供了PHP語言的非同步多執行緒伺服器,非同步TCP/UDP網路客戶端,非同步MySQL,非同步Redis,資料庫連線池,AsyncTask,訊息佇列,毫秒定時器,非同步檔案讀寫,非同步DNS查詢。 Swoole內建了Http/WebSocket伺服器端/客戶端、Http2.0伺服器端。\
Swoole可以廣泛應用於網際網路、行動通訊、企業軟體、雲端計算、網路遊戲、物聯網(IOT)、車聯網、智慧家居等領域。 使用PHP+Swoole作為網路通訊框架,可以使企業IT研發團隊的效率大大提升,更加專注於開發創新產品。

注意事項:\
1、server.php中的ip地址必須是外網可訪問地址 123.57.232.99,不能為localhost

1、安裝

# wget https://github.com/swoole/swoole-src/archive/swoole-1.7.6-stable.tar.gz 
# tar zxvf swoole-1.7.6-stable.tar.gz
# cd swoole-1.7.6-stable 
# phpize 
# ./configure 
# make  && make install** 

提示:

Build complete.
Don’t forget to run ‘make test’.
Installing shared extensions: /usr/lib64/php/modules/

說明安裝成功

2、php載入swoole擴充套件

extension=/xxx/xxx/php5.6/lib/php/extensions/no-debug-non-zts-20131226/swoole.so

3、重啟服務

service php-fpm restart
service nginx restart

4、測試,檢視phpinfo資訊,如下圖所示:

這裡寫圖片描述

5、程式碼測試

server.php程式碼:

# telnet 123.57.232.99 55152

Trying 123.57.232.99…
Connected to 123.57.232.99.
Escape character is ‘^]’.
rr\
Swoole: rr\
測試\
Swoole: 測試\
這裡寫圖片描述

日積月累,謝謝大佬

相關文章