laravel写后台

因为之前用element-admin感觉完全前后端分离在目前项目上并不是太适用所以想用laravel和vue写一个后台

开始想利用laravel原生的vue,折腾了半天感觉不是很理想

一是app.js太大,用网上的方法确实减小了很多不过感觉后面用vue和blade混写不是太方便,主要还是有点无从下手

其实后台如果纯用blade的话倒也没啥,就是section套进来呗,主要还是想用到vue

后台主要有以下几块

1.顶部(logo,顶部导航nav,顶部user下拉)

2.侧边栏(sidebar)

3.内容(content)

先纸上谈兵走一下吧

1.在layout文件引入公共的css和js

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script
        src="https://code.jquery.com/jquery-3.1.1.min.js"
        integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="
        crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script src="

//这里的js是后面sideber要用到的
<script>
    var sidebar = new Vue({
        el: '#sidebar',
        data: {
            menus: [],
            active: ''
        },
        methods: {
            toggleMenu: function(id){
                this.active = this.active == id ? '' : id;
            },
            setMenus: function(menus){
                this.menus = menus;
            },
            isCurrentUrl: function(url, key){
                var parser = document.createElement('a');
                parser.href = url;

                if(parser.pathname === window.location.pathname){
                    this.active = key ? key : this.active;
                    return true;
                }

                return false;
            }
        },
        created: function(){
            this.setMenus(JSON.parse('{!! Speedy::getMenus(true) !!}'));
        }
    });
</script>

2.相关位置引入sidebar和nav

@include('xxxxxx.sidebar')
@include('xxxxxx.nav')

sidebar代码

<div id="sidebar" class="sidebar">
    <div class="sidebar-brand">
        <a href="{{ url('admin') }}">{{ config('app.name') }}</a>
    </div>
    <div class="sidebar-body">
        <ul>
            <template v-for="(menu, key) in menus">
                <li class="first-menu-li">
                    <a v-bind:class="[isCurrentUrl(menu.url) ? 'active' : '', 'first-menu']" v-on:click="toggleMenu(key)" v-bind:id="'menu-' + key" v-bind:href="menu.url ? menu.url : 'javascript:;'">@{{ menu.display }}
                        <span v-if="menu.sub" class="glyphicon glyphicon-chevron-down" v-bind:class="{ 'menu-expand-indicator' : active == key }"></span>
                    </a>
                    <ul v-if="menu.sub" v-bind:id="'sub-menu-' + key" class="sub-menu" v-bind:style="{display: active == key ? 'block' : 'none'}">
                        <template v-for="sub in menu.sub">
                            <li class="second-menu-li"><a v-bind:class="[isCurrentUrl(sub.url, key) ? 'active' : '', 'first-menu']" v-bind:href="sub.url" v-bind:target="sub.target ? sub.target : ''">@{{ sub.display }}</a></li>
                        </template>
                    </ul>
                </li>
            </template>
        </ul>
    </div>
</div>

可以看到是通过layout在这里获取到的menus然后再sidevar里使用

image.png

其实我的理想后台是在顶部和侧部都会有导航,顶部的导航展示的是不同的模块,左侧是模块的内部导航,类似微擎的后台

image.png

那就用一个多层的menus先把顶部的检查is current然后再把下面2层对应的菜单从左侧循环出来就可以了,后面我会实践一下然后再更。

PHP的反射类ReflectionClass、ReflectionMethod使用实例

PHP5 具有完整的反射API,添加对类、接口、函数、方法和扩展进行反向工程的能力。

反射是什么?

它是指在PHP运行状态中,扩展分析PHP程序,导出或提取出关于类、方法、属性、参数等的详细信息,包括注释。这种动态获取的信息以及动态调用对象的方法的功能称为反射API。反射是操纵面向对象范型中元模型的API,其功能十分强大,可帮助我们构建复杂,可扩展的应用。

其用途如:自动加载插件,自动生成文档,甚至可用来扩充PHP语言。

PHP反射api由若干类组成,可帮助我们用来访问程序的元数据或者同相关的注释交互。借助反射我们可以获取诸如类实现了那些方法,创建一个类的实例(不同于用new创建),调用一个方法(也不同于常规调用),传递参数,动态调用类的静态方法。

