在Laravel 5中创建一个新的ServiceProvider / Facade作为包

时间:2015-02-22 20:10:34

标签: php laravel package composer-php laravel-5

简介

我以前从未使用过框架(Zend,CakePHP等),最后决定坐下来学习一个。我从Laravel开始,因为代码看起来很漂亮,而且与我试图安装的其他框架不同," Hello,World!"示例在第一次尝试时起作用。

目标

目前,我希望我的应用程序能够做一些非常简单的事情:

  1. 用户以GET /dist/lat,lng

  2. 的形式提交请求
  3. 该应用使用远程IP地址和MaxMind来确定$latitude1$longitude1

  4. $latitude2$longitude2

  5. 解析此请求路径
  6. 使用这两个位置,我们计算它们之间的距离。要做到这一点,我使用Rafael Fragoso's WorldDistance PHP class

  7. 由于我打算在以后的项目中重用这个功能,所以将所有代码都放到/app目录中似乎没有用。该应用程序的两个可重用部分是:

    1. 连接到MaxMind并返回经度和纬度的服务提供商
    2. 在地球上占据两个点并返回距离的服务提供商
    3. 如果我正确构建外观,那么我可以简单地写一下,而不是我的routes.php文件在闭包内是一堆乱码,我可以简单地写一下:

      Route::get('dist/{input}', function($input){
          $input = explode( "," , $input );
      
          return Distance::getDistance( GeoIP::getLocation(), $input );
      });
      

      我尝试了什么

      初始尝试

      对于第一家服务提供商,我找到了Daniel Stainback's Laravel 5 GeoIP service provider。它没有像应有的那样轻松安装(我必须手动将geoip.php复制到/config目录,手动更新/config/app.php,然后运行composer updatephp artisan optimize)但是它有效:向GET /test发出的请求返回了我的所有信息。

      对于第二个服务提供商,我首先尝试模仿GeoIP服务提供商的目录结构和文件命名约定。我想如果我有相同的命名约定,自动加载器将能够找到我的类。所以我创建了/vendor/stevendesu/worlddistance/src/Stevendesu/WorldDistance\WorldDistanceServiceProvider.php

      <?php namespace Stevendesu\WorldDistance;
      
      use Illuminate\Support\ServiceProvider;
      
      class WorldDistanceServiceProvider extends ServiceProvider {
      
          protected $defer = false;
      
          public function register()
          {
              // Register providers.
              $this->app['distance'] = $this->app->share(function($app)
              {
                  return new WorldDistance();
              });
          }
      
          public function provides()
          {
              return ['distance'];
          }
      
      }
      

      然后我将此添加到我的/config/app.php

              'Stevendesu\WorldDistance\WorldDistanceServiceProvider',
      

      失败并出现致命错误:

      FatalErrorException in ProviderRepository.php line 150:
      Class 'Stevendesu\WorldDistance\WorldDistanceServiceProvider' not found
      

      使用WorkBench

      由于这完全失败,我认为必须有一些其他文件依赖:可能没有composer.json或没有README它放弃了。我不知道。所以我开始研究包的创建。几个Google搜索&#34;创建包laravel 5&#34;证明没有结果。之一:

      1. 他们使用的是Laravel 4.2,在这种情况下,建议是&#34;运行php artisan workbench vendor / package --resources&#34;
      2. 或者

        1. 他们使用的是Laravel 5,在这种情况下the docs were completely useless
        2. 官方的Laravel 5文档为您提供了大量的示例代码,例如:

            

          您需要做的就是告诉Laravel给定命名空间的视图所在的位置。例如,如果您的包名为&#34; courier&#34;,您可以将以下内容添加到服务提供商的引导方法中:

          public function boot()
          {
              $this->loadViewsFrom(__DIR__.'/path/to/views', 'courier');
          }
          

          这假设您有一个服务提供商将引导方法放入

          文档中没有任何内容说明如何以实际由Laravel加载的方式创建服务提供者。

          我还发现several different resources所有这些都假设你有一个存储库而你只想将它包含在你的应用中,或者假设你有&#34; workbench&# 34 ;.没有关于从头开始创建新包的事。

          PHP Artisan甚至没有&#34;工作台&#34;命令,并没有&#34; workbench.php&#34; /config中的文件,所以我发现与工作台相关的任何内容都毫无价值。我开始对Workbench进行一些研究,并在StackOverflow上找到several different questions

          经过很长一段时间和一些实验,我设法将laravel/workbench放入我的composer.json,composer update,composer install,手动构建workbench.php配置文件,最后使用PHP Artisan Workbench命令制作一个新包装:

          php artisan workbench Stevendesu/WorldDistance --resources
          

          这创建了一个目录:/workbench/stevendesu/world-distance,其中包含许多子目录和一个文件:/workbench/stevendesu/world-distance/src/Stevendesu/WorldDistance/WorldDistanceServiceProvider.php

          此服务提供程序类看起来与我之前创建的文件基本相同,除了它位于/workbench目录而不是/vendor目录中。我尝试重新加载页面,但仍然有致命的错误:

          FatalErrorException in ProviderRepository.php line 150:
          Class 'Stevendesu\WorldDistance\WorldDistanceServiceProvider' not found
          

          我也试过php artisan vendor:publish。我真的不知道这个命令是做什么的,而且描述没有帮助,所以它可能会有所帮助吗?它没有。

          问题

          如何创建一个新的服务提供者作为一个包,以便在以后的项目中我可以简单地包含这个包并具有所有相同的功能?或者说,我做错了什么,以便我创建的包不起作用?

1 个答案:

答案 0 :(得分:5)

经过两天玩这个游戏后,我找到了解决方案。我假设目录结构直接映射到它检查的自动加载器的路径(例如,尝试访问类Stevendesu\WorldDistance\WorldDistanceServiceProvider将查看vendor/stevendesu/world-distance/WorldDistanceServiceProvider)...这不是案件。

通过作曲家源代码阅读实际如何加载文件,它构建了一个&#34;类图&#34; - 本质上是一个巨大的数组映射类到它们各自的文件。此文件是在您运行composer updatecomposer install时构建的 - 只有在编辑者知道您的包的详细信息时才能正确构建。也就是说 - 如果您的软件包包含在项目的composer.json文件中

我在我的应用程序之外创建了一个本地git存储库,然后将我的包添加到我应用程序的composer.json文件中,然后运行composer update - 突然一切都运行良好。

至于:

  

它没有像应有的那样轻松安装

这里的秘诀是首先将服务提供商添加到/config/app.php 然后,第二次运行php artisan vendor:publish