轻巧易于使用的PHP框架。
DeJframework是一个简单而最小的PHP MVC框架,重点是简洁,简单性和可理解性。它的语法主要是从Laravel启发的。 DeJframework是由ATA Marzban开发的,用于学士学位的最终项目。
#安装
composer install 。为了使框架知道请求时该怎么办,您应该在 /app/routes.php中为应用程序设置路由。它很容易完成。
路由由HTTP方法,URL和如果使用指定的URL指定的方法提出请求,该路由应执行。没有设置路线就无法执行任何执行。您可以将关闭作为目的地:
[/app/routes.php]
Route:: set ( " GET " , " / " , function (){
return " Hello World! " ;
});如果您访问您的网站在yoursite.com上,则此代码将输出“ Hello World”。
[/app/routes.php]
Route:: set ( " GET " , " /some/url " , function (){
return " This is some url! " ;
});此代码将输出“这是一些URL!”如果您访问您的网站,请访问您的网站。
[/app/routes.php]
Route:: set ( " POST " , " /do/something " , function (){
return " Here you should write your own code to do the things you want. " ;
});如果您使用邮政方法访问yoursite.com/do/something,则将执行此代码。 (来自表格或API调用)
您可以在关闭或控制器中返回字符串,对象,数组或视图(稍后讨论)。字符串将直接输出,而对象或视图将自动转换为JSON和输出,并且视图将呈现为输出。
在下一部分中,您将学习如何将路由连接到控制器而不是关闭。
在MVC模式中,应将应用程序逻辑放入控制器中被认为是最佳实践。
[/app/controllers/YourController.php]
<?php
namespace app controllers;
class YourController extends dej mvc Controller
{
public static function yourAction ()
{
return " This is the right way to do it! " ;
}
}重要的是:正如您在上面的示例中看到的,对于PSR-0自动加载器的功能正常,在将任何类添加到应用程序中时,应遵循以下约定:
现在,让我们继续学习如何使控制器正常工作:
[/app/routes.php]
Route:: set ( " GET " , " / " , " YourController@YourAction " );当路由触发器时,将执行指定控制器上的指定操作。
不断实例化课程并将依赖性传递给他们可能会成为PHP开发中的重复任务。 dej App服务提供商的目标是使此过程尽可能干燥。使用此服务提供商,您无需在每个文件中添加使用语句并通过依赖项。以此示例:
/**
* Without a Service Provider
* when you want to build a query
*/
use dej db Connection ;
$ connection = Connection:: getInstance ();
use dej db Query ;
$ query = new Query ( $ connection );
$ result = $ query -> select ()-> from ( ' someTable ' )-> getAll ();
return $ result ;每当您想使用查询构建器时,都应重复这一点。现在,使用服务提供商:
use dej App ;
return App:: Query ()-> select ()-> from ( ' some_table ' );就是这样!看看DEJ/app.php,以查看其工作原理。在应用程序类上调用了一个名为“查询”的静态方法。它实例化查询类并将连接实例作为构造函数参数传递给其。蛋糕!
#request dejhttpRequest类使与请求的互动变得容易,请查看以下示例:
//check if request is ajax or not
$ result = App:: Request ()-> isAjax ();
//returns $_GET['name'];
$ result = App:: Request ()-> get ( ' name ' );
//returns $_POST['name'];
$ result = App:: Request ()-> post ( ' name ' );
//returns $_REQUEST;
$ result = App:: Request ()-> all (); #Response dejhttpResponse类使设置响应参数变得容易,如果要设置HTTP响应代码或标题,则应在控制器中返回响应,请查看以下示例:
class IndexController extends dej mvc Controller
{
public static function index ()
{
return App:: Response ()-> code ( 404 )-> header ( ' HTTP/1.1 404 Not Found ' );
}
}您可以轻松地重定向:
//in the controller
return App:: Response ()-> redirect ( ' /login ' );
//redirect with errors
App:: Response ()-> redirect ( ' / ' )-> withErrors ([ ' login ' => ' login unsuccessful! maybe password is wrong. ' ]);通过错误重定向会闪烁到会话的错误(稍后讨论)。
配置:首先在/config.json中输入数据库配置。 DeJframework在三层体系结构中处理数据库:
第1层 - 数据库连接对象:这扩展了Singleton抽象类。这意味着它仅是实例化的一次,这是第一次被称为。 DeJframework上的其他一些服务也是如此。为了防止每次要运行查询时连接到数据库的开销。这是您可以使用它的方法:
//simple query
$ result = App:: Connection ()-> executeQuery ( " SELECT * FROM some_table " );
//NonQuery: a query that doesn't return rows, only the number of affected rows.
$ result = App:: Connection ()-> executeNonQuery ( " DELETE FROM some_table WHERE some_field = 'some_value' " );
//A Query using prepared statements, To protect against SQL Injection.
$ result = App:: Connection ()-> executeQuery ( " SELECT * FROM some_table WHERE some_field = ? " , [ " some_value " ]);
//A Query using prepared statements, To protect against SQL Injection. With Multiple Parameters.
$ result = App:: Connection ()-> executeQuery ( " SELECT * FROM some_table WHERE some_field = ? AND another_field = ? " , [ $ some_value , " another_value " ]);
//A Query using prepared statements, To protect against SQL Injection. With Named Parameters.
$ result = App:: Connection ()-> executeQuery ( " SELECT * FROM some_table WHERE some_field = :some_value_name
AND another_field = :another_value_name " ,
[ " :some_value_name " => $ some_value ,
" another_value_name " => " another_value " ]);您可以在任何地方执行此操作,只要您添加use dejApp; 。
第2层 - 查询构建器:此类构建查询并使用连接类使用安全准备的语句运行它们。它应该针对每个新查询进行实例化,每次您键入App::Query()时,这是通过 /dej /app自动为您完成的,就像我们在Service Povider部分示例中看到的那样。您可以使用方法链条使用它来构建查询。看看以下示例:
$ result = App:: Query ()-> select ()-> from ( ' users ' )-> getAll ();
$ result = App:: Query ()-> select ()-> from ( ' users ' )-> getOne ();
$ result = App:: Query ()-> select ()-> from ( ' users ' )-> getJson ();
$ query = App:: Query ()-> select ()-> from ( ' users ' )-> getQuery ();如您所见,使用DEJ查询构建器很简单,请使用呼叫app :: query(),并且它会自动传递一个新的,依赖的注入Query类,然后您将其链接到它上的方法以添加您喜欢的条件,例如Select(),例如(),然后从(然后)使用get a in aw of the thes as a in a. get fet fet fet fet fet( getOne() getAll() ) getJson() )或构造的查询( getQuery() )。结果以STDCLASS格式获取,您可以轻松使用。值得注意的是,如果没有在查询末尾使用一种获取方法,结果就不会被获取。另外,您可以在多行上链接方法,例如,以多个步骤进行链接,以通过某种条件进行更改:
$ query = App:: Query ()-> select ();
if ( $ somecondition == true ) $ query -> from ( ' users ' );
else $ query -> from ( ' another_table ' );
$ result = $ query -> getAll ();在以下示例中,让我们查看查询构建器上可用的其他方法:
//All queries will be executed using prepared statements and parameters will be handled automatically.
//SELECT Queries:
$ result = App:: Query ()-> select ()-> from ( ' users ' )-> where ( ' id ' , ' = ' , ' 22 ' )-> getAll ();
//you can omit the operator and it uses '=' by default
$ result = App:: Query ()-> select ()-> from ( ' users ' )-> where ( ' id ' , ' 22 ' )-> getAll ();
$ result = App:: Query ()-> select ()-> from ( ' users ' )-> where ( ' city ' , ' = ' , ' Berlin ' )
-> andWhere ( ' age ' , ' > ' , ' 20 ' )-> getAll ();
$ result = App:: Query ()-> select ()-> from ( ' users ' )-> where ( ' city ' , ' = ' , ' Berlin ' )
-> orWhere ( ' city ' , ' = ' , ' Paris ' )-> getAll ();
$ result = App:: Query ()-> select ()-> from ( ' users ' )-> orderBy ( ' age ' , ' DESC ' )
-> limit ( 25 )
-> offset ( 50 )-> getAll ();
//INSERT Query:
$ affectedRows = App:: Query ()-> insertInto ( ' users ' )-> values ([ " username " => " jameshetfield " ,
" password " => " 19831983 " ,
" city " => " Downey " ])-> execute ();请注意,不返回结果的查询必须使用php execute()执行,并且它将自动返回受影响的行的数量。
//UPDATE Query:
$ affectedRows = App:: Query ()-> update ( ' users ' )-> set ([ " age " => 53 ,
" band " => " Metallica " ])
-> where ( ' username ' , ' = ' , ' jameshetfield ' )-> execute ();
//DELETE Query:
$ affectedRows = App:: Query ()-> deleteFrom ( ' users ' )-> where ( ' username ' , ' = ' , ' someone ' )-> execute ();请注意,删除或更新查询可能会导致数据丢失,如果没有提供的条款,作为安全措施,如果遇到这种情况,DEJFRAMEWORK将抛出异常。请手动使用连接类运行此类查询。
第3层 - 对象相关映射: ORM将在下一部分中讨论。
根据Wikipedia的说法:
对象关联映射(ORM)...是一种编程技术,用于在面向对象的编程语言中不兼容类型系统之间转换数据。这实际上创建了一个可以从编程语言中使用的“虚拟对象数据库”。
由于DEJFRAMEWORK在MVC体系结构中起作用,因此数据持久性包含在MVC的模型组件中。模型与您应用程序中的实体有关,例如用户,购买,产品等。它们需要保存并从数据库中检索。与大多数框架在面向对象的环境中运行一样,关系数据库以SQL语言和DEJFRAMEWORK工作。 PHP代码中间的SQL代码被认为不是最佳实践。因此,DeJframework试图将您与SQL代码分为3个级别,其中2个在上一节中详细阐述了,现在我们将看到如何使用模型:
class User extends dej mvc Model
{
protected static $ dbTable = " users " ;
//Format: ["db_field_name" => "modelPropertyName"]
protected static $ primaryKey = [ " id " => " id " ];
//Model properties
public $ username ;
public $ password ;
public $ city ;
.
.
.
} class User extends dej mvc Model
{
protected static $ dbTable = " users " ;
//Format: ["db_field_name" => "modelPropertyName"]
protected static $ dbFields = [ " username " => " username " ,
" password " => " password " ,
" city " => " city " ,
" id " => " id " ];
public $ username ;
public $ password ;
public $ city ;
.
.
.
}请注意, id属性是在模型扩展的/dej/mvc/Model类中定义的。因此,如果您希望模型具有ID,则无需再次定义它。
class User extends dej mvc Model
{
protected static $ dbTable = " users " ;
protected static $ dbFields = [ " username " => " username " ,
" password " => " password " ,
" city " => " city " ,
" id " => " id " ];
//Exactly the same as the class name
protected static $ modelName = " User " ;
public $ username ;
public $ password ;
public $ city ;
.
.
.
}现在就是这样,只要您已经正确设置了这些配置,则可以在模型上使用ORM方法。看看以下示例:
//Creating a new record
use app models User ;
$ user = new User ();
$ user -> username = " jameshetfield " ;
$ user -> password = " 13831383 " ;
$ user -> city = " Downey " ;
$ user -> create (); //Saved into the database.
//or you can set the properties in the constructor
$ user = new User ([
' username ' => ' jameshetfield ' ,
' password ' => ' 13831383 ' ,
' city ' => ' Downey '
]);
$ user -> create ();ORM使用下面的DEJ查询构建器来生成必要的查询。
请注意, create(),update()和delete()返回影响的行,您可以检查一下操作是否成功。
//Finding a record by a field named 'id'
$ user = User:: findById ( 11 );
//changing it's properties
$ user -> password = " through_the_never " ;
$ user -> update (); //Updated in the database.
//deleting it.
$ user -> delete ();请注意,这些功能与记录的主要键一起工作。
//Finding records by some condition.
$ users = User:: find ()-> where ( ' city ' , ' = ' , ' Sari ' )-> getAll (); //Returns an array of User objects.
//A more complex one
$ users = User:: find ()-> where ( ' city ' , ' = ' , ' Sari ' )-> andWhere ( ' age ' , ' > ' , 20 )-> orderBy ( ' age ' , ' ASC ' )
-> limit ( 25 )
-> offset ( 100 )-> getAll ();
//Don't forget the get*() method!
//Retrieveing all records
$ users = User:: getAll (); //doesn't need a getAll() at the end because it knows what to do.
//The method for deleting by condition is named 'wipe'
$ users = User:: wipe ()-> where ( ' status ' , ' = ' , ' banned ' )-> orWhere ( ' email_confirmation ' , ' = ' , ' 0 ' )-> execute ();
//counting all records
$ userCount = User:: countAll ();
//counting records that have a certain condition
$ userCount = User:: count ()-> where ( ' city ' , ' = ' , ' Sari ' )-> getInt (); //getInt() returns the count of the results as an Integer.DEJFRAMEWORK中的数据验证由dejValidator类处理。您可以以各种方式使用它:
App::Validator()验证服务,从而为您提供了它的singleton实例。它接受2个参数:要验证的值。 (字符串,int,数组,对象)和一组规则以验证数据相反。让我们看看它的工作原理:
use dej App ;
//Validate a single value according to a set of rules seperated by "|".
$ result = App:: Validator ()-> validate ( " This is going to be validated " , " required|string|min:5|max:30 " );
//Validate an object or and array:
$ result = App:: Validator ()-> validate ( $ user , [ ' username ' => ' required|string|email|min:5|max:30 ' ,
' password ' => ' required|string|min:10|max:100 ' ],
' age ' => ' int|min:18|max:99 ' ); validate()方法返回数组。如果没有验证错误并且数据有效,则将是一个空数组。因此,您可以检查数据是否有效使用empty() 。如果有任何验证错误,您将在数组中看到它们。
//The rules have changed
$ errors = App:: Validator ()-> validate ( " This is going to be validated " , " required|string|email|min:5|max:10 " );
var_dump ( $ errors );这就是上述代码将输出的内容:
array
0 => 'This Field should be an email'
1 => 'This Field should be less than 10'
现在有一个对象:
$ errors = App:: Validator ()-> validate ( $ obj , [ ' email ' => ' required|string|email ' ,
' password ' => ' required|string ' ,
' age ' => ' int ' ]);
var_dump ( $ errors );输出:
array (size=3)
'email' =>
array (size=1)
0 => string 'This Field should be an email'
'password' =>
array (size=2)
0 => string 'This Field is Required'
1 => string 'This Field should be more than 10'
'age' =>
array (size=1)
0 => string 'This Field should be a number'
如您所见,如果将对象或数组传递给验证器,它将返回与关联数组中的每个字段相关的错误,其中键是字段名称,并且值是包含与该字段相关的错误的数组。
validate()方法来验证请求参数(GET和POST参数)。 $ errors = App:: Request ()-> validate ([ ' email ' => ' required|string|email ' ,
' password ' => ' required|string|min:10|max:100 ' ]);
var_dump ( $ errors );访问yoursite.local/?email=notanemail&password=123将导致:
array (size=2)
'email' =>
array (size=1)
0 => string 'This Field should be an email'
'password' =>
array (size=1)
0 => string 'This Field should be more than 10'
/app/models/User.php中的用户模型: class User extends dej mvc Model
{
.
.
.
protected static $ validationRules = [ " username " => " required|string|min:5|max:20 " ,
" password " => " required|string|min:5|max:255 " ,
" city " => " string|max:10 " ];
.
.
.
}现在您可以验证模型的实例:
$ user = User:: getById ( 11 );
$ errors = $ user -> validate (); //returns errors in array like the previous examples.
$ isValid = $ user -> isValid (); //returns true or false当您有错误时,您可以将其传递到视图以显示,或将其重定向到其中的某个地方:
//in the controller
$ errors = $ user -> validate ();
if (! empty ( $ errors )) return App:: Response ()-> redirect ( ' / ' )-> withErrors ( $ errors );您在上一个示例中看到的验证消息是默认消息,如果您想更改它们,或者以自己的语言有验证消息怎么办?看/app/locale/en/validation/messages.php :
return [
" required " => " This Field is Required " ,
" string " => " This Field should be an string " ,
" int " => " This Field should be a number " ,
" min " => " This Field should be more than %s " ,
" max " => " This Field should be less than %s " ,
" email " => " This Field should be an email " ,
];您可以看到键的对应于验证类型,并且值是验证消息。变量包含在“ S”的消息中。在/app/locale中,您可以为自己选择的语言和该目录中创建自己的目录,并具有带有变量的验证消息。
您可以在/config.json中设置默认场所。
您可以通过App::Config()->locale = 'your_locale';
为了使用PHP会话,DeJframework提供dejSession类。以下是有关如何使用它的一些示例:
//to set session variables
App:: Session ()-> save ([
' key1 ' => ' value1 ' ,
' key2 ' => ' value2 '
]);
//to get session variables
$ value1 = App:: Session ()-> get ( ' key1 ' );
//to regenerate session id
App:: session ()-> regenerateId ();
//get all session variables as associative array
$ wholeSession = App:: session ()-> all ();
//destroy the session
App:: session ()-> destroy ();
//delete a variable
App:: session ()-> delete ( ' key1 ' );
//see if variable is set
$ trueOrFalse = App:: session ()-> isSaved ( ' key1 ' );如果您希望仅在下一个请求中可用会话变量,例如某个错误消息,则可以将其刷新到这样的会话:
App:: session ()-> flash ([ ' message ' => ' Registered Successfully! ' ]);并在下一个请求中检索它:
$ message = App:: session ()-> getFlash ( ' message ' );请注意,闪存消息仅在下一个请求中可用,只有->getFlash() 。
您可以将会话设置为自上次访问会话以来定义的时间后到期:
App:: Session ()-> save ([ ' key ' => ' value ' ]);
App:: Session ()-> lifeTime ( 60 ); //session will expire after 60 seconds since last access to the session. (last use of App::Session())有时,您可能希望您的应用程序记住下一个请求的模型实例。例如,您希望您的应用记住登录的用户,或者用户拥有的购物车或其他任何用户。如果您在会话中存储了所需的模型的主要键,并在每个请求中运行查询以检索它,则可能会变得乏味。 DeJframework通过为您提供可以在模型中使用的特征来解决此问题。看看:
class ShoppingCart extends dej mvc Model
{
use dej traits IsStateful;
.
.
.
}现在,您在模型中有更多方法可用:
//suppose you want to create a shopping cart for a guest user and add a product to it:
$ cart = new ShoppingCart ();
$ cart -> addProduct ( 2389 );
$ cart -> create (); //stored in the db
//if you want to save it to the session get it easily in the next request
$ cart -> remember ( ' guest_shopping_cart ' ); //provide a key to remember it by this key.现在在下一个请求中:
if (ShoppingCart:: isRemembered ( ' guest_shopping_cart ' )) //see if theres any cart in the session
$ cart = ShoppingCart:: retrieve ( ' users_shopping_cart ' ); //get's fresh data from the db
if (ShoppingCart:: hasChanged ( ' guest_shopping_cart ' ))
{
//checks if the cart in the database has changed **since you saved the cart in the session**.
doSomeThing ();
}
ShoppingCart:: forget ( ' guest_shopping_cart ' ); //forgets the cart.要将数据显示给用户,您需要一个用户界面。在网络中,大多数情况下,这意味着HTML标记。在MVC中,必须将逻辑与UI分开,因此您将HTML放置在视图中,并且仅在其中包含演示文稿逻辑,例如echo或将数组放入``foreach''中以迭代其上。要创建一个视图,您应该:
/app/views中创建您的视图文件。默认情况下包含一个视图: index.phtml <!DOCTYPE html >
< html >
< head >
< title > < ?= $data- > user- > username ? > 's profile </ title >
</ head >
< body >
< h2 > View < ?= $data- > user- > username ? > 's Profile </ h2 >
< p > Username: < ?= $data- > user- > username ? > </ p >
< p > Password: < ?= $data- > user- > password ? > </ p >
< p > City: < ?= $data- > user- > city ? > </ p >
</ body >
</ html > class IndexController extends dej mvc Controller
{
public static function index()
{
$ user = User:: find ()-> where ( ' username ' , ' = ' , ' jameshetfield ' )-> getOne ();
return App:: View ( ' user ' , [ ' user ' => $ user ]); //the first argument is the view name,
the second one is the data you want to pass to
the view, in this example, a variable called ' user '
will be available in the user.phtml view
which contains the instance of user we fetched.
Piece of cake!
}
}您也可以提供错误消息:
//in the controller
return App:: View ( ' user ' )-> withErrors ([ ' authorization ' => ' You are not allowed to view this user. ' ]);该框架将使视图输出,结果将是:
<!DOCTYPE html >
< html >
< head >
< title > jameshetfield's profile </ title >
</ head >
< body >
<!-- access the errors like this: -->
< span class =" error " > < ?= $this- > errors('authorization') ? > </ span >
< h2 > View jameshetfield's Profile </ h2 >
< p > Username: jameshetfield </ p >
< p > Password: 13831383 </ p >
< p > City: Downey </ p >
</ body >
</ html >现在让我们看看另一个示例,如果我们要创建所有用户的表怎么办?编辑您的视图:
<!DOCTYPE html >
< html >
< head >
< title > All Users </ title >
</ head >
< body >
< table >
< tr >
< th > username </ th >
< th > password </ th >
< th > city </ th >
</ tr >
< ?php foreach ($data- > users as $user): ? >
< tr >
< th > < ?= $user- > username ? > </ th >
< th > < ?= $user- > password ? > </ th >
< th > < ?= $user- > city ? > </ th >
</ tr >
< ?php endforeach; ? >
</ table >
</ body >
</ html >然后您的控制器:
class IndexController extends dej mvc Controller
{
public static function index ()
{
$ users = User:: getAll ();
return App:: View ( ' user ' , [ ' users ' => $ users ]);
}
}并亲自看看结果!
您可以在其他视图中创建查看部分并将其粘贴(包括):
[/app/views/partials/header.phtml]
<!--begin header-->
<!DOCTYPE html >
< html >
< head >
< meta charset =" UTF-8 " >
< title > < ?= $data- > title ? > </ title >
</ head >
< body >
<!--end header-->并将其粘贴到index.phtml :
[/app/views/index.phtml]
< ?php $this- > paste('partials/header'); ? >
< h2 > < ?= $data- > message ? > </ h2 >
.
.
.
</ html >身份验证是与应用程序有关的问题。它在每个应用程序中都可能非常不同,因此DeJframework不会在框架本身中实现它,相反,您将为您提供基本的用户模型,auth路由和控制器逻辑,使身份验证发生并且您可以自由更改或实现自己的解决方案,或实现自己的解决方案,在框架中实现的IsStateful方案在用户模型中实现了$user->remember() 。您唯一需要做的就是在config.json中设置'default_auth_model' ,以便能够使用IsStateful性状使用App::Request->user() to ::retrieve()从会话中的用户使用。
查看框架中提供的控制器,模型和视图,以了解其工作原理。并随心所欲地更改/改进/删除它。
注意:要使用户模型正常工作,您需要使用2个字段创建一个名为users的表:
TABLE: users
FIELD TYPE
id int, autoincrement
username varchar
password varchar(255) //password hashing system requires 255