反射api是PHP内建的OOP技术扩展,包括一些类,异常和接口,综合使用他们可用来帮助我们分析其它类,接口,方法,属性,方法和扩展。这些OOP扩展被称为反射。

平常我们用的比较多的是 ReflectionClass类 和 ReflectionMethod类,例如:

<?php
class Person {
 
 /**
  * For the sake of demonstration, we"re setting this private
  */
 private $_allowDynamicAttributes = false;
 /**
  * type=primary_autoincrement
  */
 protected $id = 0;
 /**
  * type=varchar length=255 null
  */
 protected $name;
 /**
  * type=text null
  */
 protected $biography;
 public function getId() {
  return $this->id;
 }
 public function setId($v) {
  $this->id = $v;
 }
 public function getName() {
  return $this->name;
 }
 public function setName($v) {
  $this->name = $v;
 }
 public function getBiography() {
  return $this->biography;
 }
 public function setBiography($v) {
  $this->biography = $v;
 }
}

一、通过ReflectionClass,我们可以得到Person类的以下信息:

1.常量 Contants

2.属性 Property Names

3.方法 Method Names静态

4.属性 Static Properties

5.命名空间 Namespace

6.Person类是否为final或者abstract

7.Person类是否有某个方法

接下来反射它,只要把类名"Person"传递给ReflectionClass就可以了:

$class = new ReflectionClass('Person'); // 建立 Person这个类的反射类  
$instance  = $class->newInstanceArgs($args); // 相当于实例化Person 类

 

1)获取属性(Properties):

$properties = $class->getProperties();
foreach ($properties as $property) {
 echo $property->getName() . "\n";
}
// 输出:
// _allowDynamicAttributes
// id
// name
// biography

默认情况下,ReflectionClass会获取到所有的属性,private 和 protected的也可以。如果只想获取到private属性,就要额外传个参数:

$private_properties = $class->getProperties(ReflectionProperty::IS_PRIVATE);

 

可用参数列表:

ReflectionProperty::IS_STATIC
ReflectionProperty::IS_PUBLIC
ReflectionProperty::IS_PROTECTED
ReflectionProperty::IS_PRIVATE

通过$property->getName()可以得到属性名。

2)获取注释:

通过getDocComment可以得到写给property的注释。

foreach ($properties as $property) {
 if ($property->isProtected()) {
  $docblock = $property->getDocComment();
  preg_match('/ type\=([a-z_]*) /', $property->getDocComment(), $matches);
  echo $matches[1] . "\n";
 }
}
// Output:
// primary_autoincrement
// varchar
// text

3)获取类的方法

getMethods()       来获取到类的所有methods。

hasMethod(string)  是否存在某个方法

getMethod(string)  获取方法

 

 4)执行类的方法:

$instance->getName(); // 执行Person 里的方法getName
// 或者:
$method = $class->getmethod('getName'); // 获取Person 类中的getName方法
$method->invoke($instance);    // 执行getName 方法
// 或者:
$method = $class->getmethod('setName'); // 获取Person 类中的setName方法
$method->invokeArgs($instance, array('snsgou.com'));

 

二、通过ReflectionMethod,我们可以得到Person类的某个方法的信息:

1.是否“public”、“protected”、“private” 、“static”类型

2.方法的参数列表

3.方法的参数个数

4.反调用类的方法

// 执行detail方法
$method = new ReflectionMethod('Person', 'test');
 
if ($method->isPublic() && !$method->isStatic()) {
 echo 'Action is right';
}
echo $method->getNumberOfParameters(); // 参数个数
echo $method->getParameters(); // 参数对象数组

laravel alias getAlias

/**
 * Get the alias for an abstract if available.
 *
 * @param  string  $abstract
 * @return string
 *
 * @throws \LogicException
 */
public function getAlias($abstract)
{
    if (! isset($this->aliases[$abstract])) {
        return $abstract;
    }

    if ($this->aliases[$abstract] === $abstract) {
        throw new LogicException("[{$abstract}] is aliased to itself.");
    }

    return $this->getAlias($this->aliases[$abstract]);
}

laravel这个function 开始看的时候真的挺坑的

因为这个参数$abstract 命名实在是挺误导的

$aliases在赋值的时候是"Illuminate\Foundation\Application"=> 'app' 这种形式的

/**
 * Alias a type to a different name.
 *
 * @param  string  $abstract
 * @param  string  $alias
 * @return void
 */
public function alias($abstract, $alias)
{
    $this->aliases[$alias] = $abstract;

    $this->abstractAliases[$abstract][] = $alias;
}

在function alias里app是$abstract, Illuminate\Foundation\Application是$alias

而在getAlias里参数是$abstract就很误导

getAlias传入的$abstract其实是“Illuminate\Foundation\Application”

如果没有定义值就返回自己

如果定了了就返回定义值

这样理解要方便一些

PHP的反射类ReflectionClass、ReflectionMethod使用实例

PHP5 具有完整的反射API,添加对类、接口、函数、方法和扩展进行反向工程的能力。

反射是什么?

它是指在PHP运行状态中,扩展分析PHP程序,导出或提取出关于类、方法、属性、参数等的详细信息,包括注释。这种动态获取的信息以及动态调用对象的方法的功能称为反射API。反射是操纵面向对象范型中元模型的API,其功能十分强大,可帮助我们构建复杂,可扩展的应用。

其用途如:自动加载插件,自动生成文档,甚至可用来扩充PHP语言。

PHP反射api由若干类组成,可帮助我们用来访问程序的元数据或者同相关的注释交互。借助反射我们可以获取诸如类实现了那些方法,创建一个类的实例(不同于用new创建),调用一个方法(也不同于常规调用),传递参数,动态调用类的静态方法。

反射api是PHP内建的OOP技术扩展,包括一些类,异常和接口,综合使用他们可用来帮助我们分析其它类,接口,方法,属性,方法和扩展。这些OOP扩展被称为反射。

平常我们用的比较多的是 ReflectionClass类 和 ReflectionMethod类,例如:

<?php
class Person {
 

 /**
  * For the sake of demonstration, we"re setting this private
  */
 private $_allowDynamicAttributes = false;

 /**
  * type=primary_autoincrement
  */
 protected $id = 0;

 /**
  * type=varchar length=255 null
  */
 protected $name;

 /**
  * type=text null
  */
 protected $biography;

 public function getId() {
  return $this->id;
 }

 public function setId($v) {
  $this->id = $v;
 }

 public function getName() {
  return $this->name;
 }

 public function setName($v) {
  $this->name = $v;
 }

 public function getBiography() {
  return $this->biography;
 }

 public function setBiography($v) {
  $this->biography = $v;
 }
}

一、通过ReflectionClass,我们可以得到Person类的以下信息:

1.常量 Contants

2.属性 Property Names

3.方法 Method Names静态

4.属性 Static Properties

5.命名空间 Namespace

6.Person类是否为final或者abstract

7.Person类是否有某个方法

接下来反射它,只要把类名"Person"传递给ReflectionClass就可以了:

$class = new ReflectionClass('Person'); // 建立 Person这个类的反射类  
$instance  = $class->newInstanceArgs($args); // 相当于实例化Person 类

1)获取属性(Properties):

代码如下:

$properties = $class->getProperties();
foreach ($properties as $property) {
 echo $property->getName() . "\n";
}
// 输出:
// _allowDynamicAttributes
// id
// name
// biography

默认情况下,ReflectionClass会获取到所有的属性,private 和 protected的也可以。如果只想获取到private属性,就要额外传个参数:

代码如下:

$private_properties = $class->getProperties(ReflectionProperty::IS_PRIVATE);

可用参数列表:

代码如下:

ReflectionProperty::IS_STATIC
ReflectionProperty::IS_PUBLIC
ReflectionProperty::IS_PROTECTED
ReflectionProperty::IS_PRIVATE

通过$property->getName()可以得到属性名。

2)获取注释:

通过getDocComment可以得到写给property的注释。

代码如下:

foreach ($properties as $property) {
 if ($property->isProtected()) {
  $docblock = $property->getDocComment();
  preg_match('/ type\=([a-z_]*) /', $property->getDocComment(), $matches);
  echo $matches[1] . "\n";
 }
}
// Output:
// primary_autoincrement
// varchar
// text

3)获取类的方法

代码如下:

getMethods()       来获取到类的所有methods。
hasMethod(string)  是否存在某个方法
getMethod(string)  获取方法

4)执行类的方法:

代码如下:

