AngularJS and Laravel Shopping List Application – Part 2
As promised here is the second part of building our Shopping List Application with the excellent AngularJS the JavaScript MVW framework. In this final part we are going to look at how to extend our application so that it can receive data (via JSON) from a REST based application to populate our shopping list with items. This is as opposed to the static method we have at the moment.
AngularJS + Laravel: Prerequisites
The most obvious prerequisite is that you have followed or at least read the first part of this tutorial. If you haven’t go back & read part one of our AngularJS tutorial now. I’ll wait for you. You back? Good.
AngularJS + Laravel: Notes
First a couple of notes. There are a couple of ways to do this. I’ve picked the simplest as it is a simple application & we don’t want to overcomplicate things. Also I’m going to show you how to set up a REST based application to feed data into our AngularJS app using Laravel. To do this you need a few things. Please note: Laravel requires PHP 5.3.7
& MCrypt
to work.
First is Composer. Just go to the download page. If you are on Windows like me, get the Windows install & you should be done in no time. You may need to restart or at least log out for some changes to take effect so go on. I’ll wait again. Back? Good.
Now that you have Composer, let’s get on with setting up Laravel.
AngularJS + Laravel: Setting Up
There are two ways to do this. I prefer the slightly more manual method so we are going to follow that one. Get yourself a copy of the Master of Laravel from Github (Hit ‘Download ZIP’ on the bottom right) and extract it to a folder in your localhost. I’m using the folder name rest
for this. Now I think I should explain how this is going to work first.
Instead of having Laravel running our AngularJS application and our REST system we are just going to have Laravel run our REST system. This keeps things simpler as this tutorial is more about AngularJS & not Laravel.
Now that you have Laravel in it’s folder let’s get it setup. Open a command prompt, or terminal and navigate to the directory you just extracted Laravel to. In my case the command looked like this:
1 |
cd ../../xampp/htdocs/rest |
That’s cd
or ‘change directory’. Out 2 folders, into the xampp
folder, htdocs
and then rest
. Now that you are there just run:
1 |
composer install |
Then wait for a while as Composer installs Laravel & it’s dependencies.
All done? Good. Now you’ve done that we need to set a few more things up. First open up app/config/app.php
and use a random string generator to get a 32 character string to place in the key
field. Also update the url
in here which will eventually be http://localhost/rest
once we’ve setup an Alias.
Now rather than faff around with Virtual Hosts we are just going to set up an Alias. To do this open up your Apache httpd.conf
file. In my case (using XAMPP) this is located at C:/xampp/apache/conf/httpd.conf
. At around line 220 there is a block of code that starts with:
1 |
<Directory "C:/xampp/htdocs"> |
You want to copy that all the way down to the closing directory tag (</Directory>
) and paste it directly underneath. Then change the path inside the directory tag to C:/xampp/htdocs/rest/public
or whatever the path is to your Laravel public folder. Now look around line 340 for the <IfModule alias_module>
tag and inside add:
1 |
Alias /rest C:/xampp/htdocs/rest/public |
Again change the path to your Laravel public folder if it is different. Now restart Apache using your web servers control panel to apply the changes. Finally open up the .htaccess file located in the Laravel public folder and make sure it matches the following:
1 2 3 4 5 6 7 |
<IfModule mod_rewrite.c> RewriteEngine On RewriteBase /rest RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.php [L] </IfModule> |
Once you’ve done that visiting http://localhost/rest
should give you the Laravel welcome page. If not try restarting Apache once more, if all else fails leave a comment and I’ll see if I can help out. These steps should be the same for all web servers using Apache, just the paths might be different.
AngularJS + Laravel: REST
Now we’ve set up Laravel we can move on to getting our REST app working. For this we’ll have to visit the command line a few more times. In Laravel open up app/config/database.php
and enter your local Database details. Once you’ve done that go back to your command prompt (open one & navigate to the ‘rest’ folder if you closed it) and run:
1 |
php artisan migrate:make create_shopping_table |
This will make you a migration file. If it failed for some reason try these steps. Open it up from app/database/migrations
now in the up
function enter the following:
1 2 3 4 5 |
Schema::create('items', function($table) { $table->increments('id'); $table->string('text'); $table->boolean('bought'); }); |
In the down
function enter this:
1 |
Schema::drop('items'); |
This tells Laravel to create us a table with those fields when we run the migration. If we were to reverse it the it runs the down
function which simply drops the table. This is used for versioning your modifications to database tables within Laravel & is very handy. That, however, is something for a Laravel tutorial so let’s move on.
Now back in the command prompt run:
1 |
php artisan migrate |
This will create the table we need.
Now we need to enter some data so we can check things are working. We could use Laravel’s Seeding system, but to save complicating things just jump into your Database Admin (Normally PHPMyAdmin) and add some data manually. If you aren’t sure how to do that, don’t worry it just means you won’t be able to see any results until we’ve added in the ability to add items via our app. That’s perfectly fine though so don’t worry.
Now to do some CRUD (Create, Read, Update, Delete) on our table we need a Model so Laravel can access our table. Let’s make one. In app/models
create a file called Item.php
. Inside all you need is the following:
1 2 3 4 5 6 7 |
<?php Class Item extends Eloquent { public $timestamps = false; } |
I’ve included the PHP tag just to show it is needed, but that’s all the code you need. The $timestamps
variable is set just to tell Laravel we don’t want to use it’s automatic timestamp system. If you don’t add this Laravel will error because our table doesn’t include any fields for using timestamps, so make sure you leave it in there.
Now we just need to create our REST controller. Again at the command prompt run this:
1 |
php artisan controller:make ShoppingController |
Then open up your new controller found at app/controllers/ShoppingController.php
. We are only going to use a few of the methods available here, but it is fine to leave the others for this demo. If you are using it in production I would remove the others. You are only going to need index
, store
, and destroy
for this demo. First let’s take a look at index
:
1 2 3 4 5 |
public function index() { $items = Item::all(); return $items; } |
That’s all it is. This returns all of our items listed in some lovely clean JSON ready for AngularJS.
Next up is store
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public function store() { $input = Input::get('text'); $item = new Item; $item->text = $input; $item->save(); if($item) return 1; else return 0; } |
This just grabs the name we have sent & saves it as a new item in the database. It also returns 1 or 0 to tell Angular if it saved successfully.
Finally is the destroy
method:
1 2 3 4 5 6 7 8 9 |
public function destroy($id) { $item = Item::find($id); if(!$item) return false; $item->delete(); } |
All this does is find the item via the ID & deletes it.
The last thing we need to do is to setup some routing for Laravel. This is pretty simple, just open up app/routes.php
, delete what you find and replace it with:
1 |
Route::resource('shop', 'ShoppingController'); |
This will make it so if you visit http://localhost/rest/shop/
you will hopefully be faced with some JSON. You can also setup a method called missingMethod
in your REST controller to catch any calls to unknown methods.
Now let’s setup a route to catch any visits to other URLs so that when we turn off debugging there will be a message shown to visitors. First still in app/routes.php
type this above the route you just added:
1 2 3 4 |
Route::get('/', function() { App::abort(404); }); |
This will tell Laravel to throw a 404 error for any url that doesn’t match shop
. Then if you want to show a nice custom message you can open up app/start/global.php
and add this above the Require The Filters File
comment.
1 2 3 4 |
App::missing(function() { return Response::make("This is not a valid URL for this REST service.", 404); }); |
If you are more familiar with Laravel (again this is a AngularJS tutorial) you can return a view if you like, but this will do for this demo.
Phew! That’s our Laravel REST system complete, now we just need to tie our AngularJS code into it. Let’s do that now.
AngularJS + Laravel: $http
Now let’s get back to Angular. Reopen your app.js
& index.html
files from the last part.
First up we need to define our App this time. To do that in index.html
change ng-app
to ng-app="myApp"
. Then in app.js
add this to the top of the file:
1 |
var app = angular.module('myApp', ['SharedServices'] ); |
This defines our app & declares the SharedServices
module as a dependency, we’ll define that next.
Under that code let’s add in that dependency. It actually allows us to add a nice loading spinner while our App retrieves the data. To do this we use a nice little snippet, I honestly don’t know who came up with this first but thank you however you are:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
angular.module('SharedServices', []) .config(function ($httpProvider) { $httpProvider.responseInterceptors.push('myHttpInterceptor'); var spinnerFunction = function (data, headersGetter) { // todo start the spinner here $('#loading').show(); return data; }; $httpProvider.defaults.transformRequest.push(spinnerFunction); }) // register the interceptor as a service, intercepts ALL angular ajax http calls .factory('myHttpInterceptor', function ($q, $window) { return function (promise) { return promise.then(function (response) { // do something on success // todo hide the spinner $('#loading').hide(); return response; }, function (response) { // do something on error // todo hide the spinner $('#loading').hide(); return $q.reject(response); }); }; }); |
I don’t want to go into this code too much as it is outside of the scope of this tutorial, but it basically intercepts any requests made by the $http
service and shows/hides a loader element as needed.
You may notice that this uses jQuery. Well since we don’t have it attached to our HTML file let’s do that. Above all our other scripts I’ve attached it using the Google CDN like this:
1 |
<script src=quot;//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script> |
Again hosting it yourself is advised but this is fine for our demo. Next we need to add in the element it is using. Let’s add that in too. Again in your HTML file (index.html
) find your ul
and add a new li just above your ng-repeat
. Like this:
1 2 3 4 5 6 7 |
<ul class="unstyled"> <li id="loading"></li> <li ng-repeat="item in items"> <input type="checkbox" id="item-{{item.id}}" ng-model="item.bought"> <label for="item-{{item.id}}" class="{{isBought(item.bought)}}">{{item.name}}<span></span></label> </li> </ul> |
Now I’m going to use a Canvas loader. To do this just add the Heartcode CanvasLoader to the page with your other script tags:
1 |
<script src="//heartcode-canvasloader.googlecode.com/files/heartcode-canvasloader-min-0.9.1.js"></script> |
Then add the following code just before the closing body tag.
1 2 3 4 5 6 7 8 |
<script type="text/javascript"> var cl = new CanvasLoader('loading'); cl.setDiameter(100); // default is 40 cl.setDensity(12); // default is 40 cl.setRange(0.7); // default is 1.3 cl.setSpeed(1); // default is 2 cl.show(); // Hidden by default </script> |
Then a little bit of CSS:
1 2 3 4 5 6 |
.container .main #loading { position: absolute; top: 25%; left: 40%; z-index: 900; } |
This is entirely optional, you can just add in a standard gif, but I like the new canvas option & though you’d might like it too.
Right, before we continue you need to know how you can access the REST controller’s different methods. It’s not as simple as calling them via URL such as rest/store
. They have a special way to access them because of being a resource (as Laravel calls it) controller. Let’s take a look:
HTTP Verb | url | method |
---|---|---|
GET | /rest/shop | index |
POST | /rest/shop | store |
DELETE | /rest/shop/:id | destroy |
These are just the ones we are using to keep it simple the others can be found over in Laravel’s documentation.
Now, you might be wondering why this section is subtitled $http
, well we are getting to that now. I’m going to post all the new controller (ShopCtrl
) code in one go this time as I think it would be too awkward to explain what has been changed:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
function ShopCtrl($scope, $http) { $http({ method: 'GET', url: '/rest/shop/', cache: true }). success(function(data, status) { $scope.items = data }). error(function(data, status) { console.log('Status: ' + status); }); $scope.clearBought = function() { $scope.items = _.filter($scope.items, function(item) { if(item.bought) { $http.delete('/rest/shop/' + item.id).error(function(data, status) { console.log(status); }); } return !item.bought; }); } $scope.addItem = function() { $http.post('/rest/shop', { text: $scope.itemEntry } ).success(function(data, status) { if(data) { var last = _.last($scope.items); $scope.items.push({text: $scope.itemEntry, bought: false, id: (last.id + 1) }); $scope.itemEntry = ''; console.log($scope.items); } else { console.log('There was a problem. Status: ' + status + '; Data: ' + data); } }).error(function(data, status) { console.log('status: ' + status); }); } $scope.isBought = function(bought) { return (bought) ? 'bought' : 'not-bought'; } } |
You’ll probably be able to see the biggest change is the use of Angular’s $http
service. Let’s go through each new part of this code. First the most important part that I’ve noticed causes a lot of bother.
1 |
function ShopCtrl($scope, $http) { |
Yep, there are lots of beginners that completely forget to send the $http
service through and wonder why it doesn’t work. Well, in the infamous words of Adam Savage, “There’s your problem!”
Next up is the part that actually grabs the data from our REST service when the page loads.
1 2 3 4 5 6 7 |
$http({ method: 'GET', url: '/rest/shop/', cache: true }). success(function(data, status) { $scope.items = data }). error(function(data, status) { console.log('Status: ' + status); }); |
So this is the extended version of using the $http
service. It is not necessary to use this version here, but I thought I would in this demo to show what it looked like. Basically we give it the method (HTTP VERB), in this case GET, the URL to visit, in this case /rest/shop/
, and we also want it to cache the data to save resources. Then we have two callbacks, if you are familiar with jQuery’s AJAX then you might feel at home with these. Basically if the request was successful we populate the $scope.items
(the variable that holds all the shopping items, remember?) variable with the data. If there was an error, you would need to trigger something for the user to see. Again as this is just a demo I have just triggered a console log so I can see the status code. You could trigger a modal with an error in or a small text message, anything you like really.
Notice that the code we have just been talking about is just inside the controller & is not held in a method. This is because we want to trigger it as soon as the controller is called. I’ve seen some arguments about whether this is valid, but I haven’t had any trouble with it so I’d say go for it. If it makes you feel better though you can add it as a method of $scope
& call it at the bottom of your app.js
file to trigger everything off.
Next up is the new version of clearBought
.
1 2 3 4 5 6 7 8 9 10 |
$scope.clearBought = function() { $scope.items = _.filter($scope.items, function(item) { if(item.bought) { $http.delete('/rest/shop/' + item.id).error(function(data, status) { console.log(status); }); } return !item.bought; }); } |
Now this probably isn’t the most efficient way to do this, but as we were using a REST service you can only pass 1 ID at a time so this is the best I could come up with. If you have another idea that is more efficient, answers on a postcard (or the comments) please.
All this code does is exactly the same as before. Filters out the items that have been bought, but this time as it is filtering we check if the current item has been bought & fire off a $http
request to delete the item. This time I’m using the short version with the delete
method. All you do is pass the URL, which in this case is /rest/shop
plus the ID of the item we want to delete. Again I’ve added a error callback which just sends back the status code for debugging, but you’d want to add your own result to notify the visitor. Again a modal or something like that would be perfect.
Finally is the code to add a new item. This is the longest code so hold onto your hats, we’re going in.
1 2 3 4 5 6 7 8 9 10 11 12 |
$scope.addItem = function() { $http.post('/rest/shop', { text: $scope.itemEntry } ).success(function(data, status) { if(data) { $scope.items.push({text: $scope.itemEntry, bought: false, id: data }); $scope.itemEntry = ''; } else { console.log('There was a problem. Status: ' + status + '; Data: ' + data); } }).error(function(data, status) { console.log('status: ' + status); }); } |
So straight away we trigger $http
this time using the post
method, again we give it the url /rest/shop
and this time we pass along some data. Note the lack of forward slash on the end of the URL. I’ve noticed if you add that in it will fail to add the item. In this case all we want is the text. How? Well the id & the bought value will be automatically be set to the correct values by the database as the ID is auto incremented & bought should be false by default.
Now in the success callback we check if our data was added, remember our Laravel method returns 1 on success, 0 on failure (0 is treated as falsy). The problem with this is that we need the ID that was created for the inserted item. To fix this go back to your Laravel application & open up app/controllers/ShoppingController.php
and in the store
method find:
1 2 3 4 |
if($item) return 1; else return 0; |
Change it to:
1 2 3 4 |
if($item) return $item->id; else return 0; |
This will send us back the ID created by the database when the item was inserted or 0 if it fails.
Now back to Angular. The last important line is:
1 |
$scope.items.push({text: $scope.itemEntry, bought: false, id: data }); |
This adds our new item to our array using the text from the text field again, automatically setting bought to false & using the ID we retrieved from Laravel (held in the data
) variable. The rest of the code is just for error handling. Again I have console logs in there for debugging purposes but you could add some sort of modal to show visitors a friendly error.
AngularJS + Laravel: Artisan Doesn’t Work
This is normally because you are on a windows machine & PHP isn’t in your PATH environment variable. To solve this open an Windows Explorer window (the folder), right-click Computer and press ‘Properties’. Now click ‘Advanced System Settings’ on the left (Win 7 >), then press ‘Environment Variables’. In the bottom panel click Path, then click ‘Edit’. Now at the end of the 2nd text field enter a ;
if there isn’t one there then type the path to the folder where PHP is held. If you are using XAMPP on your C drive this is normally C:\xampp\php\
. That’s it.
You may need to restart or log out for the changes to take effect but normally you can just start using it without any problems.
AngularJS + Laravel: Summary
That’s it. It’s been a long tutorial but we’ve finally finished. If you reached this point you should now have a Shopping List application that is nearly identical to part 1, but it is now loading it’s data from an external source.
This is a huge tutorial so if you do have any problems please let me know in the comments & give me as much detail as you can about the issue you are having as it is pretty hard to debug without any error data. Unfortunately there is no demo for this part since, if this tutorial became popular, my server would hate me for it. If you are itching to see what it would look like though, use the demo in part 1.
As always thank you for reading. If you have any tips, suggestions or improvements I’m always happy to hear them. If you have any ideas for the kind of tutorials you’d like to see next, please post them on our Facebook wall or get in touch using Google Plus (links in the sidebar on the left).
47 Comments
Stephen
A really great set of tutorials… I had been struggling with connecting AngularJS to PHP and these tutorials made it really clear for me, thanks.
In the store piece of code I did have to change name to be text to line up with the fieldname i the database?
$input = Input::get(‘text’);
$item = new Item;
$item->text= $input;
Although I may have it wrong but my code works now 🙂
Paul Robinson
Hi Stephen,
Glad it helped. I must admit that connection Angular to PHP is a little difficult, it took a while to find a method that wasn’t too difficult to explain without a lecture, lol.
Nice spot. I had originally used different names for the variables & I hadn’t changed that. Thanks for pointing it out, I’ll change it now. 🙂
Loko
Thanks bro for this tuto.
Burak AKIN
Hello nice tutorial but I cant get some parts work as expected. I create a virtual host. I installed my laravel application. When I visit application.dev/shop I can see the Json array.
Where do I put index.html and app.js ? I cant get any views?
Paul Robinson
Hi Burak,
Your Angular app would be setup in another directory on your localhost. For example my local install I used
http://localhost/angular/
for my Angular app, andhttp://localhost/rest/
for my Laravel install.I apologise if that hadn’t been made clear in the tutorial.
Ghislain
That is a great tutorial and is what I was looking for in combining Laravel + AngularJS…if I may give you a suggestion on your loop of removing the bought items, it might be better to just remove the chosen item on the spot when user is clicking on it, I mean why wait for the button “Remove Bought” and loop on each of them when you can remove the particular item when user is selecting it? Unless you really want to have the display still showing these bought items, but even then you could delete them from the DB and leave screen as is, after then if user refreshes his screen they’ll be gone, I would probably prefer this way actually, if user decide to put it back you could just re-push the same item in the DB.
Nice work again…
Paul Robinson
Hi Ghislain,
Unfortunately that idea violates the general features of a shopping list, or Todo app.
Leaving the items on the page allows the user to reference that they have already completed that task (Todo app) or bought the item (Shopping list).
Deleting the item, but leaving the item on the page risks problems with the item being permanently removed if the user loses signal or has an internet outage. It is also much more work to delete it, then re-push to the database than it is to just wait until they decide to clear the list.
As I have always said though, nothing is right or wrong. There are just different ideas on efficiency and ease of use. I personally prefer this setup, but would love to find a way to send a mass delete request to the REST API instead of looping through one at a time.
pl Nodi
Very helped tutorial……..
mothana
it takes around 3seconds to load from the DB, dont you think thats very slow?
Paul Robinson
Hi,
There is something wrong with your database if it is taking that long. During my testing my local database was serving data almost instantly with a list of up to 40 items.
Hasan
Thank for your tutorial
I think it would be better to use $resource instead of $http in a Rest application.
Isn’t it?
Paul Robinson
Hi Hasan,
I’ve seen no evidence to suggest either way is better than the other (unless it has changed in a newer version of Angular), but whichever way you find the easiest or are familiar with would be the best way to go.
The aim of most of my tutorials is simply to teach those that don’t know, and nudge or help those that do in the correct direction. It isn’t to dictate what code you should & shouldn’t use.
softfrog
Lovely tut, thanks! Quick change to update the bought status in the db:
– add ng-change=”toggleBought(item.id, item.bought)” to the checkbox
– add the toggleBought function to the app:
– add the update function to the controller:
Paul Robinson
Hi,
Very nicely done. Would you mind if I added this to the article so that everyone can find it easily?
One small amendment, only for validation purposes, might be to pass
Input::get('bought')
throughfilter_var($input, FILTER_VALIDATE_BOOLEAN)
to make sure it is a boolean. Mainly to keep validation purists happy. 😉Again very well done & thank you for sharing it.
softfrog
Sure thing. My first stab at laravel & angular, was glad to find they slot together so neatly. Validation definitely!
Ryan Durham
Hi – thank you for this great tutorial!
I am running into a problem with the clearBought() function.
For some reason, my code is treating items.bought as a string rather than an integer, and as a consequence it is removing items from $scope.items randomly, rahter than just the ones that have been marked as bought. Any idea what could be causing that?
Thanks!
Ryan Durham
Sorry – I used the wrong snippet there. I added the ‘ == “1”‘ to get around the string problem and it seems to be working.
Ryan Durham
I was able to get it working with these modifications: http://paste.laravel.com/1cvP
I still feel like I must be doing something wrong – any idea what it could be?
Burak AKIN
Hello , I am trying to run this with nginx server … how can I rewrite base with nginx ?
Here is my nginx config : http://paste.laravel.com/1h1N
Nick Harberg
The tutorial is great and is just what I have been looking for. I am having trouble with the laravel set up. It has to do with the Alias and .htaccess steps since when I run my laravel install using ‘php artisan serve’ the rest folder works on localhost:8000 and when I go to localhost:8000/shop I see the json read out from the database.
I am using osx with the local apache, php setup (and mysql is installed as well). My local machine url is localhost/~harberg/(folder name here), so for the angular portion I have it in a folder called shop, so localhost/~harberg/shop. When I open localhost/~harberg/rest I see the file directory (with the public folder missing). When I enter in localhost/~harberg/rest/public/ I get a 403 error. I have done a chmod to set the permissions at 777, but that hasn’t helped.
I tried just leaving the two folders (shop and rest) where they were working, but when I put the url of ‘localhost:8000/shop’ into the $http method of app.js I get an error in the console.
I would like to assume I am just missing something little, but any help would be great. Thanks.
NaingWin
I got (anonymous function) in Delete Method
(anonymous function) angular.min.js:99
l angular.min.js:95
m angular.min.js:94
m.(anonymous function) angular.min.js:96
(anonymous function) app.js:37
w.filter.w.select underscore-min.js:1
ShopCtrl.$scope.clearBought app.js:35
(anonymous function) angular.min.js:72
(anonymous function) angular.min.js:143
e.$eval angular.min.js:88
e.$apply angular.min.js:88
$delegate.__proto__.$apply VM2506:855
(anonymous function) angular.min.js:143
x.event.dispatch jquery.js:5116
v.handle
rahul
Can i use Laravel framework as frontend and angular js as a part . If yes? then how will i manage angular controller
Paul Robinson
Hi Rahul,
I’m not sure I understand. If you mean can you have Laravel run your app as well as the REST app, then sure. Just setup a second controller to serve your application & setup a route to match. It’s too complicated to explain here, but Laravel’s quickstart docs do a pretty good job of explaining what you would need to know to do that.
Shrutika
Hi, your part 1 link is broken I suppose it gives 404 error
Paul Robinson
Hi,
Sorry about that. Thank you for letting me know. I’ve now corrected the link & it should be working again.
Akbar
Hi, I am doing one project in Laravel and AngularJS, PHP, Can you help me how to insert multiple records in one click submit.
I am sorry actually i am new to these technologies.
Ak
Please find the below code of Controller :
Find App.js Code :
Paul Robinson
Hi Akbar,
I’m not too sure I understand? Do you mean you would like to insert more than one record into your database on submit? If so you can use:
Just note that using that will insert the rows immediately (save does not need to be called) and can only be done if you have set a
fillable
orguarded
property on your Eloquent Model.Is that what you were looking for?
Akbar
Thanks for reply,
Yes i want to insert multiple records, because i am creating invoice form.
I am sorry i can’t understand your code please can explains as per my code.
Please don’t mind i am new to this.
Ak
Paul Robinson
Hi,
Laravel has two methods of creating new rows in your table. The way you are using, and the
create()
method that is available on your Eloquent Model.Assuming that
hostel_add
is your Model name then you would use:If your data comes comes from a POST request then you might want to run through your POST data using a for loop and create an array of arrays from your POST data and pass that straight to the
create()
method. There is more in Laravel’s docs under the section called Mass Assignment.Does that help a little more?
Akbar
Thanks for reply,
I have to use loop to save multiple records.
Akbar
Akbar
Hi,
hostel_add is my model name.
I made a multi record form in html, once i submit the button it will trigger the create function in controller.
Akbar
Paul Robinson
Hi,
Then if you are sending all of the form results to your Laravel Controller you would use a
foreach
loop to go through each record and create an array of arrays containing the information in the format I used in the last comment. Then just pass that variable to your Model’s create method. It might look like:This assumes you are already doing any validation you need to do on your data.
Does that help at all?
Akbar
Hi,
Thanks for reply,
You mean to say like this.
I am getting this error :\
Paul Robinson
Hi,
Assuming those are the correct keys, yes. The error is my fault, I forgot you said you were new to PHP and I missed the semi-colon out on the end of the array, that is line 16 in your example code. I’ve added it to my original comment just in case anyone else tries to copy to code and doesn’t notice the error.
Also you need to pass the array you generate to
hostel_add::create()
so that the rows are added to the database. If you don’t you’ll just create an array but nothing will be done in the database.Akbar
Hi,
Yes, Thanks,
But not inserting the data, can you show me how to save the records.
Akbar
Paul Robinson
Hi,
As mentioned in my last reply, you just need to pass the array into
hostel_add::create()
and it should save.Just to note that
foreach
loops, multi-dimensional arrays and Classes are some things in PHP that you should learn about before you jump into a complicated Framework such as Laravel. Without having an understanding of those basics it can be hard to understand how Laravel works.I started out with a book by Apress way back but there are great guides on websites now. I would however recommend a book or a paid course on a website as self-teaching via tutorials can make you end up with bad habits.
Akbar
The below code is my controller which my masters teaching.
Please tell me clearly is this possible or not.
Code is:
Akbar
I need this part to below to insert multiple records.
public function create(){
if($this->data[‘users’]->role != “admin”) exit;
/*$bookLibrary = new hostel_add();
$bookLibrary->hostel_type = ‘Boys’; //Input::get(‘hostel_type’);
$bookLibrary->host_id = ‘1’; //Input::get(‘host_id’);
$bookLibrary->floor_name = Input::get(‘floor_name’);
$bookLibrary->room_no = Input::get(‘room_no’);
$bookLibrary->no_of_beds = Input::get(‘no_of_beds’);
$bookLibrary->amount_for = Input::get(‘amount_for’);
$bookLibrary->amount = Input::get(‘amount’);
$bookLibrary->save();*/
return $this->panelInit->apiOutput(true,$this->panelInit->language[‘gennotify’],$this->panelInit->language[‘genrecadd’],$bookLibrary->toArray() );
}
I am trying based on your suggestion but not inserting the records.
Akbar
Akbar
Hi,
Actually i got an assignment to make master detail forms like making invoice for every module.
Akbar
Akbar
Hi,
Please help me in this either give me any contact of good developer he can make invoice as per my system, i will pay if he want. Sorry to say this but i need very badly.
Akbar
Paul Robinson
Without any errors it is difficult to help, also please do not spam comments, I have to sleep and it was late when I replied to your previous message.
You need to create the array of arrays like I showed you previously, but I made a mistake and you need to use the insert method instead as Eloquent’s create method doesn’t accept a multidimensional array. Apologies. It’s been a little while since I’ve needed to do mass row insertions.
Code would be something like:
Again it may need tweaking. You will probably also need to include the
Illuminate\Support\Facades\DB;
namespace at the top of your file to allow you to use theDB
facadeThis assumes the data that is coming in is an array of records held in the
POST
superglobal under the keyrecord
. There are some many extra variables that could cause it to fail since I don’t know everything about your project.From the questions you are asking I would guess you have only just started learning PHP? If so I would strongly suggest learning more about basic PHP before continuing with Laravel.
Akbar
Hi,
I am getting this error below:
[2017-05-12 12:17:42] local.ERROR: exception ‘Symfony\Component\Debug\Exception\FatalErrorException’ with message ‘Undefined constant ‘Illuminate\Support\Facades\DB” in D:\wamp\www\ESMS\app\controllers\HosteladdController.php:2
Stack trace:
#0 [internal function]: Illuminate\Exception\Handler->handleShutdown()
#1 {main} [] []
[2017-05-12 12:17:42] local.ERROR: exception ‘Symfony\Component\Debug\Exception\FatalErrorException’ with message ‘Undefined constant ‘Illuminate\Support\Facades\DB” in D:\wamp\www\ESMS\app\controllers\HosteladdController.php:2
Stack trace:
#0 [internal function]: Illuminate\Exception\Handler->handleShutdown()
#1 {main} [] []
Akbar