每日一些小技巧
调用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 协议》,转载必须注明作者和本文链接
推荐文章: