17

I am trying to build a web application which should use Laravel as a RESTful backend API and AngularJS on client side. I read all the other post on Stackoverflow about the issue, but no one is definitely answering my doubts, at least, I did not find a definitive source example.

For instance...

Should I develop two completely distinct applications, a backend one with Laravel and another, purely client, with AngularJS? But in this case: how to handle them through a single domain (or virtual host)?

Or should I create AngularJS templates inside Laravel, in the "views" folder and from them call Laravel services? I doubt this is the best approach: in this case the backend is not completely decoupled from the frontend implementation.

Also, how to correctly handle routing? I mean: I would like to manage from AngularJS routes like menu/page navigation, calling Laravel only to retrieve data and fill my views. Moving the "public" folder as suggested in this post (Angular JS + Laravel 4: How to compile for production mode?) may help?

Thanx in advance for suggestions, examples...

Community
  • 1
  • 1
Matteo Piazza
  • 2,462
  • 7
  • 29
  • 38
  • 2
    Keeping the two decoupled is the right idea. I haven't worked with Laravel but I'd say have Angular handle all the client side presentation and interaction logic. Keep Laravel protecting and serving up the appropriate data and use it to fetch data using either $resource or $http in angularjs to avoid page reloads. To navigate the client views you can use ui-router or the built in routes and $location – shaunhusain Nov 13 '13 at 22:46
  • Thanx Shaunhusain, I was following the path of two decoupled applications... but it is not clear to me how to handle them from the "domain" point of view. For instance: if my web application is "http://myapplication.com" how should two decoupled applications behave? "http://myapplication.com" should reach a "index.html" file written through Angular and something like "http://myapplication.com/ws/..." should handle requests to Laravel? How to set those routing in AngularJS, Laravel or, for instance, Apache virtual host? – Matteo Piazza Nov 13 '13 at 22:54
  • Although I generally agree with shainhusain it depends on how you want to handle authentication. There are some approaches which couple angularjs and laravel more closely and in doing so adding to the level of security: http://blog.neoxia.com/laravel4-and-angularjs/ – hugo der hungrige Nov 13 '13 at 23:43
  • I don't understand the security concern here. I'm rolling my own PHP services and have authentication setup using phPass for making/checking hashes stored in a MySQL database. If any request is made without a valid session the response is 401 which I just handle client side by redirecting to the login. I'm thinking of also adding a bit similar to most bank sites to notify the user before the session will expire and ask if they'd like to maintain it since there's not a lot of chatter being a SPA. Matteo think you have the right idea though angular loads then does XHR. – shaunhusain Nov 14 '13 at 06:35

2 Answers2

24

Finally I found a working solution, perfect in my scenario, which does not require a subdomain. In this case Laravel acts exclusively as a RESTful web service, no server side views or templates: the presentation layer is completely demanded to AngularJS.

Let's say I have two completely decoupled applications (FE e WS) inside the same root folder:

root
|__fe
|__ws

I modified virtual host settings under Apache httpd-vhosts.conf file the following way:

<VirtualHost *:80>
    ServerName myapp.com
    DocumentRoot "\www\root\fe"

    alias /ws "\www\root\ws\public"
    <Directory "\www\root\ws\public">
        Options Indexes FollowSymLinks MultiViews
        AllowOverride all
            Order allow,deny
        Allow from all
    </Directory>
</VirtualHost>

I then added "RewriteBase /ws" into my laravel/public/.htacces file:

<IfModule mod_rewrite.c>
    Options -MultiViews
    RewriteEngine On

    RewriteBase /ws

    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [NC,L]
</IfModule>

This way I can write in the browser (for instance):

http://myapp.com             (AngularJS client side root)
http://myapp.com/ws/users    (RESTful service endpoint for "users")

And then define a client side, AngularJS routing the following way:

app.config(function($routeProvider) {
    $routeProvider
        .when('/', {controller: 'HomeController', templateUrl: 'templates/home.html'})
        .when('/users', {controller: 'UsersController', templateUrl: 'templates/users.html'})
        .otherwise({redirectTo: '/'});
});

Linking it to a RESTful resource this way:

app.factory('User', function($resource) {
    return $resource('http://myapp.com/ws/users');
});

app.controller('UsersController', function($scope, User) {
    $scope.title = "Users";
    $scope.users = User.query();
});

I enabled HTML5 history API, adding this line to configure my Angular application:

$locationProvider.html5Mode(true);

together with (inside index.html head section):

<base href="/" />
<meta name="fragment" content="!" />

So the last requirement to solve problems like browser page refresh, deep linking, or direct page bookmark, is to add a .htaccess file in the root of the folder which contains the Angular application:

<IfModule mod_rewrite.c>
    Options -MultiViews
    RewriteEngine On

    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.html [NC,L]
</IfModule>

Hope it helps!

Matteo Piazza
  • 2,462
  • 7
  • 29
  • 38
  • I am looking for a similar structure for my application,but I am not sure how I should move ahead with **angular 5.0** If you have used a similar struture in angular,could you help by updating the answer? The challenge is I am not able to invoke routes correctly. How to load **initial route**. I found all apps place the angular index file with dependency placed inside the `resources` or `public` dir of laravel. But for such a structure I believe that cannot be a solution.Reference: http://angular-tips.com/blog/2014/10/working-with-a-laravel-4-plus-angular-application/ – KillABug Jul 14 '15 at 09:33
  • Also do the sessions function as usual in this scenario or need some modification? Do you use any token management for the ws ? I want my app to work as an API and also a web application backend. Please suggest – KillABug Jul 14 '15 at 09:37
0

This is a half comment half answer, it got too long.

Matteo as you pointed out there are basically three different places you can do some sort of routing/redirecting with this stack. Ordinarily I haven't seen an advantage to doing the redirects at the Apache level, I imagine this might be more useful for localization or perhaps some sort of load/disk balancing. However you will have your VirtualHost configuration if you have multiple domains pointing to this address and you need to route those initial requests to the appropriate index.html (so if you consider this routing this would be my server side routing).

Generally speaking after that I rely on the Angular $routeProvider to handle client side "routes" really just mapping a URL to a view (possibly passing along some data).

I haven't gotten fancy with setting up a router in my PHP code to create a proper RESTful interface. In my particular case the data is being stored in a fairly abstract way and I had to do a fair amount of work in the PHP to get it organized in a coherent way, any straight ORM type solution wasn't going to work. This attempt has led me to consider options like MongoDB though since it should alleviate the workload necessary for doing the translation from persistent storage to client side and back.

Anyhow all that said I use $http to just make my calls from custom services to particular PHP endpoints that I need. My PHP folder with my scripts sits right next to where my index file is served up so requests from angular are all relative paths from the server root which keeps it simple. So they are physically "nested" so to speak or living side by side but the PHP code never writes any templates or affects the presentation it just gets data and serves it up (as JSON), so conceptually they remain separate.

shaunhusain
  • 19,630
  • 4
  • 38
  • 51
  • 1
    So far, I ended up creating two completely decoupled applications: one is the backend web services provider (Laravel as RESTful) and the second is merely client side (angular project, with html, js, and css). I defined a domain to access the frontend side (http://myapplication.com) and a subdomain to access backend services (http://ws.myapplication.com). – Matteo Piazza Nov 15 '13 at 09:09