longdhdev / project_holaframework
一个简单的PHP框架
v1.0.9
2024-08-14 12:09 UTC
Requires
- php: >=7.4
- longdhdev/holaframework: v1.0.9
This package is auto-updated.
Last update: 2024-09-19 09:54:31 UTC
README
入门
composer create-project longdhdev/project_holaframework
composer install
版本v1.0.9的新功能
- 添加依赖注入
- 重构命名空间
- 模型改进
- 在模型中添加保存、软删除、分页、分页带计数功能
- 添加应用程序类
- 添加registerCommand和app()
- 改进响应和队列
- php版本 >= 8.0
列表
路由器
- 在router/web.php中设置
- 路由器将接收两个参数,第一个参数是url,第二个参数是包含控制器和控制器中函数的数组的数组
use Hola\Core\Router; use App\Controllers\HomeController; Router::get('/', [HomeController::class,'index']); Router::get('/home', [HomeController::class,'index']);
- 使用参数
use Hola\Core\Router; use App\Controllers\HomeController; // url {domain}/home/1 Router::get('/home/{id}', [HomeController::class,'index']); // url {domain}/home/detail/2 Router::get('/home/detail/{id}', [HomeController::class,'detail']);
- 使用带前缀的路由器
Router::prefix('home')->group(function (){ Router::get('/', [HomeController::class,'index']); Router::get('/detail', [HomeController::class,'detail']); Router::get('/list', [HomeController::class,'list']); }); // The path will be // https://domain.com/home // https://domain.com/home/detail // https://domain.com/home/list
- 当你想创建另一个路由器文件时,你可以在router文件夹中创建它,然后在router/index.php中添加以下代码
add()函数将识别你的路径,而loadFile()函数将加载你刚刚创建的路由器文件
use Hola\Core\ConfigRouter; $configRouter = new ConfigRouter(); $configRouter->add('api')->loadFile('api'); // https://domain.com/api $configRouter->add('api_v2')->loadFile('api_v2'); // https://domain.com/api_2 // or $configRouter->add([ 'web' => 'web', 'api_v2' => 'api' ])->work(); // https://domain.com/web // https://domain.com/api_v2
- 控制器中的参数
<?php namespace App\Controllers; class HomeController extends BaseController { public function index($id){ echo $id; } public function detail($id){ echo $id; } }
- 控制器中的请求和参数
<?php namespace App\Controllers; use Hola\Core\Request; class HomeController extends BaseController { public function index(Request $request, $id){ echo $id; } public function detail(Request $request, $id){ echo $id; } }
应用程序
- 在app/Controllers文件夹中创建控制器
- 在app/Models文件夹中创建模型
- 在app/views文件夹中创建视图
使用控制器
- 创建控制器
<?php namespace App\Controllers; use Hola\Core\BaseController; class HomeController extends BaseController { public function __construct() {} public function index(){ echo 'index'; } public function store(){ echo 'store'; } }
- 如何在控制器中创建命名空间
File in folder app/Controllers -> namespace App\Controllers File in folder app/Controllers/{name_folder} -> namespace App\Controllers\{name_folder}
- 运行create controller命令
- php cli.php create:controller NameController // or - php cli.php create:controller folder/folder/NameController
使用模型
- 创建模型
- 在模型中创建函数时,将其设置为静态函数
- 当你使用
create()、insert()、insertLastId()函数时,将自动创建具有date_created列的日期,使用update()函数将创建具有date_updated列的日期。如果设置为false,可以关闭此功能。 - 可以使用
$date_create和$date_update变量更改这两个默认日期列。 - 如果你不使用它们,可能不需要声明这三个变量
$times_auto、$date_create、$date_update。 - 运行create controller命令
- php cli.php create:model NameModel --table=name
<?php namespace App\Models; use Hola\Core\Model; class Categories extends Model { protected static $tableName = 'categories'; // protected static $times_auto = false; // protected static $date_create = "date_created"; // protected static $date_update = "date_updated"; protected static $field = [ 'id', 'name' ]; public static function index(){ echo 'categories index'; } }
- 在控制器中使用模型
=== 使用方法 1 ===
public function index(){ $category = $this->model(Categories::class)::index(); }
=== 使用方法 2 ===
class Controller extends BaseController { public function __construct() { $this->model([ Categories::class, Product::class ]); } public function listCategories(){ $data = $this->Categories::instance()->get()->values(); // or $data = $this->Categories->get()->values(); } public function listProduct(){ $data = $this->Product::instance()->get()->values(); // or $data = $this->Product->get()->values(); return $data; } }
=== 使用方法 3 ===
class Controller extends BaseController { public function __construct() {} public function listCategories(){ $data = Categories::instance()->get()->values(); } public function listProduct(){ $data = Product::instance()->get()->values(); return $data; } }
在模块中使用属性
- 模型中的属性将包括set和get函数。例如,如果你想设置表中的列名,set和get函数的结构将是setAttribute{column_table}和getAttribute{column_table}
- 以下示例代码
namespace App\Models; use Hola\Core\Database; use Hola\Core\Model; class Categories extends Model { protected static $tableName = 'categories'; protected static $times_auto = false; protected static $date_create = "date_created"; protected static $date_update = "date_update"; protected static $field = [ 'name', 'view', 'invalid' ]; public function setAttributeName($value) { return json_encode($value); } public function getAttributeName($value) { return json_decode($value); } }
使用视图
- 在app/views文件夹中创建名为{name_file}.view.php的视图
- 使用视图控制器
<?php namespace App\Controllers; use App\Models\Categories; use Hola\Core\BaseController; use Hola\Core\Request; use Hola\Core\Response; class HomeController extends BaseController { public function __construct() {} public function index(){ return $this->render_view('name_file', ["title" => "Home"]); } // or public function index2(){ return Response::view('name_file', ["title" => "Home"]); } }
- 在上面的示例视图中使用变量,在代码行中传递标题参数,可以声明如下
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <!-- use --> <title><?=$title?></title> <!-- or use variable var --> <title><?=@var('title')?></title> </head> <body> </body> </html>
- 运行create view命令
- php cli.php create:view name_view // or - php cli.php create:view folder/folder/name_view
使用请求
use Hola\Core\Request; class Controller extends BaseController { public function __construct() {} public function index(Request $request){ $name = $request->get('name'); $name = $request->name; // or $name = $request->value('name'); $file = $request->get_file('file'); $set_file = $request->file('file'); // use set file $extension = $request->extension(); // get extension file $size = $request->size(); // get size file $type = $request->type(); // get type file $originName = $request->originName(); // get originName file $isFile = $request->isFile(); // check file $all = $request->all(); // get all data request $session = $request->session('name'); // get session $cookie = $request->cookie('name'); // get cookie $cookie = $request->headers('name'); // get headers $has = $request->has('name'); // check key } }
使用验证请求
=== 方法 1 ===
$validate = Validation::create( $request->all(), [ 'username' => [ 'required', 'number', ], 'password' => [ 'required', 'number', 'max:6', 'min:6' ], ] );
=== 方法 2 ===
$validate = Validation::create( [ 'username' => $request->username, 'password' => $request->password ], [ 'username' => [ 'required', 'number', ], 'password' => [ 'required', 'number', 'max:6', 'min:6' ], ] );
可以使用以下代码返回你的错误信息
$validate = Validation::create( [ 'username' => $request->username, 'password' => $request->password ], [ 'username' => [ 'required' => 'Username is required', 'number' => 'username is number', ], 'password' => [ 'required', 'number', 'max:6', 'min:6' ], ] );
使用正则表达式
Validation::create([ 'username' => 'long' ], [ 'username' => [ 'pattern:/([0-9]+)/'=> 'You must be a number', ] ]);
在控制器中使用validateRequest。如果存在编码者识别的字段,此validateRequest函数将返回错误。如果条件满足,validateRequest函数将返回用户提交的数据
<?php namespace App\Controllers; use Hola\Core\BaseController; use Hola\Core\Request; use Hola\Core\Response; use Hola\Core\Validation; class HomeController extends BaseController { public function __construct() {} public function index(Request $request){ $validate = Validation::create( $request->all(), [ 'username' => [ 'required'=>'Không để trống', 'number', ], 'password' => [ 'required', 'number', 'max:6' => 'Pass phải lớn hơn hoặc bằng {{password}}', 'min:6' ], ] ); if(!empty($validate->errors())) { // show error return false; } $data = $validate->data(); // get data access return [ 'data_request' => $data ]; } }
使用表单请求
- 运行create form request命令
php cli.php create:request name
- 运行命令时,它将在request文件夹中生成一个名为{name}的文件。在这个文件中,你可以验证它
<?php namespace Request; use Hola\Core\FormRequest; class AuthRequest extends FormRequest { public function __construct() { parent::__construct(); } public function auth() { return true; } public function rules() { return [ 'username' => [ 'required'=>'Không để trống', 'number', ], 'password' => [ 'required', 'number', 'max:6' => 'Pass phải lớn hơn hoặc bằng {{password}}', 'min:6' ], ]; } /** * @return string * This function you can return view as you want, this function can be declared or not needed * If you want to use this function, you must declare the auth function first */ public function view_auth() { return 'error.index'; } /** * @return array * This function you can return data as you want, this function can be declared or not needed * If you want to use this function, you must declare the auth function first */ public function data_auth() { return [ 'message' => 'unauthorized', 'code' => 403 ]; } }
可以使用规则
required// 检查是否为空number// 检查数字max// 检查最大值min// 检查最小值pattern// 使用正则表达式检查boolean// 检查布尔值array// 检查数组date// 检查日期not_pattern// 使用正则表达式检查
使用响应
use Hola\Core\Response; class Controller extends BaseController { public function __construct() {} public function index(Request $request){ $data = []; return Response::view('name_view', $data); } public function json(Request $request){ $data = []; return Response::json($data, $status ?? 200); } public function redirectTo(Request $request){ $data = []; return Response::redirectTo('/login'); } }
- 在视图中使用变量
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title><?=$title ?? ''?></title> // get data </head> <body> </body> </html>
查询构建器
- 在模型中获取一条记录
Categories::instance()->first()->values();
- 使用带有函数 where 的列获取一条记录
Categories::instance()->where('id','=', 1)->first()->values(); // get by id Categories::instance()->where('name','=', 1)->first()->values(); // get by name Categories::instance()->where('name','like', '%value%')->first()->values(); // get by name
- 在模型中获取所有记录
Categories::instance()->get()->values();
-
使用带有函数 where 的列获取所有记录
get() 函数将返回一个对象。如果您想返回数组数据类型,可以使用 getArray() 函数。
Categories::instance()->where('id','=', 1)->get()->values(); // get by id Categories::instance()->where('name','=', 1)->get()->values(); // get by name Categories::instance()->where('name','like', '%value%')->get()->values(); // get by name // return data type array Categories::instance()->where('id','=', 1)->getArray(); // get by id Categories::instance()->where('name','=', 1)->getArray(); // get by name Categories::instance()->where('name','like', '%value%')->getArray(); // get by name // version 1.0.6 Categories::instance()->where('id','=', 1)->get()->toArray(); // get by id Categories::instance()->where('name','=', 1)->get()->toArray(); // get by name Categories::instance()->where('name','like', '%value%')->get()->toArray(); // get by name
$data1 = Categories::instance()->select('*')->where(function (Database $q){ $q->where('id',3)->orWhere('id',2); })->get()->toArray(); $data2 = Categories::instance()->select('*')->where(function (Database $q){ $q->where('id',3); })->orWhere(function (Database $q){ $q->where('id',2); })->get()->toArray();
- 使用 select()
Categories::instance()->select('*')->get()->values(); Categories::instance()->select(['*'])->get()->values(); Categories::instance()->select(['id','name'])->get()->values(); // with sum and count Summary::instance()->select([ 'SUM(amount) as amount', 'SUM(amount2) as amount2', ])->get()->values(); Region::instance()->select([ 'COUNT(id) as number' ])->get()->values();
- 使用 findById()
Categories::instance()->findById(1);
- 使用 orWhere()
Categories::instance()->where('id','=', 1)->orWhere('id','=',2)->get()->values();
- 使用 whereLike()
Categories::instance()->whereLike('name', '%long')->get()->values(); Categories::instance()->whereLike('name', 'long%')->get()->values(); Categories::instance()->whereLike('name', '%long%')->get()->values();
- 使用 orWhereLike()
Categories::instance()->orWhereLike('name', '%long')->get()->values(); Categories::instance()->orWhereLike('name', 'long%')->get()->values(); Categories::instance()->orWhereLike('name', '%long%')->get()->values();
- 使用 whereIn()
Categories::instance()->whereIn('id', [1,2])->get()->values();
- 使用 orWhereIn()
Categories::instance()->orWhereIn('id', [1,2])->get()->values();
- 使用 whereNotIn()
Categories::instance()->whereNotIn('id', [1,2])->get()->values();
- 使用 orWhereNotIn()
Categories::instance()->orWhereNotIn('name', [1,2])->get()->values();
- 使用 whereBetween()
Categories::instance()->whereBetween('date', ['2023-01-01 00:00:01','2023-12-31 23:59:59'])->get()->values();
- 使用 whereRaw()
Categories::instance()->whereRaw('id = 1 and age = 18')->get()->values();
- 使用 orWhereRaw()
Categories::instance()->where('id', 1)->orWhereRaw('id = 2')->get()->values();
- 使用 join
// way 1 Blog::instance()->select('*')->join('categories', function ($q) { $q->on('categories.id','=','category_blogs.category_id'); })->get()->values(); // way 2 Blog::instance()->select('*')->join('categories')->on('categories.id','=','category_blogs.category_id')->get()->values();
- 使用 left join
// way 1 Blog::instance()->select('*')->leftJoin('categories', function ($q) { $q->on('categories.id','=','category_blogs.category_id'); })->get()->values(); // way 2 Blog::instance()->select('*')->leftJoin('categories')->on('categories.id','=','category_blogs.category_id')->get()->values();
- 使用 right join
// way 1 Blog::instance()->select('*')->rightJoin('categories', function ($q) { $q->on('categories.id','=','category_blogs.category_id'); })->get()->values(); // way 2 Blog::instance()->select('*')->rightJoin('categories')->on('categories.id','=','category_blogs.category_id')->get()->values();
- 使用 order by
News::instance()->select('*')->orderBy('id', 'DESC')->get()->values(); // ASC, DESC
- 使用 group by
// way 1 News::instance()->select('*')->groupBy('id')->get()->values(); // way 2 News::instance()->select('*')->groupBy(['field1','field2','field3'])->get()->values();
- 使用 limit
News::instance()->select('*')->limit(100)->get()->values();
- 使用 limit 和 offset
News::instance()->select('*')->page(0)->limit(100)->get()->values(); // offset 0 limit 100 News::instance()->select('*')->page(1)->limit(100)->get()->values(); // offset 100 limit 100 News::instance()->select('*')->page(2)->limit(100)->get()->values(); // offset 200 limit 100
- 使用 insert
News::instance()->insert([ 'name' => 'Test', 'status' => 1 ]); // returns id on successful insert News::instance()->insertLastId([ 'name' => 'Test', 'status' => 1 ]);
- 使用 update
update 函数的第二个参数默认为 id如果您想使用其他列,请将其留为一个包含列键和值的数组
News::instance()->update([ 'name' => 'New2', 'status' => 1 ], 1); // id // other key News::instance()->update ([ 'name' => 'New2', 'status' => 1 ], [ 'id' => 1, 'name' => 'Test' ]); // id, name
- 使用 update 或 insert
- 此函数将检查数据是否存在。如果存在,则更新它;如果不存在,则插入它
updateOrInsert 函数的第二个参数默认为 id如果您想使用其他列,请将其留为一个包含列键和值的数组
News::instance()->updateOrInsert([ 'name' => 'New2', 'status' => 1 ], 1); // id // other key News::instance()->updateOrInsert([ 'name' => 'New2', 'status' => 1 ], [ 'id' => 1, 'name' => 'Test' ]); // id, name
- 此外,您还可以使用带有自定义函数的纯 SQL 语句
News::instance()->query("SELECT * FROM news WHERE id = 1")->get()->values(); News::instance()->query("SELECT * FROM news")->get()->values();
- 或者您可以使用数据库类使用以下示例中的纯 SQL 语句
$database = new Database(); $database->query("SELECT * FROM categories")->fetch(); $database->query("SELECT * FROM categories")->fetchAll();
- 除了 insert 函数外,您还可以使用 create 函数将数据插入到表中
请注意,create 函数将根据在模型内部声明的键插入列。如果您没有声明键,则在插入数据时使用 create 函数时,将忽略该列。
<?php namespace App\Models; use Hola\Core\Database; use Hola\Core\Model; class News extends Model { protected static $tableName = 'new'; protected static $field = [ 'title', 'name', 'status', 'date' ]; public static function index(){ News::instance()->create([ 'title' => 'title' 'name' => 'new', 'status' => 1, 'date' => '2023-09-28' ]); } }
- 使用 pagination() 函数
- 此函数将帮助缩短代码,而不是像以前那样必须使用 page() 和 limit() 函数。
- 第一个参数将是限制,第二个参数将是页码
- 如何使用
News::instance()->pagination(10, 1);
- 使用 paginationWithCount() 函数
- 此函数将接受 2 个参数,然后页码将返回已根据设计格式化的数据表
- 如何使用
$result = News::instance()->paginationWithCount(10, 1); // Return data [ "total" => 50, "items" => [], "page" => 1, "limit" => $limit, "total_page" => 10, ]
- 使用 save() 函数
- 此函数将用于添加或更新一条记录
- 如果对象具有已存在 id 数据,它将在数据库中更新,否则将添加一个新的对象
- 如何使用
$blog = new Blog(); $blog->name = 'Hi'; $blog->save();
- 使用 Database 类中的 table
<?php namespace App\Controllers; use Hola\Core\BaseController; use Hola\Core\Database; class HomeController extends BaseController { public function index(){ $all = Database::instance()->table('categories')->get()->values(); $first = Database::instance()->table('categories')->where('id','=',1)->first()->values(); } }
- 使用事务
<?php namespace App\Controllers; use Hola\Core\BaseController; use Hola\Core\Database; use App\Models\Categories; class HomeController extends BaseController { public function __construct() { $this->model([Categories::class]); } public function index(){ Database::beginTransaction(); try { Categories::instance()->insert(['name' => 'name1']); Database::commit(); }catch (\Exception $e) { Database::rollBack(); } } }
- 使用 Database 记录 SQL
<?php namespace App\Controllers; use Hola\Core\BaseController; use Hola\Core\Database; use App\Models\Categories; class HomeController extends BaseController { public function __construct() { $this->model([Categories::class]); } public function index(){ Database::enableQueryLog(); Categories::instance()->get()->values(); log_debug(Database::getQueryLog()); } }
- 使用模型类记录 SQL
<?php namespace App\Controllers; use Hola\Core\BaseController; use Hola\Core\Database; use App\Models\Categories; class HomeController extends BaseController { public function __construct() { $this->model([Categories::class]); } public function index(){ log_debug(Categories::instance()->where('id','=',1)->toSqlRaw()); } }
- 使用 union
Categories::instance()->union_all(Categories::clone())->get()->values(); /* * SELECT * FROM categories * UNION ALL * SELECT * FROM categories * */ Categories::instance()->union(Categories::clone())->get()->values(); /* * SELECT * FROM categories * UNION * SELECT * FROM categories */
- 使用 subQuery
Categories::instance()->subQuery(Categories::clone(), 'sub')->get()->values(); /* * SELECT * FROM (SELECT * FROM categories) as sub */ Categories::instance()->subQuery(Categories::select('id')->clone(), 'sub')->get()->values(); /* * SELECT * FROM (SELECT id FROM categories) as sub */
- 使用 collection
- 使用 collections,您可以使用
toArray、toObject、values、value、count、map、filter、push、add、chunk等函数来操作查询构建器
Categories::instance()->get()->values(); // get all value Categories::instance()->get()->toArray(); // get all value type array Categories::instance()->get()->toObject(); // get all value type object Categories::instance()->get()->value(); // get first value, use with map and filter functions Categories::instance()->get()->count(); // Count the amount of data Categories::instance()->get()->map(function ($item) { return $item->id; })->values(); // Map the data Categories::get()->filter(function ($item) { return $item->id === 1; })->values(); // filter data Categories::get()->map(function ($item) { return $item->id; })->value(); // Map the data and get one Categories::get()->filter(function ($item) { return $item->id === 1; })->value(); // filter data and get one // use chunk Categories::get()->chunk(3, function ($items) { foreach ($items as $item) { echo $item; } });
使用 relation
-
不同类型的关联
- 一对一
- 一对多
- 多对多
-
请注意,当您使用关联时,您将始终必须声明 Relations trait。** 让我们从一对一关系开始 **
-
一对一关系是一个非常基本的关系。例如,用户可以关联 1 个电子邮件。为了定义这种关系,我们在 User 模型上放置一个 email 方法。email 方法应该返回 hasOne 方法的结果
-
hasOne 函数将接受参数。例如,第一个参数是要调用的模型或您想连接的表的名称。第二个参数是表的外键。第三个参数将是您想与外键映射的主键。
<?php namespace App\Models; use Hola\Core\Model; use Hola\Traits\Relations; class User extends Model { use Relations; /** * Get the phone record associated with the user. */ public function email() { return $this->hasOne(Phone::class, 'user_id', 'id'); } }
- 一旦您成功使用 hasOne 创建了关联,您就可以像下面的代码一样调用它
$email = User::instance()->with('email')->find(1)->email; // or $email = (new User())->email()->find(1)->email;
- 现在,我们将定义一个在Email模型上的关系,以便我们可以访问User模型。我们使用hasOne的反向belongsTo方法
<?php namespace App\Models; use Hola\Core\Model; use Hola\Traits\Relations; class Email extends Model { use Relations; /** * Get the user that owns the email. */ public function user() { return $this->belongsTo(User::class, 'id', 'user_id'); } }
** 一对多 **
- 一对多关系用于在一种模型拥有另一种模型多个实例时定义关系。例如,一篇博客文章有许多评论。像许多其他Eloquent关系一样,一对多通过放置在模型上的函数来定义
<?php namespace App\Models; use Hola\Core\Model; use Hola\Traits\Relations; class Blog extends Model { use Relations; /** * Get the comments for the blog post. */ public function comments() { return $this->hasMany(Comment::class, 'blog_id', 'id'); } }
- 定义关系后,我们可以通过以下方式访问comments属性来获取评论集合
$comments = Blog::with('comments')->find(1)->comments; // or $comments = (new Blog())->comments()->find(1)->comments;
- 现在我们可以访问所有评论,让我们定义一个关系,允许从帖子中访问评论。为了确定hasMany关系的反向,我们使用belongsTo方法
<?php namespace App\Models; use Hola\Core\Model; use Hola\Traits\Relations; class Comment extends Model { use Relations; /** * Get the post that owns the comment. */ public function blog() { return $this->belongsTo(Blog::class, 'id', 'blog_id'); } }
- 定义关系后,我们可以通过访问blog来获取Comment对应的Post模型
$blog = Comment::instance()->with('blog')->find(1)->blog; // or $blog = (new Comment())->blog()->find(1)->blog;
** 多对多 **
- 多对多,比hasOne和hasMany稍微复杂一点的关系。这种关系的例子是,一个用户可以有多个角色,一个角色也属于多个用户。为了定义这种关系,需要有三个表:users、roles和user_role。user_role表将包含两个列user_id和role_id。
- 多对多关系通过调用belongsToMany或manyToMany方法来定义。例如,让我们在User模型上定义roles方法。
<?php namespace App\Models; use Hola\Core\Model; use Hola\Traits\Relations; class User extends Model { use Relations; /** * The roles that belong to the user. */ public function role() { return $this->belongsToMany(Role::class, 'user_role', 'user_id', 'role_id', 'id'); } // way two public function role() { return $this->manyToMany(Role::class, 'user_role', 'user_id', 'role_id', 'id'); } }
- 例如
$roles = User::with('role')->find(1)->role; // or $roles = (new User())->role()->find(1)->role;
- 此外,您可以在with函数内部使用查询构建器,如下面的示例所示
- 下面的语法将获取博客文章的id和title,这些文章在类别6中,并且浏览量大于0
<?php $query = Categories::with(['blog' => function ($query) { return $query->select('id, title')->where('view','>',0); }])->find(6)->value();
- 默认情况下,关系将遵循一个查询的whereIn条件。如果您想更改是否进行n + 1查询,您可以像下面的代码行一样更改。
- 将with函数的第二个参数设置为true会导致进行n + 1查询
<?php $query = Categories::with(['blog'], true)->find(6)->value();
- 使用count和sum
$sum = Categories::sum('view')->values(); $count = Categories::count('id')->values();
- 使用数组与collection
$array = [ ["id" => 1, "name" => "Name 1"], ["id" => 2, "name" => "Name 2"], ]; $data = new \Hola\Core\Collection($array); $data->values(); // get all value $data->toArray(); // get all value type array $data->toObject(); // get all value type object $data->value(); // get first value, use with map and filter functions $data->count(); // Count the amount of data $data->map(function ($item) { return $item->id; })->values(); // Map the data and get all $data->filter(function ($item) { return $item->id === 1; })->values(); // filter data and get all $data->map(function ($item) { return $item->id; })->value(); // Map the data and get one $data->filter(function ($item) { return $item->id === 1; })->value(); // filter data and get one // use chunk $data->chunk(3, function ($items) { foreach ($items as $item) { echo $item; } });
使用中间件
- 中间件将是检查请求是否前进进行处理的场所。它通常用于验证用户和许多其他事情,具体取决于您在中间件中编写的代码。
- 要创建中间件,您将在中间件文件夹中创建它
- 文件夹
middleware/{name}Middleware.php - 运行命令 create middleware
php cli.php create:middleware NameMiddleware
=== 方法 1 ===
<?php namespace Hola\Middleware; use Hola\Core\Response; use Hola\Core\Session; use Hola\Core\Request; class Auth { // return with key error code in function public function handle(Request $request){ if(!$request->session('auth')){ return $request->close('Login does not exit'); } return $request->next(); } }
=== 方法 2 ===
<?php namespace Hola\Middleware; use Hola\Core\Response; use Hola\Core\Session; use Hola\Core\Request; class Auth { // return with key error code in function public function handle(Request $request){ if(!$request->session('auth')){ return [ "error_code" => 1, "msg" => "Login does not exit" ]; } return [ "error_code" => 0 ]; } }
=== 第3种方式 ===
<?php namespace Hola\Middleware; use Hola\Core\Response; use Hola\Core\Session; use Hola\Core\Request; class Auth { // return boolean in function public function handle(Request $request){ if(!$request->session('auth')){ return false; } return true; } }
- 在中间件文件夹中位于Kernel.php文件中声明中间件名称
<?php namespace Hola\Middleware; class Kernel { public $routerMiddleware = [ "auth" => \Hola\Middleware\Auth::class, ]; }
- 在路由器中使用middleware
Router::middleware(['auth'])->group(function (){ // use many middleware Router::get('home', [HomeController::class,'index']); }); // or Router::middleware('auth')->group(function (){ // use one middleware Router::get('home', [HomeController::class,'index']); });
使用函数
- 使用
convert_to_array convert_to_array函数将对象数据转换为数组
<?php $data = new stdClass(); $data->name = 'Long'; $data->age = '22'; $data = convert_to_array($data); /* return * Array ( [name] => Long [age] => 22 ) * */ ?>
- 使用
convert_to_object convert_to_object函数将数组数据转换为对象
<?php $data = array(); $data['name'] = 'Long'; $data['age'] = '22'; $data = convert_to_object($data); /* return * stdClass Object ( [name] => Long [age] => 22 ) * */ ?>
使用翻译
- 当您想创建翻译时,您可以在语言文件夹中创建一个文件,并在文件中写下语言转换键,如下所示。
- 创建文件
vi.php - 您可以在config/constant.php文件中更改语言
define('LANGUAGE', 'vi');
<?php return [ "home" => "Trang chủ", "login" => "Đăng nhập" ];
- 创建文件
ja.php
<?php return [ "home" => "家", "login" => "サインイン" ];
- 创建并添加文件中的键后,您可以根据键使用函数
__()、translate()来转换语言
<?php echo __('home'); echo translate('home');
- 您可以通过在
__()和translate()函数的第三个参数中更改语言
<?php echo __('home', [], 'vi'); // print Trang chủ echo __('home', [], 'ja'); // print 家 echo translate('home', [], 'vi'); // print Trang chủ echo translate('home', [], 'ja'); // print 家
- 标识翻译文件中的键
<?php return [ "number" => "Total: {{value}}" ];
<?php echo __('number', ['value' => 10]); // print Total: 10
队列
- 使用redis或数据库的队列
- 在config/constant.php中更改队列连接
define('QUEUE_WORK', 'redis'); // use database or redis
- 要使用队列,在队列文件夹中创建一个文件,并声明如下
- 创建文件 Job1.php
<?php namespace Queue; class Job1 { public $params1 = 0; public $params2 = 0; public function __construct($params1, $params2) { $this->params1 = $params1; $this->params2 = $params2; } public function handle(){ // code } }
- 使用命令创建队列作业
php cli.php create:jobs SendEmail
- 在控制器中使用
<?php namespace App\Controllers; use Hola\Core\BaseController; use Hola\Core\Request; use Hola\Core\Response; use Hola\Queue\CreateQueue; use Hola\Queue\Job1; class HomeController extends BaseController { public function __construct() {} public function index(Request $request){ (new CreateQueue())->enQueue(new Job1(5,6)); return Response::view('welcome'); } }
- 您可以通过连接函数更改连接,请参阅下面的代码
<?php namespace App\Controllers; use Hola\Core\BaseController; use Hola\Core\Request; use Hola\Core\Response; use Hola\Queue\CreateQueue; use Hola\Queue\Job1; class HomeController extends BaseController { public function __construct() {} public function index(Request $request){ (new CreateQueue())->connection('redis')->enQueue(new Job1(5,6)); (new CreateQueue())->connection('database')->enQueue(new Job1(5,6)); return Response::view('welcome'); } }
// run queue connection - php cli.php queue:run redis - php cli.php queue:run database
- 我们已将队列名称默认为jobs。如果您想更改它,可以使用setQueue函数
(new CreateQueue())->setQueue('name_queue1')->enQueue(new Job1(5,6)); (new CreateQueue())->setQueue('name_queue2')->enQueue(new Job1(5,6)); // run Queue name - php cli.php queue:run --queue=name_queue1 - php cli.php queue:run --queue=name_queue2
- 目前作业的运行时间约为10分钟,您还可以在constants.php文件中更改QUEUE_TIMEOUT常量
- 此外,如果您不想为每个作业设置独立的时间,可以使用setTimeOut函数
(new CreateQueue())->setTimeOut(100)->enQueue(new Job1(5,6));
- 运行作业队列
- php cli.php queue:run
- 存在可能存在错误的任务,您可以使用以下命令重新运行它们
- php cli.php queue:run --queue=rollback_failed_job
- 使用数据库队列,您将创建以下两个表
- 表 failed_jobs
-- ---------------------------- -- Table structure for failed_jobs -- ---------------------------- DROP TABLE IF EXISTS `failed_jobs`; CREATE TABLE `failed_jobs` ( `id` int NOT NULL AUTO_INCREMENT, `data` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL, `queue` varchar(255) DEFAULT 'jobs', `exception` text DEFAULT NULL, `created_at` datetime NULL DEFAULT NULL, `updated_at` datetime NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC;
- 表 jobs
-- ---------------------------- -- Table structure for jobs -- ---------------------------- DROP TABLE IF EXISTS `jobs`; CREATE TABLE `jobs` ( `id` int NOT NULL AUTO_INCREMENT, `data` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL, `queue` varchar(255) DEFAULT 'jobs', `created_at` datetime NULL DEFAULT NULL, `updated_at` datetime NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 16 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC;
邮件
- 通过集成 phpmailer/phpmailer 包到项目中实现邮件发送
- 在 config/constant.php 文件中配置邮件
define('MAIL_CONNECTION', 'smtp'); define('MAIL_HOST', 'smtp.gmail.com'); define('MAIL_PORT', 465); define('MAIL_USERNAME', 'username@gmail.com'); define('MAIL_PASSWORD', 'password'); define('MAIL_ENCRYPTION', 'ssl'); define('MAIL_DEBUG', 0);
- 您可以通过 Email 类发送邮件,例如以下代码
<?php namespace App\Controllers; use Hola\Core\BaseController; use Hola\Core\Mail; class HomeController extends BaseController { public function __construct() {} public function sendMail() { $content = <<<HTML <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Title</title> </head> <body> This is the email content you want to write </body> </html> HTML; $mail = new Mail(); $mail->getMail()->SMTPDebug = 1; // debug mail $mail->from('youremail@gmail.com') // email sent ->withHTML() // Send email with html ->to('yourremail@gmail.com') // email you want to send to ->withData([ 'title' => 'tilte', // email title 'content' => $content, // email content, 'cc' => ['emailcc1@gmail.com'], // You want to cc an email 'cc' => [ ['email' => 'emailcc1@gmail.com', 'name' => ''], ['email' => 'emailcc2@gmail.com', 'name' => ''] ], // cc multiple emails, name can be left empty or added 'bcc' => ['emailbcc1@gmail.com'], // You want to bcc an email 'bcc' => [ ['email' => 'emailbcc1@gmail.com', 'name' => ''], ['email' => 'emailbcc2@gmail.com', 'name' => ''] ], // bcc multiple emails, name can be left empty or added 'attachment' => ['file'], // file attached 'attachment' => [ ['name'=> 'file1'], ['name'=> 'file2'], ] // file attached ]) ->work(); // received email } }
- 使用 phpmailer/phpmailer 包的函数
<?php namespace App\Controllers; use Hola\Core\BaseController; use Hola\Core\Mail; class HomeController extends BaseController { public function __construct() {} public function sendMail() { $mail = new Mail(); $mail = $mail->getMail(); // clone phpmailer try { //Server settings $mail->SMTPDebug = SMTP::DEBUG_SERVER; //Enable verbose debug output $mail->isSMTP(); //Send using SMTP //Recipients $mail->setFrom('from@example.com', 'Mailer'); $mail->addAddress('joe@example.net', 'Joe User'); //Add a recipient $mail->addAddress('ellen@example.com'); //Name is optional $mail->addReplyTo('info@example.com', 'Information'); $mail->addCC('cc@example.com'); $mail->addBCC('bcc@example.com'); //Attachments $mail->addAttachment('/var/tmp/file.tar.gz'); //Add attachments $mail->addAttachment('/tmp/image.jpg', 'new.jpg'); //Optional name //Content $mail->isHTML(true); //Set email format to HTML $mail->Subject = 'Here is the subject'; $mail->Body = 'This is the HTML message body <b>in bold!</b>'; $mail->AltBody = 'This is the body in plain text for non-HTML mail clients'; $mail->send(); echo 'Message has been sent'; } catch (Exception $e) { echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}"; } } }
- 在版本 v1.0.7 中,您可以使用以下命令创建一个用于发送独立邮件的类
php cli.php create:mail name_mail_class
- 文件结构将如下所示
<?php namespace Mails; use Hola\Core\Mail; class DefaultMail extends Mail { protected $useQueue = false; public function __construct() { parent::__construct(); } public function handle() { echo "send mail"; } }
- 如果变量 $useQueue 为 false,则在调用邮件类时将立即执行。如果 $useQueue 为 true,则将其推入队列。
- 请注意,在使用产品时,您将使用以下代码
(new CreateQueue())->enQueue(new DefaultMail()); // use queue (new DefaultMail()); // not use queue
命令
- 要开始使用,请运行以下命令以创建一个命令
- 例如,这里我将创建一个名为 Test1 的命令
php cli.php create:command Test1- 变量 $command 是您将要运行的命令,例如
php cli.php run:command_test - 变量 $command_description 是命令的标题
- $arguments 变量是要传递的参数,例如
php cli.php run:command_test name - $options 变量是选项,例如
php cli.php run:command_test name --options1=1 --options2=234
<?php namespace Commands; use Hola\Core\Command; class Test2Command extends Command { public function __construct() { parent::__construct(); } protected $command = 'run:command_test'; protected $command_description = 'A command to run'; protected $arguments = ['username']; protected $options = ['options1', 'options2]; public function handle() { $groups = [1,2,3,4,5]; $progressBar = $this->createProgressBar(count($groups)); echo $this->getArgument('username'); $progressBar->start(); foreach ($groups as $group) { sleep(2); $progressBar->advance(); } $progressBar->finish(); $this->output()->text('success'); } }
- 默认情况下,$arguments 是必需的。如果您不希望它是必需的,可以声明如下
protected $arguments = ['?username','?password'];
- 默认情况下,$options 是必需的。如果您不希望它是必需的,可以声明如下
protected $options = ['?group1','?group2'];
- 如果您不希望使用参数和选项,可能不需要在命令中声明它们,例如
<?php namespace Commands; use Hola\Core\Command; class Test2Command extends Command { public function __construct() { parent::__construct(); } protected $command = 'run:command_test'; protected $command_description = 'A command to run'; public function handle() { $this->output()->text('success'); } }
- 命令 clear cache router and config
php cli.php clear:cache