AngularJS和Laravel 4路由冲突在HTML5模式下

时间:2014-01-25 22:48:54

标签: html5 .htaccess hashtag angularjs-routing

我想使用Angularjs'$locationProvider.html5Mode(true)从网址中删除#hash。

示例:地址栏显示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 Routes)

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

app.js(AngularJS Routes)

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将从该文件中接管路由)。问题:通过这种方式,Laravel路线(Route :: resource('shop','ShoppingController'); - 与数据库交互所必需的)变得无法访问AngularJS $ http服务:

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路由?

6 个答案:

答案 0 :(得分:7)

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

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

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

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

答案 1 :(得分:5)

更好的解决方案是以这种方式重定向:

'重定向::到('/#/'。Request :: path())'

直接刷新或转到URI时:

  • 'Request :: path()':返回请求的URI,即 ( '/商店/类别/电子');
  • 'html5Mode'中的AngularJS仍然响应'#/'前缀;
  • 如果在HTML5模式下,angular会检测到前缀,则会为您删除前缀。

最终解决方案:

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

答案 2 :(得分: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);
}

答案 3 :(得分:0)

如果你有一个以上的单页应用程序在html5mode中运行,或者只是在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]

答案 4 :(得分:0)

我有另一种解决方案,我发现它非常有用。我将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);
        }
    }]);

答案 5 :(得分:0)

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

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

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