GVKun编程网logo

laravel第四讲:路由命名及路由分组(laravel路由规则)

15

如果您想了解laravel第四讲:路由命名及路由分组的相关知识,那么本文是一篇不可错过的文章,我们将对laravel路由规则进行全面详尽的解释,并且为您提供关于django之路由分组,路由分发,FBV

如果您想了解laravel第四讲:路由命名及路由分组的相关知识,那么本文是一篇不可错过的文章,我们将对laravel路由规则进行全面详尽的解释,并且为您提供关于django 之路由分组,路由分发,FBV,CBV,ORM 框架、egg(14)--router进阶路由的几种写法、路由重定向、路由分组(路由映射、Gin框架之路由分组和路由嵌套、Laravel 4 初级教程之视图、命名空间、路由,laravel初级教程的有价值的信息。

本文目录一览:

laravel第四讲:路由命名及路由分组(laravel路由规则)

laravel第四讲:路由命名及路由分组(laravel路由规则)

路由命名

路由命名是为了程序能够方便的获取到路由信息,拿到该信息,可以进行重定向或作其他操作。路由命令通过name方法来实现。下面,我们来给一个路由命名:

Route::get('about', function () {})->name('index.about');

当给一个路由命名后,就可以通过助手函数route来获取该路由的url。

$url = route('index.about');
echo $url;  // http://localhost:8000/about

如果我们不想要前面的域名部分,只想拿后面的路径,那么可以这样

$url = route('index.about', [], false);
echo $url;  // /about

如果定义的是有参数的路由,那么可以把参数作为route函数的第二个参数传入

Route::get('news/{id}', 'IndexController@news')->name('home.news');

...
return redirect()->route('home.news', ['id' => 23]);

route函数中第二个参数数组元素可以自动和路由参数对应,若route函数中第二个参数数组元素比路由设定的参数多的话,则会自动拼接生成URL

echo route('home.news', ['id' => 23, 'page' => 3, 'page_num' => 20]);
// http://localhost:8000/news/23?page=3&page_num=20

路由分组

路由分组的作用是,当系统设定了许多路由,但发现有些路由有一些共同的点,比如有相同的命名空间前缀,或有相同的路径前缀,那么就可以把有共同点的那些路由放在一个路由中,方便了管理也减少了代码量,并且代码看上去也更加的优雅。

路由前缀

我们把有相同前缀的路由放在一个分组里。下面是两个有相同前缀的路由:

Route::prefix('index')->get('a', function () {
    return 'a'; // 匹配/index/a
});

Route::prefix('index')->get('b', function () {
    return 'b'; // 匹配/index/b
});

现在,我们将他们放到一个分组中

Route::prefix('index')->group(function ()
{
    Route::get('a', function () {
        return 'a'; // 匹配/index/a
    });
    Route::get('b', function () {
        return 'b'; // 匹配/index/b
    });
});

除了使用prefix方法外,还可以在group方法的第一个参数中设定,如下所示:

Route::group(['prefix' => 'index'], function ()
{
    Route::get('a', function () {
        return 'a'; // 匹配/index/a
    });
    Route::get('b', function () {
        return 'b'; // 匹配/index/b
    });
});

命名空间

命名空间也是一个经常会用到的路由分组。

Route::group(['namespace' => 'Home'], function ()
{
    Route::get('home/index', 'IndexController@index');
});

如果上述代码没有设置命名空间,则上面的路由则为

Route::get('home/index', 'Home\IndexController@index');

子域名

用来设定通过哪个域名可以访问,不是这个域名即使路径正确也不可以访问。

Route::domain('PHP.cn')->group(...)

名称前缀

name方法可以为每个路由分组中路由添加一个给定前缀

Route::name('abc.')->group( function ()
{
    Route::get('home', function () {

    })->name('home');
});

……
$url = route('abc.home');

django 之路由分组,路由分发,FBV,CBV,ORM 框架

django 之路由分组,路由分发,FBV,CBV,ORM 框架

今日的内容:

a. 路由系统
	1. 创建app
    2. 路由的分组
    3. 路由的分发
    	-	正则表达式匹配
    
b. django的orm(模型model)
	1. 创建模型的步骤
    2. orm基本的增删改查
    3. 正向查询和反向查询

注意事项:

1. 前台传给后台一个列表时,后端如何接受:
	request.POST.getlist(字段名)

2. 前台传给后台一个列表时,需要在ajax请求中增加一个参数:
	traditional: true

3. 多选框设置选中状态时,可以使用
	$("select的选择器").val(列表)

4. cookie的参数设置

	obj = render(request,''a.html'')
	obj.set_cookie(key,values,max_age,expires,path,
domain,secure,httponly)
参数详解
"""
key, 键
value=, 值
max_age=None, 超时时间
expires=None, 指定过期时间IE 专用 date = datetime.datetime() expires=date
path=''/'', cookie有效路径
domain=None, Cookie生效的域名
secure=False, https传输
httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)
"""
5. 删除Cookie   	
def logout(request):
    rep = redirect("/login/")
    rep.delete_cookie("user")  # 删除用户浏览器上之前设置的usercookie值
    return rep

6. 获取Cookie
username = request.COOKIES.get(''username'')  # 取出登录用户名

7. cookie的加盐
#通过加盐的方式为cookie签名。	
	obj.set_signed_cookie(''kkk'',''vvv'',  salt=''123456'') 
#获取经过签名后的cookie值。
	request.get_signed_cookie(''kkk'',	salt=''123456'') 
# 目录结构
migrations	# 模型操作的迁移文件
init
admin		# 管理文件,django admin的时候会用到
apps		# 应用信息定义文件,在其中生成了类AppCongfig,该类用于定义应用名等Meta数据
models		# 添加模块层数据类的文件,orm框架时使用
tests		# 测试代码文件
views		# 视图文件

路由分组

对多个视图进行一个分组,比如 class 为一个组,所有跟 class 相关的增,删,改,查视图都放在这个 app 中。各司其职,互不干扰。相比之前把所有的代码写到 urls 中,功能分划更清晰。

创建 app 的两种方式:

1. 使用 pycharm 创建 django 项目时,可以创建。缺点:只能创建一个
2. 命令行创建 python3 manage.py startapp app 名称(可创建多个),
  • django 使用的什么版本的解释器,就需要用对应的解释器创建 app
  • 需要在对应的目录下创建

分组:

第一种方式

a. 项目下的 urls.py 中

from *** import views
urlpatterns = [
 url(r''^test/'', views.test),
]

# 缺点,只能导入一个app,多个app会导致名称空间被污染
第二种方式
  1. django 项目下的 urls.py 文件,<strong style=color:red> 注意:需要导入 include 模块 </strong>
from django.conf.urls import url,include

urlpatterns = [
 	url(r''^classes/'',inclued("classes.urls")),
	url(r''^student/'',inclued("student.urls")),
	url(r''^teacher/'',inclued("teacher.urls"))
]

  1. 在对应的 app 下,创建一个 urls.py 文件

  2. 对应 app 的 urls.py

form django.conf.urls import url

from classes import views

urlpatterns = [
 url(r''^get_classes/'',views.get_classes),
]
  1. 对应 app 下的 views.py 文件内容为:
from django.shortcuts import render,HttpResponse

# Create your views here.

def get_classes(request):

   return HttpResponse("get_classes")

第二种方式的总结:

  • 客户端访问 127.0.0.1:8000/classes/get_classes 时,先进入到项目下的 urls.py 文件进行匹配
  • 根据项目下 urls.py 中的对应关系,进入到各个 app 项目下的 urls.py 文件中进行匹配
  • 根据各个 app 下的 urls.py 中的对应关系,匹配成功请求路径后,执行对应 app 项目下 views.py 文件下的函数。

路由分发

from app01 import views
urlpatterns = [
 url(r''^test/(?P<id>\w+)/(?P<name>\w+)'', views.test),
]


# app01项目下views.py文件:
def test(request,name,id):
 print(name)
 print(id)
 return HttpResponse("test")

# 浏览器访问
http://127.0.0.1:8000/test/0123/plf

# -------------------------views.py中打印结果---------------------
plf
0123



当浏览器中输入一个不存在的地址时,我们可以在浏览器中匹配对应的路径,然后为不存在的 url, 专门设置一个页面

from app01 import views
urlpatterns = [
 url(r''^'', views.notfound),
]

反向路由

当一个路径很长的时候,我们可以在路由系统中,设置一个变量 a, 用来代替这个路径,之后我们在 form 表单中 action 中写入 {% url "a" %} 即可.

# 路由系统中的写法
urlpatterns = [
	url(r''^logindbsjhalbdhaskbhdkjsabhdkbashkdbhsabdhsja/$'', views.login, name=''test''),
]

# 对应的html的页面中写法:
<form action="/test/" method="post">
    <input type="text">
</form>

django 中请求处理方式有 2 种:FBV 和 CBV

第一种:FBV (function base views)

就是在视图里使用函数处理请求

urls.py
from django.conf.urls import url, include
# from django.contrib import admin
from mytest import views

urlpatterns = [
 # url(r''^admin/'', admin.site.urls),
 url(r''^index/'', views.index),
views.py
from django.shortcuts import render

def index(req):
 if req.method == ''POST'':
     print(''method is :'' + req.method)
 elif req.method == ''GET'':
     print(''method is :'' + req.method)
 return render(req, ''index.html'')

第二种:CBV (class base views)

就是在视图里使用类处理请求。

urls.py
from mytest import views

urlpatterns = [
 # url(r‘^index/‘, views.index),
 url(r‘^index/‘, views.Index.as_view()),
]

# 注:url(r‘^index/‘, views.Index.as_view()),  是固定用法。
views.py
from django.views import View

class Index(View):
 def get(self, req):
     print(''method is :'' + req.method)
     return render(req, ''index.html'')

 def post(self, req):
     print(''method is :'' + req.method)
     return render(req, ''index.html'')

# 注:类要继承 View ,类中函数名必须小写。
''''''
''get'', ''post'', ''put'', ''patch'', ''delete'', ''head'', ''options'', ''trace''
form 只支持 post和 get
ajax 支持 所有的方法
''''''

ORM 框架

1. 先配置 mysql 的连接地址

# 在settings.py文件中,写入自己需要连接的数据库
DATABASES = {
# ''default'': {
#     ''ENGINE'': ''django.db.backends.sqlite3'',
#     ''NAME'': os.path.join(BASE_DIR, ''db.sqlite3''),
# }
''default'': {
''ENGINE'': ''django.db.backends.mysql'',
''NAME'':''orm'',
''USER'': ''root'',
''PASSWORD'': ''123456'',
''HOST'': ''192.168.81.161'',
''PORT'': ''3306'',
}
}

2. 在 app 中的__init__.py 文件中导入 pymysql 模块

import pymysql
pymysql.install_as_MySQLdb()

3. 在 app 项目下 models.py 文件中创建表。一个类一个表

# 类需要继承models.Model


from django.db import models
# Create your models here.
class UserInfo(models.Model):
 id = models.AutoField(primary_key=True)
 name = models.CharField(max_length=32)
 age = models.CharField(max_length=32)
 ut = models.ForeignKey("UserType",null=True)

4. 修改配置文件

​ 把我们的应用添加到对应的 settings.py 的 INSTALLED_APPS 中:

INSTALLED_APPS = [
''django.contrib.admin'',
''django.contrib.auth'',
''django.contrib.contenttypes'',
''django.contrib.sessions'',
''django.contrib.messages'',
''django.contrib.staticfiles'',
''****'',    #我们创建的应用
]

4. 创建表

python manage.py makemigrations  ## 生成迁移文件
python manage.py migrate   ## 生成实际的表

ps: 如果修改了models.py中的代码,需要重新执行上面的两行代码

5. 基本操作

第一种方式
models.users.objects.create(username=''xsmile'',password=12345)

第二种方式
a = {''username'':"plf",''passsword'':''123456''}
models.users.objects.create(**a)

第三种方式:插入多条数据
info = [
    models.UserInfo(name="root1",age=34,ut_id=1),
    models.UserInfo(name="root2",age=34,ut_id=2),
    models.UserInfo(name="root3",age=34,ut_id=3),
    models.UserInfo(name="root4",age=34,ut_id=4),
    models.UserInfo(name="root5",age=34,ut_id=5),
    models.UserInfo(name="root6",age=34,ut_id=6),
    models.UserInfo(name="root7",age=34,ut_id=7),
]
models.UserInfo.objects.bulk_create(info)
删除
Test.objects.filter(name__contains=''jack'').delete()

Test.objects.filter(name__contains=''apollo1'').update(name=''Jack'')

单表查询


models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值
models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
models.Tb1.objects.filter(name__contains="ven")  # 获取name字段包含"ven"的
models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
models.Tb1.objects.filter(id__range=[1, 3])      # id范围是1到3的,等价于SQL的bettwen and
类似的还有:startswith,istartswith, endswith, iendswith 
date字段还可以:
models.Class.objects.filter(first_day__year=2017)

多表查询(外键查询)

1. 正向查询(通过关联的字段ut,直接使用点语法获取另外一张表的字段数据)
objs = models.UserInfo.objects.filter(ut_id__gt=2,ut__title="正常员工")
print(objs)
for i in objs:
 print(f"id:{i.id} {i.name} {i.age}  {i.ut.title}")

正向查询

第一种:按对象查找

语法

对象。关联字段。字段

book_obj = models.Book.objects.first()  # 第一本书对象
print(book_obj.publisher)  # 得到这本书关联的出版社对象
print(book_obj.publisher.name)  # 得到出版社对象的名称

第二种:按照字段查找

语法

关联字段__字段

print(models.Book.objects.values_list("publisher__name"))

反向查询

第一种:按照对象查找

语法

<strong style=color:red> 对象。表名_set</strong>

publisher_obj = models.Publisher.objects.first()  # 找到第一个出版社对象
books = publisher_obj.book_set.all()  # 找到第一个出版社出版的所有书
titles = books.values_list("title")  # 找到第一个出版社出版的所有书的书名

第二种:按照字段查找

语法

<strong style=color:red> 表名__字段 </strong>

titles = models.Publisher.objects.values_list("book__title")

egg(14)--router进阶路由的几种写法、路由重定向、路由分组(路由映射

egg(14)--router进阶路由的几种写法、路由重定向、路由分组(路由映射

router的几种写法

router.verb(''path-match'', app.controller.action);
router.verb(''router-name'', ''path-match'', app.controller.action);
router.verb(''path-match'', middleware1, ..., middlewareN, app.controller.action);
router.verb(''router-name'', ''path-match'', middleware1, ..., middlewareN, app.controller.action);
  router.get(''/'', controller.home.index);
  router.get(''/'', auth1,auth2,controller.home.index);
  router.get(''index'',''/'', controller.home.index);
  router.get(''index'',''/'', auth1,auth2,controller.home.index);

重定向

目录结构

clipboard.png

路由内部重定向

controller/news.js
  async index() {
    this.ctx.status = 302;
    this.ctx.redirect(''/shop'')
  }

路由外部重定向

router.js
router.redirect(''/news'', ''/shop'',302);

路由分级(路由映射)

目录结构

clipboard.png

分路由

router/admin.js
module.exports = app => {
  const { router, controller } = app;
  router.get(''/admin/article'',controller.admin.article.index);
  router.get(''/admin/user'',controller.admin.user.index);
};
router/api.js
module.exports = app => {
  const { router, controller } = app;
    router.get(''/api/article'', controller.api.article.index);
  router.get(''/api/user'', controller.api.user.index);
};
router/index.js
module.exports = app => {
  const { router, controller } = app;
  router.get(''/'', controller.home.index);
  router.redirect(''/news'', ''/shop'',302);
  router.get(''/shop'', controller.shop.index);
};

总路由

router.js
module.exports = app => {

  require(''./router/admin'')(app)
  require(''./router/api'')(app)
  require(''./router/index'')(app)
};

Gin框架之路由分组和路由嵌套

Gin框架之路由分组和路由嵌套

路由组也可以嵌套,但是需要注意的是当进行嵌套时下一层的需要调用Group方法(设置路由前缀)是需要用上一层的进行调用:

shopGroup := userGroup.Group("/shop")

代码:

 1 import (
 2     "github.com/gin-gonic/gin"
 3     "net/http"
 4 )
 5 
 6 func main() {
 7     r := gin.Default()
    //设置路由前缀 调用Group方法
8 userGroup := r.Group("/user") 9 { 10 userGroup.GET("/index", func(c *gin.Context) { 11 c.JSON(http.StatusOK, gin.H{ 12 "message": "user/index", 13 }) 14 }) 15 userGroup.GET("/login", func(c *gin.Context) { 16 c.JSON(http.StatusOK, gin.H{ 17 "message": "user/login", 18 }) 19 }) 20 shopGroup := userGroup.Group("/shop") 21 { 22 shopGroup.GET("/index", func(c *gin.Context) { 23 c.JSON(http.StatusOK, gin.H{ 24 "message": "/user/shop/index", 25 }) 26 }) 27 } 28 } 29 r.Run() 30 }

 

运行结果:

路由分组:

 

路由组的嵌套运行结果:

 

 

Laravel 4 初级教程之视图、命名空间、路由,laravel初级教程

Laravel 4 初级教程之视图、命名空间、路由,laravel初级教程

Laravel 4 初级教程之视图、命名空间、路由,laravel初级教程

1. 视图分离与嵌套

在 learnlaravel 文件夹下运行命令:

php artisan generate:view admin._layouts.default
登录后复制

这时候generator插件帮我们创建了app/views/admin/_layouts/default.blade.php 文件,将内容修改为:

<br><br><br>  <meta charset="utf-8"><br>  <title>Learn Laravel 4</title><br>  @include(''admin._partials.assets'')<br><br><br><div>
<br>  <div>
<br>  <div>
<br>    <div>
<br>      <ahref="%7B%7B%20URL::route(''admin.pages.index'')%20%7D%7D">Learn Laravel 4</a><br>      @include(''admin._partials.navigation'')<br>    </div>
<br>  </div>
<br>
</div>
<br><hr>
<br>  @yield(''main'')<br>
</div><br><br>
登录后复制

这就是视图文件,MVC中的V。视图需要仔细讲一下。

views文件夹为视图文件夹,视图文件夹可以嵌套,就像我上面一样创建了admin/_layout嵌套文件夹,在里面创建了一个叫default.blade.php的文件,那么以后我们在Laravel内任何地方要用到这个视图的时候,他就叫admin._layouts.default。

我们看到,上面代码的第七行是“@include(''admin._partials.assets'')”,根据上面我们刚刚了解的知识,这表示载入了另外一个文件。blade是Laravel的模板引擎,此处的 @include 表示直接把那个文件的所有代码带入进来放到这里,变成当前视图的一部分。

注意看第25行“@yield(''main'')”,这表示什么呢?这个有点复杂,我们稍后再讲。

2. 权限验证

Laravel支持标准HTTP认证,但是在此处我们需要构建blog系统,所以我们将编写完善的管理员登陆系统,从页面登录。

用命令行创建app/views/admin/auth/login.blade.php文件,代码如下:

@extends(''admin._layouts.default'')<br>@section(''main'')<br>  <div id="login">
<br>    {{ Form::open() }}<br>      @if ($errors-&gt;has(''login''))<br>        <div>{{ $errors-&gt;first(''login'', '':message'') }}</div>
<br>      @endif<br>      <div>
<br>        {{ Form::label(''email'', ''Email'') }}<br>        <div>
<br>          {{ Form::text(''email'') }}<br>        </div>
<br>      </div>
<br>      <div>
<br>        {{ Form::label(''password'', ''Password'') }}<br>        <div>
<br>          {{ Form::password(''password'') }}<br>        </div>
<br>      </div>
<br>      <div>
<br>        {{ Form::submit(''Login'', array(''class'' =&gt; ''btn btn-inverse btn-login'')) }}<br>      </div>
<br>    {{ Form::close() }}<br>  </div><br>@stop
登录后复制

大家应该注意到了前两行:

@extends(''admin._layouts.default'')@section(''main'')
登录后复制

这代表什么?实际上,以后我们会了解到,在controller中调用view的时候,调用的只是这个login.blade.php文件,第一行表示,此视图是admin._layouts.default的子视图,这时blade引擎会把这个视图也载入进来,怎么组装呢?这时候下面那个@section(''main'')就该出场了,被它包裹的代码将会直接放到admin._layouts.default中的@yield(''main'')中。section和yield可以任意搭配,只要两个视图之间有调用关系,他们就可以这样用,非常灵活。

写到这里大家可能有个疑问,为什么示例代码里空行那么多?这一点就是个人经验了。blade引擎的所有标签都会在视图编译时用正则处理,引擎本身有一个问题,算不上bug,就是换行符会被处理掉,导致前后行和这一行都紧紧地挤在一起,在前端浏览器中“查看源代码”时,比较不清晰,前后加上空行可以解决这个问题。当然这可能是一个自动的“压缩”特性,不再深入讨论。

增加控制器文件app/controllers/admin/AuthController.php,这时候有人就说了,这我知道,哈哈,运行

“php artisan generate:controller admin.AuthController”

这个想法是对的,但你运行一下试试?会直接在app/controllers目录下创建一个“admin.AuthController.php”文件,有人又说,那我用“admin/AuthController”总行了吧,你试一下?也不行。所以我们要先在app/controllers 下手动创建 admin 文件夹,这时候,再命令行输入:

php artisan generate:controller admin/AuthController
登录后复制

这样就可以了。接下来改写AuthController.php 的内容为:

namespace App\Controllers\Admin;<br>use Auth, BaseController, Form, Input, Redirect, Sentry, View;<br>class AuthController extends BaseController {<br>  /**<br>   * 显示登录页面<br>   * @return View<br>   */<br>  public function getLogin()<br>  {<br>    return View::make(''admin.auth.login'');<br>  }<br>  /**<br>   * POST 登录验证<br>   * @return Redirect<br>   */<br>  public function postLogin()<br>  {<br>    $credentials = array(<br>      ''email''    =&gt; Input::get(''email''),<br>      ''password'' =&gt; Input::get(''password'')<br>    );<br>    try<br>    {<br>      $user = Sentry::authenticate($credentials, false);<br>      if ($user)<br>      {<br>        return Redirect::route(''admin.pages.index'');<br>      }<br>    }<br>    catch(\Exception $e)<br>    {<br>      return Redirect::route(''admin.login'')-&gt;withErrors(array(''login'' =&gt; $e-&gt;getMessage()));<br>    }<br>  }<br>  /**<br>   * 注销<br>   * @return Redirect<br>   */<br>  public function getLogout()<br>  {<br>    Sentry::logout();<br>    return Redirect::route(''admin.login'');<br>  }<br>}
登录后复制

这就是我们登录、注销的控制器,MVC中的C。接下来我将讲解命名空间,这是Laravel的基础,或者说是composer的基础,是整个Laravel教程中的重点、难点,希望大家锱铢必较,任何不懂都不要放过。可以到phphub论坛或者golaravel论坛相应帖子下面提问,或者直接发帖提问。

我们首先观察这个文件的位置,它位于 app/controllers/admin 目录下,这有什么不同呢?在其他框架如 CI 中,子文件夹直接加上文件夹名就可以直接调用到了,虽然最多只能有一层。而Laravel没有这么简单,涉及到了PHP的命名空间。

1. composer 支持 PSR-0 及 PSR-4 标准,标准规定 PHP 包以命名空间为区分,向外提供服务,所有暴露出来的类都应该在 \作者名\包名 命名空间下,例如 \lui\MFFC\Mail 类。这样,哪怕是名称一样的包只要是不同作者也可以在https://packagist.org/上共存,供大家使用。

2. 命名空间可以类比成 Linux 系统中的 目录,在任何目录下都可以直接使用文件名打开当前目录下的所有文件和可执行程序,如果需要打开其他目录下的文件,就需要使用绝对路径或者相对路径。

3. 大家可能在许多其他教程中见到过controller头部没有 namesapce 申明,更没有那一堆的 use xxx,像这个文件https://github.com/cecoo/laravel4demo/blob/master/app/controllers /BlogController.php。这个文件在第8行直接使用了 Blog 这个类,这是为什么呢?

因为他们都已经在 learnlaravel 这个 composer 应用的配置文件中声明为自动加载了,而他们没有在顶部声明他们所在的命名空间,这样就会被自动加为顶级命名空间。这个配置文件是 composer.json,对象配置项为autoload 下的classmap 项。这个声明会让 Composer 在生成自动载入文件的时候,自动扫描该文件下所有的类以及所有子文件夹中的类,只要没有声明特定的命名空间,将会被自动加载为顶级空间。【之前表述有误,特此更正!】

关于命名空间更多详情,可以参考 【PHP 命名空间 入门】。

OK,到目前为止我们的MVC三元素已经集齐了,那接下来该做什么了呢?配置路由。这里的路由并不是家里用的无线路由 :-D,而是 用户请求的URL到控制器某个方法的转换,function是PHP中代码段的最小单位,所以用户请求的一个路径,如 http://ooxx.com/fuck/me ,这条URL打给路由之后,路由就会去解析,应该调用哪个function,最终返回结果给用户。

Laravel的路由采用闭包的方式返回结果,在app/routes.php 中增加下列内容:

Route::get(''admin/logout'', array(''as'' =&gt; ''admin.logout'', ''uses'' =&gt; ''App\Controllers\Admin\AuthController@getLogout''));<br>Route::get(''admin/login'', array(''as'' =&gt; ''admin.login'', ''uses'' =&gt; ''App\Controllers\Admin\AuthController@getLogin''));<br>Route::post(''admin/login'', array(''as'' =&gt; ''admin.login.post'', ''uses'' =&gt; ''App\Controllers\Admin\AuthController@postLogin''));<br>Route::group(array(''prefix'' =&gt; ''admin'', ''before'' =&gt; ''auth.admin''), function()<br>{<br>    Route::any(''/'', ''App\Controllers\Admin\PagesController@index'');<br>    Route::resource(''articles'', ''App\Controllers\Admin\ArticlesController'');<br>    Route::resource(''pages'', ''App\Controllers\Admin\PagesController'');<br>});
登录后复制

前三条的意思是hold住两个get请求和一个post请求,下面是一个路由组,规定了一个前缀admin,增加了一个过滤器,auth.admin,内部有一个能同时适应get和post请求的‘/''路径,其完整路径是 http://ooxx.com/admin/。剩下的两个资源控制器本质上只是一种简写,URL和控制器类中的方法名的对应表见 资源控制器。

上面说的那个过滤器 auth.admin,是Laravel提供的一个请求过滤器,这个文件就在路由文件的旁边,app/filters.php,在文件末尾增加:

Route::filter(''auth.admin'', function()<br>{<br> if ( ! Sentry::check()) {<br>  return Redirect::route(''admin.login'');<br> }<br>});
登录后复制

这样我们的权限验证就完成了。上面的代码意思是,在进入这个路由组中的任何一条路由之前,会先过一遍 auth.admin这个filter,这个filter会调用Sentry::check(),如果为false,将会进入if代码块,将用户的请求跳转到 命名路由‘admin.login'',命名路由文档。从这个命名路由的名称大家也能看出来,就是跟访客说:傻逼,干啥呢,登录去~

这里的“命名路由”功能是为了模仿 Ruby On Rails 的 “link_to”到对象 的路由绑定功能,无奈PHP上传即部署无守护进程的特性,使得我们没法维护一个全量代码的路由表,没法像Rails那样实现 资源路由-资源对象-路由调用 三者绑定的功能,只能搞出一个半成品命名路由,人为地解决了当调整 /people 到 /human 时,要求名称改变而功能不变,同时要求代码自适应的需求。

这时候,我们就可以尝试访问我们的项目了。推荐配置Apache将一个端口指向learnlaravel这个项目的public目录下,即项目通过 http://127.0.0.1:8080 这样的地址访问,十分不建议从子文件夹访问。如果你不会,可以运行

php artisan serve
登录后复制

启动PHP5.4的内建HTTP服务器。地址将会是http://localhost:8000,注意此处 127.0.0.1 不可以访问。

下面,我们在浏览器中访问 /admin,注意URL会自动跳转到 /admin/login,这说明我们的filter起作用了,但你可能得到以下页面


这说明代码出错了。接下来我们修改 app/config/app.php 第一项为:

''debug'' =&gt; true,
登录后复制

刷新页面,错误提示出来了!有没有感觉Laravel4.2的错误提示很好看啊,确实不错,但我觉得没有4.1之前的好看 :-D。我得到了如下错误:


说“App\Controllers\Admin\AuthController”这个类未找到,这是为什么呢?这个文件明明有啊。

这就涉及到了另一个问题,Laravel中的autoload问题。Laravel基于命名空间,它只会自动加载所有顶级命名空间的类,就是说我们新增的这个控制器类不是在顶级命名空间下,所以就需要告诉Laravel,我这个类是存在的,怎么告诉它呢?运行

composer dump-autoload
登录后复制

可以了,刷新页面,他告诉我

View [admin._partials.assets] not found.

这个确实是,我们还没建立这个文件呢。建立一个空文件即可,如果是用generator建的话,别忘了把里面默认的内容删掉哦。再刷新页面,如果还有问题,我相信这个问题你可以自己解决。

OK,一个丑的一逼的页面出现了,为什么它这么丑?(鸽子为什么这么大?)因为我们没有引入任何css和js文件,甚至连导航栏的html都不完整。这不要紧,来,按照我github上的代码,自己复制到相应文件中吧。另外,非常重要的一点,把我的项目中的public文件下的 js 和 css 两个文件夹完全复制到你们的public文件夹中。

再刷新,如果你看到以下页面,说明你成功了!

3. 尝试登录

用seed新增一名管理员,顺便新增一个管理员组。新建app/database/seeds/SentrySeeder.php,内容为:

class SentrySeeder extends Seeder {<br>  public function run()<br>  {<br>    DB::table(''users'')-&gt;delete();<br>    DB::table(''groups'')-&gt;delete();<br>    DB::table(''users_groups'')-&gt;delete();<br>    Sentry::getUserProvider()-&gt;create(array(<br>      ''email''      =&gt; ''oo@xx.com'',<br>      ''password''   =&gt; "ooxx",<br>      ''first_name'' =&gt; ''OO'',<br>      ''last_name''  =&gt; ''XX'',<br>      ''activated''  =&gt; 1,<br>    ));<br>    Sentry::getGroupProvider()-&gt;create(array(<br>      ''name''        =&gt; ''Admin'',<br>      ''permissions'' =&gt; [''admin'' =&gt; 1],<br>    ));<br>    // 将用户加入用户组<br>    $adminUser  = Sentry::getUserProvider()-&gt;findByLogin(''oo@xx.com'');<br>    $adminGroup = Sentry::getGroupProvider()-&gt;findByName(''Admin'');<br>    $adminUser-&gt;addGroup($adminGroup);<br>  }<br>}
登录后复制

给app/database/seeds/DatabaseSeeder.php 新增一行:

$this-&gt;call(''SentrySeeder'');
登录后复制

然后运行:

php artisan db:seed
登录后复制

成功以后,进数据库就会发现,users、groups、users_groups表均新增了一行。但是,articles和pages表也分别新增了10行,对,seed就是这么蠢萌^_^

让我们来尝试登录!如果你得到:

Class App\Controllers\Admin\PagesController does not exist

这说明你成功了!

什是Laravel?

它可以让你从面条一样杂乱的代码中解脱出来;它可以帮你构建一个完美的网络APP,而且每行代码都可以简洁、富于表达力。1、Bundle是Laravel的扩展包组织形式或称呼。Laravel的扩展包仓库已经相当成熟了,可以很容易的帮你把扩展包(bundle)安装到你的应用中。你可以选择下载一个扩展包(bundle)然后拷贝到bundles目录,或者通过命令行工具“Artisan”自动安装。2、在Laravel中已经具有了一套高级的PHP ActiveRecord实现 -- Eloquent ORM。它能方便的将“约束(constraints)”应用到关系的双方,这样你就具有了对数据的完全控制,而且享受到ActiveRecord的所有便利。Eloquent原生支持Fluent中查询构造器(query-builder)的所有方法。3、应用逻辑(Application Logic)可以在控制器(controllers)中实现,也可以直接集成到路由(route)声明中,并且语法和Sinatra框架类似。Laravel的设计理念是:给开发者以最大的灵活性,既能创建非常小的网站也能构建大型的企业应用。4、反向路由(Reverse Routing)赋予你通过路由(routes)名称创建链接(URI)的能力。只需使用路由名称(route name),Laravel就会自动帮你创建正确的URI。这样你就可以随时改变你的路由(routes),Laravel会帮你自动更新所有相关的链接。5、Restful控制器(Restful Controllers)是一项区分GET和POST请求逻辑的可选方式。比如在一个用户登陆逻辑中,你声明了一个get_login()的动作(action)来处理获取登陆页面的服务;同时也声明了一个post_login()动作(action)来校验表单POST过来的数据,并且在验证之后,做出重新转向(redirect)到登陆页面还是转向控制台的决定。6、自动加载类(Class Auto-loading)简化了类(class)的加载工作,以后就可以不用去维护自动加载配置表和非必须的组件加载工作了。当你想加载任何库(library)或模型(model)时,立即使用就行了,Laravel会自动帮你加载需要的文件。7、视图组装器(View Composers)本质上就是一段代码,这段代码在视图(View)加载时会自动执行。最好的例子就是博客中的侧边随机文章推荐,“视图组装器”中包含了加载随机文章推荐的逻辑,这样,你只需要加载内容区域的视图(view)就行了,其它的事情Laravel会帮你自动完成。8、反向控制容器(IoC container)提供了生成新对象、随时实例化对象、访问单例(singleton)对象的便捷方式。反向控制(IoC)意味着你几乎不需要特意去加载外部的库(libraries),就可以在代码中的任意位置访问这些对象,并且不需要忍受繁杂、冗余的代码结构。9、迁移(Migrations)就像是版本控制(version control)工具,不过,它管理的是数据库范式,并且直接集成在了Laravel中。你可以使用“Artisan”命令行工具生成、执行“迁移”指令。当你的小组成员改变了数据库范式的时候,你就可以轻松的通过版本控制工具更新当前工程,然后执行“迁移指令即可,好了,你的数据库已经是最新的了!11、自动分页(Automatic Pagination)功能避免了在你的业务逻辑中混入大量无关分页配置代码。方便的是不需要记住当前页......余下全文>>
 

什是Laravel?

它可以让你从面条一样杂乱的代码中解脱出来;它可以帮你构建一个完美的网络APP,而且每行代码都可以简洁、富于表达力。1、Bundle是Laravel的扩展包组织形式或称呼。Laravel的扩展包仓库已经相当成熟了,可以很容易的帮你把扩展包(bundle)安装到你的应用中。你可以选择下载一个扩展包(bundle)然后拷贝到bundles目录,或者通过命令行工具“Artisan”自动安装。2、在Laravel中已经具有了一套高级的PHP ActiveRecord实现 -- Eloquent ORM。它能方便的将“约束(constraints)”应用到关系的双方,这样你就具有了对数据的完全控制,而且享受到ActiveRecord的所有便利。Eloquent原生支持Fluent中查询构造器(query-builder)的所有方法。3、应用逻辑(Application Logic)可以在控制器(controllers)中实现,也可以直接集成到路由(route)声明中,并且语法和Sinatra框架类似。Laravel的设计理念是:给开发者以最大的灵活性,既能创建非常小的网站也能构建大型的企业应用。4、反向路由(Reverse Routing)赋予你通过路由(routes)名称创建链接(URI)的能力。只需使用路由名称(route name),Laravel就会自动帮你创建正确的URI。这样你就可以随时改变你的路由(routes),Laravel会帮你自动更新所有相关的链接。5、Restful控制器(Restful Controllers)是一项区分GET和POST请求逻辑的可选方式。比如在一个用户登陆逻辑中,你声明了一个get_login()的动作(action)来处理获取登陆页面的服务;同时也声明了一个post_login()动作(action)来校验表单POST过来的数据,并且在验证之后,做出重新转向(redirect)到登陆页面还是转向控制台的决定。6、自动加载类(Class Auto-loading)简化了类(class)的加载工作,以后就可以不用去维护自动加载配置表和非必须的组件加载工作了。当你想加载任何库(library)或模型(model)时,立即使用就行了,Laravel会自动帮你加载需要的文件。7、视图组装器(View Composers)本质上就是一段代码,这段代码在视图(View)加载时会自动执行。最好的例子就是博客中的侧边随机文章推荐,“视图组装器”中包含了加载随机文章推荐的逻辑,这样,你只需要加载内容区域的视图(view)就行了,其它的事情Laravel会帮你自动完成。8、反向控制容器(IoC container)提供了生成新对象、随时实例化对象、访问单例(singleton)对象的便捷方式。反向控制(IoC)意味着你几乎不需要特意去加载外部的库(libraries),就可以在代码中的任意位置访问这些对象,并且不需要忍受繁杂、冗余的代码结构。9、迁移(Migrations)就像是版本控制(version control)工具,不过,它管理的是数据库范式,并且直接集成在了Laravel中。你可以使用“Artisan”命令行工具生成、执行“迁移”指令。当你的小组成员改变了数据库范式的时候,你就可以轻松的通过版本控制工具更新当前工程,然后执行“迁移指令即可,好了,你的数据库已经是最新的了!11、自动分页(Automatic Pagination)功能避免了在你的业务逻辑中混入大量无关分页配置代码。方便的是不需要记住当前页......余下全文>>
 

今天关于laravel第四讲:路由命名及路由分组laravel路由规则的分享就到这里,希望大家有所收获,若想了解更多关于django 之路由分组,路由分发,FBV,CBV,ORM 框架、egg(14)--router进阶路由的几种写法、路由重定向、路由分组(路由映射、Gin框架之路由分组和路由嵌套、Laravel 4 初级教程之视图、命名空间、路由,laravel初级教程等相关知识,可以在本站进行查询。

本文标签: