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;
    }
}

计算得出非连续数字分段

<?php

$array = array(10010,10011,10012,10013,10015,10016,10026,10027,10028,10029);

$range = get_num_range($array);

print_r($range);

function get_num_range($arr){

    $range = array();

    $i = 1;

    $tmp_min = $tmp_max = '';

    foreach($arr as $no){

        //如果没有此range的最小值 第一个就是最小值

        if(empty($tmp_min)){

            $tmp_min = $no;

        }

        //下一个值不存在计算出最大值

        $next_no = $no+1;

        if(!in_array($next_no,$arr) && !empty($next_no)){

            $tmp_max = $no;

            $range[] = array($tmp_min, $tmp_max);

            $tmp_min = '';

        }

    }

    return $range;

}

?>

swoole 动态进程池

<?php
/**
 * Created by PhpStorm.
 * User: LeoKim
 * Date: 2017/5/13
 * Time: 9:10
 */

class BaseProcess{
    private $process;

    private $process_list = [];
    private $process_use = [];
    private $min_worker_num = 3;
    private $max_worker_num = 6;

    private $current_num;

    public function __construct()
    {
        $this->process = new swoole_process(array($this, 'run'), false, 2);
        $this->process->start();

        swoole_process::wait();
    }

    public function run($worker)
    {
        $this->current_num = $this->min_worker_num;

        //创建初始进程
        for($i=0; $i < $this->current_num; $i++){
            $process = new swoole_process(array($this, 'task_run'), false, 2);
            $pid = $process->start();

            echo $pid.': 我被初始创建了.'.date('H:i:s').PHP_EOL;
            $this->process_list[$pid] = $process;
            $this->process_use[$pid] = 0;
        }

        foreach($this->process_list as $process){
            //pipe管道被读操作的时候执行闭包的function?
            $this->bind_set_empty($process);
        }

        swoole_timer_tick(1000, function($timer_id){
            static $index=0;
            $index = $index+1;
            $flag = true;

            //我们在前面定义过 当pid对应的值为0的时候表示该进程现在空闲
            foreach($this->process_use as $pid => $used){
                if($used == 0){
                    $flag = false;
                    //我们要使用空闲的进程,把进程标记成工作状态
                    $this->process_use[$pid] = 1;
                    $this->process_list[$pid]->write($index." Hi 我开始工作了.");
                    break;
                }
            }

            //如果没有进程是空闲的, 那么检查进程是否超过最大值,没超过的话创建新的进程
            if($flag && $this->current_num < $this->max_worker_num)
            {
                $process = new swoole_process(array($this, 'task_run'), false, 2);
                $pid = $process->start();
                $this->process_list[$pid] = $process;
                $this->process_use[$pid] = 1 ;
                $this->process_list[$pid]->write($index." Hi 我是新来的,我开始工作了.");
                $this->current_num++;

                $this->bind_set_empty($process);
            }

            //执行n次退出
            if($index==20){
                foreach($this->process_list as $process){
                    foreach($this->process_list as $process){
                        $process->write("任务完毕 我退出了.");
                    }
                    swoole_timer_clear($timer_id);
                    $this->process->exit();
                }
            }
        });
    }

    //进程在创建的时候被执行
    public function task_run($worker)
    {
        //为每个进程绑定回调,当进程执行write的时候触发
        swoole_event_add($worker->pipe, function($pipe) use($worker){
            $data = $worker->read();
            var_dump($worker->pid.": ".$data.' -- '.date('H:i:s'));echo PHP_EOL;
            if($data == '任务完毕 我退出了.')
            {
                $worker->exit();
                exit;
            }

            sleep(5);

            //当worker进程执行write的时候会出发line:43的回调函数
            //把进程标记为空闲
            $worker->write($worker->pid);
        });
    }

    public function bind_set_empty($worker){
        swoole_event_add($worker->pipe, function($pipe) use($worker){
            $pid= $worker->read();
            echo $pid.' 报告,我处理完了之前的任务现在空下来了.'.date('H:i:s').PHP_EOL;
            $this->process_use[$pid] =  0;
        });
    }
}

new BaseProcess();

swoole 简单聊天室

服务端

<?php
/**
 * Created by PhpStorm.
 * User: LeoKim
 * Date: 2017/5/12
 * Time: 23:05
 */

class Server{
    private $serv;
    private $test;

    public function __construct()
    {
        $this->serv = new swoole_server("0.0.0.0", 9502);
        $this->serv->set(
            array(
                'worker_num' => 1,
            )
        );

        $this->serv->on('Start', array($this, 'onStart'));
        $this->serv->on('Connect', array($this, 'onConnect'));
        $this->serv->on('Receive', array($this, 'onReceive'));
        $this->serv->on('Close', array($this, 'onClose'));

        $this->serv->start();
    }

    public function onStart( $serv ) {
        echo "Start\n";
    }

    public function onConnect( $serv, $fd, $from_id ) {
        echo "Client {$fd} connect\n";
    }

    public function onClose( $serv, $fd, $from_id ) {
        echo "Client {$fd} close connection\n";
    }

    public function onReceive( swoole_server $serv, $fd, $from_id, $data){
        echo "Get Message From Client {$fd}:{$data}\n";
        foreach($serv->connections as $client){
            if($fd != $client)
            $serv->send($client, $data);
        }
    }
}

$server = new Server();

客户端

<?php
/**
 * Created by PhpStorm.
 * User: LeoKim
 * Date: 2017/5/12
 * Time: 23:13
 */

$socket = stream_socket_client("tcp://127.0.0.1:9502", $errno, $errstr, 30);

function OnRead()
{
    global $socket;
    $buffer = stream_socket_recvfrom($socket, 1024);
    if(!$buffer)
    {
        echo "Server clised\n";
    }
    echo "\nRECV: {$buffer}\n";
    fwrite(STDOUT, "Enter Msg:");
}

function onWrite()
{
    global $socket;
    echo "on Write\n";
}

function onInput()
{
    global $socket;
    $msg = trim(fgets(STDIN));

    if($msg == 'exit'){
        swoole_event_exit();
        exit();
    }

    swoole_event_write($socket, $msg);
    fwrite(STDOUT, "Enter Msg:");
}

swoole_event_add($socket, 'onRead', 'onWrite');

swoole_event_add(STDIN, 'onInput');

fwrite(STDOUT, "Enter Msg:");

image.png

image.png

image.png

laravel5集成angular2

这个问题我之前一直在思考

学习angular的过程中都是把angular视为一个完整的前端存在

也就是脱离了后端的独立存在

在代码里不去插入动态语言

在前端完成数据的存储,通信,绑定,修改

与后端可以用http协议交互,像app一样只做展示的前端操作

angular2通过ng server创建http服务

我想要把angular2结合laravel5一起使用

开始我觉得是不是angular2就像上面说的那样还是通过ng server创建服务

运行在4200端口 然后nginx反向代理到4200端口访问angular

然后angular通过http协议与laravel后端通信

google了之后发现使用angular2的开发模式(development mode)可以直接使用

而之前ng server只是单独为了让程序跑起来提供的一个服务

如今又laravel了 就可以不用创建那个服务 直接在这个上面跑

哎 还是基础不好思维有限 慢慢补吧

让我们开始吧!首先要安装基础laravel应用

image.png

我们需要获取angular2和typescript源码

在新创建的文件夹(larangular)中可以看到package.json文件

修改

{
  "private": true,
  "scripts": {
    "dev": "npm run development",
    "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch-poll": "npm run watch -- --watch-poll",
    "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
    "prod": "npm run production",
    "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
  },
  "devDependencies": {
    "axios": "^0.15.3",
    "bootstrap-sass": "^3.3.7",
    "cross-env": "^3.2.3",
    "jquery": "^3.1.1",
    "laravel-mix": "0.*",
    "lodash": "^4.17.4",
    "vue": "^2.1.10",
    "concurrently": "^1.0.0",
    "del": "^2.2.0",
    "gulp": "^3.8.8"
  },
  "dependencies": {
    "angular2": "2.0.0-beta.0",
    "bootstrap-sass": "^3.0.0",
    "elixir-typescript": "^1.1.2",
    "es6-promise": "^3.0.2",
    "es6-shim": "^0.33.3",
    "laravel-elixir": "^4.0.0",
    "reflect-metadata": "0.1.2",
    "rxjs": "5.0.0-beta.0",
    "systemjs": "0.19.6",
    "zone.js": "0.5.10"
  }
}

现在执行npm install,所需要的文件将被下载到node_modules文件夹

image.png

完成之后,我们要添加Typescript在laravel项目的resouce/assets目录

在这个文件夹里我们要创建2个文件app.component.ts 和 boot.ts

import {Component} from 'angular2/core';
 
@Component({
    selector: 'my-app',
    template: '<h1>My First Angular 2 App</h1>'
})
export class AppComponent { }
import {bootstrap}    from 'angular2/platform/browser'
import {AppComponent} from './app.component'
 
