UserName: homestead
Password: secret
用户表
商品表 -> 用户
订单表 -> 用户 商品
评价表 -> 用户 商品 订单表
轮播图 ->
分类表 -> 分类表
购物车表 -> 用户 商品
用户地址表 -> 用户
用户收藏表 -> 用户 商品
php artisan make:model Address
php artisan make:model Cart
php artisan make:model Category
php artisan make:model City
php artisan make:model Collect
php artisan make:model Comment
php artisan make:model Good
php artisan make:model Order
php artisan make:model OrderDetails
php artisan make:model Slide
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Cart extends Model
{
use HasFactory;
// 允许批量赋值的字段
protected $fillable = ['user_id', 'goods_id', 'num'];
/**
* 所关联的商品
*/
public function goods()
{
return $this->belongsTo(Good::class, 'goods_id', 'id');
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
use HasFactory;
// 可批量赋值的字段
protected $fillable = ['name', 'pid', 'level', 'group'];
/**
* 分类的子类
*/
public function children()
{
return $this->hasMany(Category::class, 'pid', 'id');
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class City extends Model
{
use HasFactory;
// 指定模型关联的表名
protected $table = 'city';
/**
* 子类
*/
public function children()
{
return $this->hasMany(City::class, 'pid', 'id');
}
/**
* 父级
*/
public function parent()
{
return $this->belongsTo(City::class, 'pid', 'id');
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Collect extends Model
{
use HasFactory;
protected $guarded = [];
/**
* 收藏所属于的商品, 一对一
*/
public function goods()
{
return $this->belongsTo(Good::class, 'goods_id', 'id');
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
use HasFactory;
// 不允许批量赋值的字段
protected $guarded = [];
/**
* 强制转换的属性
*
* @var array
*/
protected $casts = [
'pics' => 'array',
];
/**
* 评论所属用户
*/
public function user()
{
return $this->belongsTo(User::class, 'user_id', 'id');
}
/**
* 评论所属商品
*/
public function goods()
{
return $this->belongsTo(Good::class, 'goods_id', 'id');
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Good extends Model
{
use HasFactory;
// 可批量赋值的字段
protected $fillable = [
'title',
'user_id',
'category_id',
'description',
'price',
'stock',
'cover',
'pics',
'is_on',
'is_recommend',
'details'
];
/**
* 强制转换的属性
*
* @var array
*/
protected $casts = [
'pics' => 'array',
];
/**
* 商品所属的分类
*/
public function category()
{
return $this->belongsTo(Category::class, 'category_id', 'id');
}
/**
* 商品所属的用户
*/
public function user()
{
return $this->belongsTo(User::class, 'user_id', 'id');
}
/**
* 商品所有的评价
*/
public function comments()
{
return $this->hasMany(Comment::class, 'goods_id', 'id');
}
/**
* 商品所有的收藏
*/
public function collects()
{
return $this->hasMany(Collect::class, 'goods_id', 'id');
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
use HasFactory;
// 可以批量赋值的字段
protected $fillable = [
'user_id',
'order_no',
'amount',
'address_id',
'status',
'trade_no',
'pay_type',
'pay_time'
];
/**
* 所属用户
*/
public function user()
{
return $this->belongsTo(User::class, 'user_id', 'id');
}
/**
* 订单拥有的订单细节
*/
public function orderDetails()
{
return $this->hasMany(OrderDetails::class, 'order_id', 'id');
}
/**
* 订单所关联的地址
*/
public function orderAddress()
{
return $this->hasOne(Address::class, 'id', 'address_id');
}
/**
* 订单远程一对多, 关联的商品
*/
public function goods()
{
return $this->hasManyThrough(
Good::class, // 最终关联的模型
OrderDetails::class, // 中间模型
'order_id', // 中间模型和本模型关联的外键
'id', // 最终关联模型的外键
'id', // 本模型和中间模型关联的键
'goods_id' // 中间表和最终模型关联的一个键
);
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class OrderDetails extends Model
{
use HasFactory;
// 可批量赋值的字段
protected $fillable = ['order_id', 'goods_id', 'price', 'num'];
/**
* 细节所属订单主表
*/
public function order()
{
return $this->belongsTo(Order::class, 'order_id', 'id');
}
/**
* 细节所关系的商品
*/
public function goods()
{
return $this->hasOne(Good::class, 'id', 'goods_id');
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Slide extends Model
{
use HasFactory;
protected $fillable = ['title', 'url', 'img', 'status', 'seq'];
}
composer require laravel-lang/lang:~8.0
使用composer(如上所述)将依赖项添加到您的应用程序后,您可以在目录下找到语言文件vendor/laravel-lang/lang
。
vendor/laravel-lang/lang/src/zh_CN 复制到 resources/lang/zh_CN
config/app.php
'locale' => 'zh_CN',
config/app.php
'timezone' => 'Asia/Shanghai',
或者修改为:PRC
composer require dingo/api
如果您想在配置文件中进行配置更改,您可以使用以下 Artisan 命令发布它(否则,不需要此步骤):
git init
git status
git add .
git commit -m '初始化项目'
php artisan vendor:publish --provider="Dingo\Api\Provider\LaravelServiceProvider"
<?php
namespace App\Http\Controllers;
use Dingo\Api\Routing\Helpers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
use Helpers;
}
API_STANDARDS_TREE=x
API_SUBTYPE=shop
API_PREFIX=api
API_VERSION=v1
API_NAME=shop
API_CONDITIONAL_REQUEST=false
API_STRICT=false
API_DEFAULT_FORMAT=json
API_DEBUG=true
App\Providers\RouteServiceProvider
// 用户认证相关路由
Route::prefix('api')
->middleware('api')
->namespace($this->namespace)
->group(base_path('routes/auth.php'));
// 前台路由
Route::prefix('api')
->middleware('api')
->namespace($this->namespace)
->group(base_path('routes/api.php'));
// 后台路由
Route::prefix('api')
->middleware('api')
->namespace($this->namespace)
->group(base_path('routes/admin.php'));
为了避免与你主要的项目路由冲突,dingo/api 将会使用其专属的路由实例。要创建端点,我们首先需要获得一个 API 路由的实例:
$api = app('Dingo\Api\Routing\Router');
现在我们必须定义一个版本分组。这种定义方式有利于后续为相同端点新增多版本支持。
$api->version('v1', function ($api) {
});
如果你想一个分组返回多个版本,只需要传递一个版本数组。
$api->version(['v1', 'v2'], function ($api) {
});
通过在第二个参数上传递一个属性数组,你也可以将此组视为特定框架的标准组。
$api->version('v1', ['middleware' => 'foo'], function ($api) {
});
你还可以嵌套常规组以进一步定制某些端点。
$api->version('v1', function ($api) {
$api->group(['middleware' => 'foo'], function ($api) {
});
});
一旦你有了一个版本分组,你就可以在分组闭包的参数中,通过 $api
创建端点。
$api->version('v1', function ($api) {
$api->get('users/{id}', 'App\Api\Controllers\UserController@show');
});
创建前台控制器
php artisan make:controller Api/UserController
class UserController
{
public function show()
{
return User::all();
}
}
你可以返回一个单一的用户。
class UserController
{
public function show($id)
{
return User::findOrFail($id);
}
}
响应生成器提供了一个流畅的接口去方便的建立一个更定制化的响应。响应的生成器通常是与 transformer 相结合。
要利用响应生成器,你的控制器需要使用 Dingo\Api\Routing\Helpers
trait。为了在你的控制器里保持引入和使用这个 trait,你可以创建一个基础控制器,然后你的所有的 API 控制器都继承它。
use Dingo\Api\Routing\Helpers;
use Illuminate\Routing\Controller;
class BaseController extends Controller
{
use Helpers;
}
现在你的控制器可以直接继承基础控制器。响应生成器可以在控制器里通过 $response
属性获取。
class UserController extends BaseController
{
public function show($id)
{
$user = User::findOrFail($id);
return $this->response->array($user->toArray());
}
}
class UserController extends BaseController
{
public function show($id)
{
$user = User::findOrFail($id);
return $this->response->item($user, new UserTransformer);
}
}
每个Transformer 可以对应一个模型,用来格式化响应的数据。Transformers
创建在APP目录下。Transformers 允许你便捷地、始终如一地将对象转换为一个数组。通过使用一个 transformer 你可以对整数和布尔值,包括分页结果和嵌套关系进行类型转换。
<?php
namespace App\Transformers;
use App\Models\User;
use League\Fractal\TransformerAbstract;
class UserTransformer extends TransformerAbstract
{
public function transform(User $user)
{
return [
'id' => $user->id,
'name' => $user->name,
'email' => $user->email,
'phone' => $user->phohe,
'avatar' => $user->avatar,
'openid' => $user->openid,
];
}
}
class UserController extends BaseController
{
public function index()
{
$users = User::all();
return $this->response->collection($users, new UserTransformer);
}
}
class UserController extends BaseController
{
public function index()
{
$users = User::paginate(25);
return $this->response->paginator($users, new UserTransformer);
}
}
return $this->response->noContent();
return $this->response->created();
这有很多不同的方式创建错误响应,你可以快速的生成一个错误响应。
// 一个自定义消息和状态码的普通错误。
return $this->response->error('This is an error.', 404);
// 一个没有找到资源的错误,第一个参数可以传递自定义消息。
return $this->response->errorNotFound();
// 一个 bad request 错误,第一个参数可以传递自定义消息。
return $this->response->errorBadRequest();
// 一个服务器拒绝错误,第一个参数可以传递自定义消息。
return $this->response->errorForbidden();
// 一个内部错误,第一个参数可以传递自定义消息。
return $this->response->errorInternal();
// 一个未认证错误,第一个参数可以传递自定义消息。
return $this->response->errorUnauthorized();
return $this->response->item($user, new UserTransformer)->addMeta('foo', 'bar');
节流限速 (throttling) 允许你限制客户端给定时间的访问次数。限制和过期时间是在限速器里定义的。 默认有两个限速器,验证通过限速器和未验证限速器。
要为路由或路由组启用节流限制,你必须启用 api.throttle
中间件。 一旦启用了节流限制,你必须已经配置过了一些限制或配置过了具体的路由限制。
$api->version('v1', ['middleware' => 'api.throttle'], function ($api) {
// 此版本组中的路由将需要身份认证.
});
如果只是想限制某些路由或者路由群组,可使用 limit
和 expires
选项。
$api->version('v1', function ($api) {
$api->get('users', ['middleware' => 'api.throttle', 'limit' => 100, 'expires' => 5, function () {
return User::all();
}]);
});
以上为这个路由设置了请求限制 100 次,过期时间 5 分钟。如果你把它设置在路由群组上,那组内的每个路由具有 100 次请求的限制。
$api->version('v1', ['middleware' => 'api.throttle', 'limit' => 100, 'expires' => 5], function ($api) {
$api->get('users', function () {
return User::all();
});
$api->get('posts', function () {
return Post::all();
});
});