$instance->getName(); // 执行Person 里的方法getName
// 或者:
$method = $class->getmethod('getName'); // 获取Person 类中的getName方法
$method->invoke($instance);    // 执行getName 方法
// 或者:
$method = $class->getmethod('setName'); // 获取Person 类中的setName方法
$method->invokeArgs($instance, array('snsgou.com'));

二、通过ReflectionMethod,我们可以得到Person类的某个方法的信息:

1.是否“public”、“protected”、“private” 、“static”类型

2.方法的参数列表

3.方法的参数个数

4.反调用类的方法

代码如下:

// 执行detail方法

$method = new ReflectionMethod('Person', 'test');

 

if ($method->isPublic() && !$method->isStatic()) {

 echo 'Action is right';

}

echo $method->getNumberOfParameters(); // 参数个数

echo $method->getParameters(); // 参数对象数组

PHP预定义接口之 ArrayAccess

先说 ArrayAccess 吧!ArrayAccess 的作用是使得你的对象可以像数组一样可以被访问。应该说 ArrayAccess 在PHP5中才开始有的,PHP5中加入了很多新的特性,当然也使类的重载也加强了,PHP5 中添加了一系列接口,这些接口和实现的 Class 统称为 SPL。

ArrayAccess 这个接口定义了4个必须要实现的方法:

{
   abstract public offsetExists ($offset)  //检查偏移位置是否存在
   abstract public offsetGet ($offset)     //获取一个偏移位置的值
   abstract public void offsetSet ($offset ,$value) //设置一个偏移位置的值
   abstract public void offsetUnset ($offset)       //复位一个偏移位置的值
}

所以我们要使用ArrayAccess这个接口,就要实现相应的方法,这几个方法不是随便写的,我们可以看一下 ArrayAccess 的原型:

/**
 * Interface to provide accessing objects as arrays.
 * @link http://php.net/manual/en/class.arrayaccess.php
 */
interface ArrayAccess {

    /**
     * (PHP 5 &gt;= 5.0.0)<br/>
     * Whether a offset exists
     * @link http://php.net/manual/en/arrayaccess.offsetexists.php
     * @param mixed $offset <p>
     * An offset to check for.
     * </p>
     * @return boolean true on success or false on failure.
     * </p>
     * <p>
     * The return value will be casted to boolean if non-boolean was returned.
     */
    public function offsetExists($offset);

    /**
     * (PHP 5 &gt;= 5.0.0)<br/>
     * Offset to retrieve
     * @link http://php.net/manual/en/arrayaccess.offsetget.php
     * @param mixed $offset <p>
     * The offset to retrieve.
     * </p>
     * @return mixed Can return all value types.
     */
    public function offsetGet($offset);

    /**
     * (PHP 5 &gt;= 5.0.0)<br/>
     * Offset to set
     * @link http://php.net/manual/en/arrayaccess.offsetset.php
     * @param mixed $offset <p>
     * The offset to assign the value to.
     * </p>
     * @param mixed $value <p>
     * The value to set.
     * </p>
     * @return void
     */
    public function offsetSet($offset, $value);

    /**
     * (PHP 5 &gt;= 5.0.0)<br/>
     * Offset to unset
     * @link http://php.net/manual/en/arrayaccess.offsetunset.php
     * @param mixed $offset <p>
     * The offset to unset.
     * </p>
     * @return void
     */
    public function offsetUnset($offset);
}

下面我们可以写一个例子,非常简单:

<?php
class Test implements ArrayAccess
{
    private $testData;

    public function offsetExists($key)
    {
        return isset($this->testData[$key]);
    }

    public function offsetSet($key, $value)
    {
        $this->testData[$key] = $value;
    }

    public function offsetGet($key)
    {
        return $this->testData[$key];
    }

    public function offsetUnset($key)
    {
        unset($this->testData[$key]);
    }
}

  $obj = new Test();

  //自动调用offsetSet方法
  $obj['data'] = 'data';

  //自动调用offsetExists
  if(isset($obj['data'])){
    echo 'has setting!';
  }
  //自动调用offsetGet
  var_dump($obj['data']);

  //自动调用offsetUnset
  unset($obj['data']);
  var_dump($test['data']);

  //输出:
  //has setting!
  //data  
  //null

php closure 的bind和bindTo