bootstrap(AppComponent);

下面我们需要编写一个简单的Elixir task来完成Typescript

在主文件夹中创建gulpfile.js

var elixir = require('laravel-elixir');
var elixirTypscript = require('elixir-typescript');

/*
 |--------------------------------------------------------------------------
 | Elixir Asset Management
 |--------------------------------------------------------------------------
 |
 | Elixir provides a clean, fluent API for defining some basic Gulp tasks
 | for your Laravel application. By default, we are compiling the Sass
 | file for our application, as well as publishing vendor resources.
 |
 */

elixir(function(mix) {
    mix.sass('app.scss');

    mix.copy('node_modules/angular2', 'public/angular2');
    mix.copy('node_modules/rxjs', 'public/rxjs');
    mix.copy('node_modules/systemjs', 'public/systemjs');
    mix.copy('node_modules/es6-promise', 'public/es6-promise');
    mix.copy('node_modules/es6-shim', 'public/es6-shim');
    mix.copy('node_modules/zone.js', 'public/zone.js');

    mix.typescript('app.js','public/','/**/*.ts',{
        "target": "ES5",
        "module": "system",
        "moduleResolution": "node",
        "sourceMap": true,
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "removeComments": false,
        "noImplicitAny": false,
    });

});

然后安装gulp

image.png

修改如下文件 node_modules/elixir_typescript/index.js 

new Task(pluginName, function () {
       var tsResult = gulp.src(assetPath + search)
           .pipe(ts(options, undefined, _laravelReporter.ElixirMessage()));
       return tsResult
           //  .pipe(concat(outputFileName))
             .pipe(gulp.dest(outputFolder));


   })

如果不修改会出现下面的错误

image.png

现在在程序根目录下执行gulp

image.png

全部执行完成

修改views

<!doctype html>
<html lang="{{ config('app.locale') }}">
    <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>Laravel</title>

        <!-- Fonts -->
        <link href="https://fonts.googleapis.com/css?family=Raleway:100,600" rel="stylesheet" type="text/css">

        <!-- Styles -->
        <style>
            html, body {
                background-color: #fff;
                color: #636b6f;
                font-family: 'Raleway', sans-serif;
                font-weight: 100;
                height: 100vh;
                margin: 0;
            }

            .full-height {
                height: 100vh;
            }

            .flex-center {
                align-items: center;
                display: flex;
                justify-content: center;
            }

            .position-ref {
                position: relative;
            }

            .top-right {
                position: absolute;
                right: 10px;
                top: 18px;
            }

            .content {
                text-align: center;
            }

            .title {
                font-size: 84px;
            }

            .links > a {
                color: #636b6f;
                padding: 0 25px;
                font-size: 12px;
                font-weight: 600;
                letter-spacing: .1rem;
                text-decoration: none;
                text-transform: uppercase;
            }

            .m-b-md {
                margin-bottom: 30px;
            }
        </style>

        <script src="es6-shim/es6-shim.min.js"></script>
        <script src="systemjs/dist/system-polyfills.js"></script>
         
        <script src="angular2/bundles/angular2-polyfills.js"></script>
        <script src="systemjs/dist/system.src.js"></script>
        <script src="rxjs/bundles/Rx.js"></script>
        <script src="angular2/bundles/angular2.dev.js"></script>

        <script>
            System.config({
              "defaultJSExtensions": true,
              packages: {
                app: {
                  format: 'register',
                  defaultExtension: 'js'
                }
              }
            });
         
         
            System.import('typescript/boot')
                  .then(null, console.error.bind(console));
          </script>
    </head>
    <body>
        <div class="flex-center position-ref full-height">
            @if (Route::has('login'))
                <div class="top-right links">
                    @if (Auth::check())
                        <a href="{{ url('/home') }}">Home</a>
                    @else
                        <a href="{{ url('/login') }}">Login</a>
                        <a href="{{ url('/register') }}">Register</a>
                    @endif
                </div>
            @endif

            <div>
                <div class="title m-b-md">
                    Laravel
                </div>
                <my-app>Loading...</my-app>

                <div>
                    <a href="https://laravel.com/docs">Documentation</a>
                    <a href="https://laracasts.com">Laracasts</a>
                    <a href="https://laravel-news.com">News</a>
                    <a href="https://forge.laravel.com">Forge</a>
                    <a href="https://github.com/laravel/laravel">GitHub</a>
                </div>
            </div>
        </div>
    </body>
</html>

成功了!!!

image.png

我把它放在了这里

https://git.oschina.net/iamleokim/larangular.git