【问题标题】:AngularJS and Laravel 4 routing conflict in HTML5 modeHTML5 模式下 AngularJS 和 Laravel 4 路由冲突
【发布时间】:2014-02-16 21:33:44
【问题描述】:

我想使用 Angularjs 的 $locationProvider.html5Mode(true) 从 URL 中删除 # 哈希。

示例:地址栏显示http://localhost/shop,而不是http://localhost/#/shop

在我刷新页面之前一切正常。如果我刷新,将访问以下 Laravel 路由(在 routes.php 中定义)

Route::resource('shop', 'ShoppingController')

不是 AngularJS 路由(在 app.js 中定义)

$routeProvider.when('/shop', { 
    templateUrl: 'templates/shop.html', 
    controller: 'ShoppingController' 
});

我的代码:

routes.php(Laravel 路由)

Route::get('/', function() {
    return View::make('index'); 
});
Route::resource('shop', 'ShoppingController'); 

app.js(AngularJS 路由)

var app = angular.module('shoppingApp',['ngRoute','SharedServices']); 

app.config(function($routeProvider, $locationProvider) { 
    $routeProvider.when('/shop', {
        templateUrl: 'templates/shop.html', 
        controller: 'ShoppingController'
    });
    $routeProvider.otherwise({ redirectTo: '/' }); 
    $locationProvider.html5Mode(true); 
});

我的目录结构:

Project
    /app 
        /...
        /views
            -index.php (single page application file)
            -routes.php (Laravel routes)
    /public
        /...
        /js
            -angular.js
            -app.js
        -index.php (Laravel index file)

尝试过的解决方案:

重写 htaccess 文件,以便将所有请求重定向到 index.php(单页应用程序文件,AngularJS 将从该文件接管路由)。问题:这样,AngularJS $http 服务无法访问 Laravel 路由(Route::resource('shop', 'ShoppingController'); - 与数据库交互所必需的):

app.js

app.controller("ShoppingController", function($scope, $http) {
    $http.get('/shop', { cache: true}).
        success(function(data, status) {
        $scope.items = data
    }).
    error(function(data, status) {
        console.log('Status: ' + status);
        });
});

问题: 如何解决路由问题,以便在刷新 localhost/shop 时访问 AngularJS 路由,而不是 Laravel 路由?

【问题讨论】:

    标签: html .htaccess hashtag angularjs-routing


    【解决方案1】:

    根据我的阅读,当您刷新页面时,Laravel 似乎正在阅读修改后的路线。在这种情况下,你应该让 Laravel 继续制作原始视图,即使它是 404 重定向。

    尝试在 Laravel 端的某处添加以下内容(例如 routes.php)

    App::missing(function($exception)
    {
        return View::make('index');
    });
    

    注意:您可能希望 AngularJS 的路由使用 .otherwise 来处理未找到的页面。

    【讨论】:

    • 感谢您的回复。我添加了这样一个捕获所有路由并为我的所有后端路由(Route::group(array('prefix' => 'api'), function(){}) 添加了前缀,正如本优秀教程中所建议的那样:scotch.io/tutorials/php/…
    • 我认为这样可以避免 404 错误页面。所以我们的应用不会有任何 404 页面!
    【解决方案2】:

    更好的解决方案是这样重定向:

    'Redirect::to('/#/' .Request::path())'

    当你刷新或直接进入 URI 时:

    • 'Request::path()':返回请求的 URI,即 ('/shop/categories/electronics');
    • “html5Mode”中的 AngularJS 仍然响应“#/”前缀;
    • 如果 Angular 在 HTML5 模式下检测到前缀,它将为您删除前缀。

    最终解决方案:

    App::missing(function($exception) {
        return Redirect::to('/#/' . Request::path());
    });
    

    【讨论】:

      【解决方案3】:

      如果您使用的是 Laravel 5,请转到 app/Exception/Handler.php 并将代码放在下面:

      public function render($request, Exception $e)
      {
          if($e instanceof NotFoundHttpException)
          {
              return Redirect::to('/#/' . Request::path());
          }
          return parent::render($request, $e);
      }
      

      【讨论】:

        【解决方案4】:

        如果你想在 html5 模式下运行多个单页应用程序,或者只是在 Laravel 应用程序中对 App::missing 有另一种用途,你可能会使用这样的重写规则:

        #Redirect base url of AngularJS app in html5mode
        
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_URI} ^/path/.+$
        RewriteRule  ^(path)/(.*)  /path/#/$2           [R=301,L,NE]
        

        【讨论】:

          【解决方案5】:

          我有另一个我觉得非常有用的解决方案。我不只是制作主页视图,而是将 URI 传递给主页,该主页将由控制器检查并相应地重定向(Angular 方式)。这意味着,如果您在 myapp.com/about 上并刷新,而不是带您回家,它会将您带回您当前所在的页面。

          routes.php: 请注意,我有一个 URI 通配符,我将其作为参数传递给回调函数,然后作为变量传递给视图。

          // Note that this must be on the bottom of your routes file because
          // if you have any registered route with a similar pattern
          // it will get caught by this route and never reach any registered routes you might have
          Route::get('{slug}', function($slug){
              return View::make('index', compact('slug'));
          });
          
          
          // These routes will never get hit, so move them above Route::get('{slug}')
          Route::get('about', function(){...});
          Route::get('contact', function(){...});
          

          index.blade.php:

          <html ng-app"myApp">
          <head>
              ...
          </head>
          <body>
              <!--Check if there is a variable named $slug that is set-->
              <!--If it is, set hidden input with ng-model-->
              @if(isset($slug))
                  <input type="hidden" value="{{slug}}" ng-model="slug" ng-controller="RedirectController">
              @endif
          
              <div ng-view></div>
          </body>
          </html>
          

          app.js

          angular.module('myApp', [])
              .controller('RedirectController', ['$location', '$scope', function ($location, $scope) {
                  // If slug is set, redirect to that slug
                  if ($scope.slug) {
                      $location.path('/' + $scope.slug);
                  }
              }]);
          

          【讨论】:

            【解决方案6】:

            对于 Laravel 4.x 或 5.x,我使用这个简单而漂亮的技巧,无需更改 .htaccess 文件。这个技巧非常简单,对我有用。它不会重定向 URL,当刷新页面和页面刷新时,用户将保持在相同的 URL:

            Route::get('dashboard/{all?}', function(){
                return view('main.index');
            });
            

            我的仪表板应用是我的 SPA。这样我们也可以解决 404 错误页面。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2018-11-30
              • 2016-05-26
              • 1970-01-01
              • 2017-04-15
              • 2018-05-23
              • 1970-01-01
              • 2014-09-23
              相关资源
              最近更新 更多