1.理解这两个方法,首先要明白闭包。

闭包的理解:就是匿名函数,也就是没有名字的函数

例如:

<?php
 
$a = function($args){
    echo "i haven't name";
    echo "=".$args;
};
$a(11);
?>

输出:i haven't name=11

2.这两个函数需要解决的问题。(我也不知道,这东西能解决啥问题,待我明白能解决的问题再补上吧)

例如:

<?php
class user{
private $money = 200;
public $level = 0;
public function beatMonster(){
echo "beat monster!";
}
}
//进入游戏之后新建一个角色xf
$xf = new user;
 
 
$uplevel = function(){
$this->level++;
};
 
 
$upmylevel = closure::bind($uplevel,$xf,'user');
 
 
echo $xf->level;
echo '<br/>';
$upmylevel();
echo $xf->level;
echo '<br/>';
?>

 

输出:01

说白了就是将一个匿名函数放在了一个实例中。

解释一下关于第二个和第三个参数:

<?php
/**  
 * 复制一个闭包,绑定指定的$this对象和类作用域。  
 *  
 * @author LeoKim
 */  
class Animal {  
    private static $cat = "cat";  
    private $dog = "dog";  
    public $pig = "pig";  
}  
  
/*  
 * 获取Animal类静态私有成员属性 
 */  
$cat = static function() {  
    return Animal::$cat;  
};  
  
/*  
 * 获取Animal实例私有成员属性 
 */  
$dog = function() {  
    return $this->dog;  
};  
  
/*  
 * 获取Animal实例公有成员属性 
 */  
$pig = function() {  
    return $this->pig;  
};  
  
$bindCat = Closure::bind($cat, null, new Animal());// 给闭包绑定了Animal实例的作用域,但未给闭包绑定$this对象  
$bindDog = Closure::bind($dog, new Animal(), 'Animal');// 给闭包绑定了Animal类的作用域,同时将Animal实例对象作为$this对象绑定给闭包  
$bindPig = Closure::bind($pig, new Animal());// 将Animal实例对象作为$this对象绑定给闭包,保留闭包原有作用域  
echo $bindCat(),'<br>';// 根据绑定规则,允许闭包通过作用域限定操作符获取Animal类静态私有成员属性  
echo $bindDog(),'<br>';// 根据绑定规则,允许闭包通过绑定的$this对象(Animal实例对象)获取Animal实例私有成员属性  
echo $bindPig(),'<br>';// 根据绑定规则,允许闭包通过绑定的$this对象获取Animal实例公有成员属性  
?>

输出:

cat

dog

pig

解释一下:

第二个参数:

官方原话:需要绑定到匿名函数的对象,或者 NULL 创建未绑定的闭包。

这是啥,完全懵逼啊。经过各种尝试。明白了,可以理解为,

你把这个匿名的方法是否放在一个实例中,如果放在实例中,

这个参数就是一个实例,如果不放在实例中,那就放null。

当你不放在实例中,也就是不存在$this。也就不能用$this

不过只有这一个参数,没有第三个,通过$this只能访问public 的参数

第三个参数:

官方原话:想要绑定给闭包的类作用域,或者 'static' 表示不改变。

如果传入一个对象,则使用这个对象的类型名。 

类作用域用来决定在闭包中 $this 对象的 私有、保护方法 的可见性。

这是啥意思,你问我,我也懵逼。不过你就记住,这个参数设置

实例或者是,类名例如:'Composer\Autoload\ClassLoader'

就能访问static ,私有的,保护的了

然后说下 bindTo,简单说下。

例如:

<?php
class user{
private $money = 200;
public $level = 0;
public function beatMonster(){
echo "beat monster!";
}
}
//进入游戏之后新建一个角色xf
$xf = new user;
 
$uplevel = function(){
$this->level++;
};
 
$upmylevel = $uplevel->bindTo($xf,'user');
echo $xf->level;
echo '<br/>';
$upmylevel();
echo $xf->level;
echo '<br/>';
 
?>

superagent post数据获取2次请求 & php如何接受AJAX POST跨域的request payload形式的参数

superagent 使用post的时候会有2次请求

一次请求的类型是OPTIONS

另一种是POST

开始的时候我如何都接受不到post过来的数据

后来仔细核对了浏览器里的信息发现传输数据的方式不是以前的form data而是request payload

