每日一些小技巧

调用api接口

跨域请求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...

laravel中使用PDO防止sql注入

具体的实现

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;

php二进制流手机上传图片模仿

模拟请求

   $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);

elpquent api资源的简单使用

生成资源

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);
    }
}

20个小技巧

触发父级的时间戳

在子模型更新时,可以触发父模型的时间戳。例如 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: 测试\
这里写图片描述

日积月累,谢谢大佬

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 5

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!