然后就上网找如何处理request payload类型的数据

最终像下面这样解决

header('Access-Control-Allow-Origin: *');
        header('Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE');

        if($_SERVER['REQUEST_METHOD'] == 'OPTIONS'){
            header('HTTP/1.1 204 No Content');
            header('Server: Cowboy');
            header('Content-Length: 0');
            header('Connection: keep-alive');
            header('Vary: Access-Control-Request-Headers');
            header('Access-Control-Allow-Headers: content-type');
            header('Date: Fri, 19 Jan 2018 07:57:49 GMT');
            header('Via: 1.1 vegur');
        }else if($_SERVER['REQUEST_METHOD'] == 'POST'){
            $request_body = file_get_contents('php://input');
            $data = json_decode($request_body);

            echo json_encode($result);
        }

notadd 初始化所有modules

notadd\vendor\notadd\framework\src\Module\ModuleManager.php

function getModules

/**
 * Modules of list.
 *
 * @return \Illuminate\Support\Collection
 */
public function getModules()
{
    if ($this->modules->isEmpty()) {
        if ($this->files->isDirectory($this->getModulePath())) {
            collect($this->files->directories($this->getModulePath()))->each(function ($directory) {
                if ($this->files->exists($file = $directory . DIRECTORY_SEPARATOR . 'composer.json')) {
                    $package = new Collection(json_decode($this->files->get($file), true));
                    $identification = Arr::get($package, 'name');
                    $type = Arr::get($package, 'type');
                    if ($type == 'notadd-module' && $identification) {
                        $provider = '';
                        if ($entries = data_get($package, 'autoload.psr-4')) {
                            foreach ($entries as $namespace => $entry) {
                                $provider = $namespace . 'ModuleServiceProvider';
                            }
                        }
                        if ($this->files->exists($autoload = $directory . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php')) {
                            $this->files->requireOnce($autoload);
                        }
                        $authors = Arr::get($package, 'authors');
                        $description = Arr::get($package, 'description');
                        if (class_exists($provider)) {
                            $module = new Module($identification);
                            $module->setAuthor($authors);
                            $module->setDescription($description);
                            $module->setDirectory($directory);
                            $module->setEnabled($this->container->isInstalled() ? $this->container->make('setting')->get('module.' . $identification . '.enabled', false) : false);
                            $module->setInstalled($this->container->isInstalled() ? $this->container->make('setting')->get('module.' . $identification . '.installed', false) : false);
                            $module->setEntry($provider);
                            if (method_exists($provider, 'alias')) {
                                $module->setAlias(call_user_func([$provider, 'alias']));
                            } else {
                                $module->setAlias([$identification]);
                            }
                            method_exists($provider, 'description') && $module->setDescription(call_user_func([$provider, 'description']));
                            method_exists($provider, 'name') && $module->setName(call_user_func([$provider, 'name']));
                            method_exists($provider, 'script') && $module->setScript(call_user_func([$provider, 'script']));
                            method_exists($provider, 'stylesheet') && $module->setStylesheet(call_user_func([$provider, 'stylesheet']));
                            method_exists($provider, 'version') && $module->setVersion(call_user_func([$provider, 'version']));
                            $this->modules->put($identification, $module);
                        } else {
                            $this->unloaded->put($identification, [
                                'authors'        => $authors,
                                'description'    => $description,
                                'directory'      => $directory,
                                'identification' => $identification,
                                'provider'       => $provider,
                            ]);
                        }
                    }
                }
            });
        }
    }

    return $this->modules;
}

这个function 获取到所有的module

我想一定是系统初始化的时候初始化了每一个module 所以才能注册到module的route

notadd 查找/admin路由绑定的地方

一直想找notadd的后台时如何创建路由的,结果一直没有找到

今天总算是让我找到了

一下记录一下步骤

获取所有路由列表

php notadd route:list > D:route.txt

image.png

发现是在Notadd\Administration\Controllers\AdminController这个文件里定义的 

我打开notadd\modules\administration\src\ModuleServiceProvider.php

看到ModuleServiceProvider的boot function是这样的

/**
 * Boot service provider.
 *
 * @throws \Illuminate\Contracts\Container\BindingResolutionException
 */
public function boot()
{
    $administrator = new Administrator($this->app['events'], $this->app['router']);
    $administrator->registerPath('admin');
    $administrator->registerHandler(AdminController::class . '@handle');
    $this->administration->setAdministrator($administrator);
    $this->app->make(Dispatcher::class)->subscribe(CsrfTokenRegister::class);
    $this->app->make(Dispatcher::class)->subscribe(PermissionGroupRegister::class);
    $this->app->make(Dispatcher::class)->subscribe(PermissionModuleRegister::class);
    $this->app->make(Dispatcher::class)->subscribe(PermissionRegister::class);
    $this->app->make(Dispatcher::class)->subscribe(PermissionTypeRegister::class);
    $this->app->make(Dispatcher::class)->subscribe(RouteRegister::class);
    $this->loadTranslationsFrom(realpath(__DIR__ . '/../resources/translations'), 'administration');
    $this->loadViewsFrom(realpath(__DIR__ . '/../resources/views'), 'admin');
    $this->publishes([
        realpath(__DIR__ . '/../resources/mixes/administration/dist/assets/admin') => public_path('assets/admin'),
        realpath(__DIR__ . '/../resources/mixes/neditor')                          => public_path('assets/neditor'),
    ], 'public');
}

重点是这几行

image.png

我不知道registerPath和registerHandler是做什么用的,那么我向上追溯到了notadd\vendor\notadd\framework\src\Administration\Abstracts\Administrator.php

/**
 * Init administrator.
 *
 * @throws \InvalidArgumentException
 */
final public function init()
{
    if (is_null($this->path) || is_null($this->handler)) {
        throw new InvalidArgumentException('Handler or Path must be Setted!');
    }
    $this->router->group(['middleware' => 'web'], function () {
        $this->router->get($this->path, $this->handler);
    });
}

/**
 * Register administration handler.
 *
 * @param $handler
 */
public function registerHandler($handler)
{
    $this->handler = $handler;
}

/**
 * Register administration route path.
 *
 * @param string $path
 */
public function registerPath($path)
{
    $this->path = $path;
}

发现了这些代码,好吧 原来这个路由是在这里去绑定的······ 怪不得我开始怎么找也找不到呢

所以是吧/admin  绑定到了notadd\modules\administration\src\Controllers\AdminController.php 的 handle function

/**
 * Return index content.
 *
 * @param \Notadd\Foundation\Extension\ExtensionManager $extension
 * @param \Notadd\Foundation\Module\ModuleManager       $module
 *
 * @return \Illuminate\Contracts\View\View
 */
public function handle(ExtensionManager $extension, ModuleManager $module)
{
    $this->share('extensions', $extension->getEnabledExtensions());
    $this->share('modules', $module->getEnabledModules());
    $this->share('translations', json_encode($this->translator->fetch('zh-cn')));
    return $this->view('admin::layout');
}

所以在这些操作之前,一定有一个地方初始化了所有的module

我想找到这个地方

Laravel 事件

事件类通常被保存在 app/Events 目录下,而它们的处理程序则被保存在 app/Handlers/Events 目录下。

leokim\app\Events\LeokimTestEvent.php

<?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class LeokimTestEvent
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel('channel-name');
    }
}

1.创建事件

php artisan make:event LeokimTestEvent

2.创建事件handle

leokim\app\Handlers\Events\LeokimTestEventHandler.php

<?php
namespace App\Handlers\Events;
use App\Events\LeokimTestEvent;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldBeQueued;

class LeokimTestEventHandler{
    public function __construct()
    {
    }

    public function handle(LeokimTestEvent $event)
    {
        echo '<br>事件触发测试';
    }
}

3.在EventServiceProvider中注册

leokim\app\Providers\EventServiceProvider.php

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        'App\Events\Event' => [
            'App\Listeners\EventListener',
        ],
        'App\Events\LeokimTestEvent' => [
            'App\Handlers\Events\LeokimTestEventHandler',
        ],
    ];

    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();

        //
    }
}

4.在controller中触发

<?php

namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Events\LeokimTestEvent;

class LeokimController extends Controller
{
    protected $leo;

    function __construct($leo)
    {
        $this->leo = $leo;
    }

    function index(){
        echo '123';
        event(new LeokimTestEvent());
    }

    function test($id){
        return $this->leo.$id;
    }
}