Increment columns in laravel - php

Is there a way to increment more than one column in laravel?
Let's say:
DB::table('my_table')
->where('rowID', 1)
->increment('column1', 2)
->increment('column2', 10)
->increment('column3', 13)
->increment('column4', 5);
But this results to:
Call to a member function increment() on integer
I just want to find an efficient way to do this using the given functions from laravel. Thanks. Any suggestions will do.

There is no existing function to do this. You have to use update():
DB::table('my_table')
->where('rowID', 1)
->update([
'column1' => DB::raw('column1 + 2'),
'column2' => DB::raw('column2 + 10'),
'column3' => DB::raw('column3 + 13'),
'column4' => DB::raw('column4 + 5'),
]);

Increments and Decrements in Laravel Eloquent Model
Add to cart option is one of the most important functions in e-commerce websites. The tricky part is getting the number of items in the cart to display on the cart icon. The predominant approach to get this done is using the increment and decrement function on Laravel. This also facilitates the addition or removal of a product from your cart. The way to implement this function is ,
$user = User::find(‘517c43667db388101e00000f’);
$user->cart_count++;
// $user->cart_count--; // for decrement the count
$user->save()
An alternate and easier way is,
$user = User::find($article_id);
$user->increment('cart_count');
Also these will work:
$user->increment('cart_count');// increase one count
$user->decrement('cart_count'); // decrease one count
$user->increment('cart_count',10); // increase 10 count
$user->decrement('cart_count',10); // decrease 10 count

Now in laravel 5.7 laravel query builder, increment and decrement, it can be done easily.
Model::where('id', "rowID")->increment('columne1');`
or you can use DB
DB::table("my_table")->where('id', "rowID")->increment('column1');

For future reference in 5.2 it has been made do able by doing the following
You may also specify additional columns to update during the operation:
DB::table('users')->increment('votes', 1, ['name' => 'John']);
Source: https://laravel.com/docs/5.2/queries#updates

First off, the result of increment is an integer according to the documentation: http://laravel.com/api/4.2/Illuminate/Database/Query/Builder.html
So you would have to do a call for each increment:
DB::table('my_table')
->where('rowID', 1)
->increment('column1', 2);
DB::table('my_table')
->where('rowID', 1)
->increment('column2', 10);
DB::table('my_table')
->where('rowID', 1)
->increment('column3', 13);
DB::table('my_table')
->where('rowID', 1)
->increment('column4', 5);
I'm unable to find any quicker solution, unless you want to solve it with a raw update query command.
Also your example code will probably generate an error as you've closed the statement with ; and continue with a new ->increment call on the next line.

$id=5;
$votes=20;
DB::table('users')
->where('id', $id)
->update([
'votes' => DB::raw('votes + '.$votes)
]);

just use this code
\App\Models\User::find(1)->increment('column1'); //id = 1
or multi recorded
\App\Models\User::where('column1','>','100')->increment('column1');

In the latest version of 9.x, you can increment and decrement multiple columns using incrementEach and decrementEach methods:
DB::table('users')->incrementEach([
'votes' => 5,
'balance' => 100,
]);
(taken from the documentation)

Model::where('id', "rowID")->increment('columne1');
This works for me

Related

Using PHP Faker in Laravel to generate "unique with" entry when seeding a database using a factory

So Similar to the unique with validation rule (See: https://github.com/felixkiss/uniquewith-validator), I want to know how to generate a entry, where one column is unique with another one. I want to seed my database as follows.
Example:
There are 12 steps in the "steps" table. Each step should have 5 categories associated with each one that are stored in the "step_categories" table. Each of those categories are assigned a unique order number 1 through 5 that is unique with each "step_id".
See this image here for an example of what the database should look like: https://imgur.com/a/XYA5yyn
I had to manually to make the entries in the database for the above image example. I don't want to have to generate this manually every time, say I make a mistake and have to rollback the migrations for example.
I am using a factory to generate this data. So the factory name is StepCategoriesFactory.php and clearly I'm calling the factory with the create() method from the DatabaseSeeder.php file.
I thought about doing this in a for loop, then i got as far as realizing when i called the 'step_id' => App\Model::all()->random()->id to grab a new id, that I wouldn't be able to ensure I wasn't grabbing the id that i just generated 5 entries for. I'm really new with Laravel, and I'm not sure where to even start on this. There's no real information on SO where faker can use the unique with another column. How would I Go about this?
NOTE: The step id is not always going to be 1-12. The step ID might be different depending on whether a step gets deleted and remade. So just assigning the step_id to equal 1-12 wont work.
UPDATE: Here's some code I just wrote, and I think I'm on the right track. Maybe. I've grabbed the step_id by it's number field as that will always be 1-12, and I've grabbed the IID out of the entry. But now I'm stuck on how to generate the order 1-5 without repeating itself. I still haven't run this yet as its incomplete and I know it'll throw an error without the correct order number.
UPDATE 2: I think I'm on the right track here. However I'm getting an undefined variable error. When I put the first line from within the anonymous function, it's resetting the order to "1" for every entry. How do i make the $autoIncrement variable available to the anonymous function? The Seeder has stayed the same between updates.
Image of the error: https://imgur.com/a/ywkd0Lb
Second image with the Die/Dump error in terminal: https://imgur.com/a/rOGRv32
Reference this article here: https://laracasts.com/discuss/channels/laravel/model-factory-increment-value-faker?page=1
UPDATE 3: I forgot the use ($autoIncrement) line of code for the anonymous function. Code below has been updated, but now I'm getting a different error saying that the order column has a null value and can't be inserted. clearly it should be '1'. Even after I call my $autoIncrement->next(); which should increment it to '1' it's still returning null according to the terminal. However, when I do a diedump on $autoIncrement->current() it's returning 1. Weird.
Update 3 error: https://imgur.com/a/STOmIjF
StepCategoriesFactory.php
use Faker\Generator as Faker;
$autoIncrement = autoIncrement();
$factory->define(App\StepCategory::class, function (Faker $faker) use ($autoIncrement) {
// Generate Created At and Updated at DATETIME
$DateTime = $faker->dateTime($max = 'now');
$autoIncrement->next();
$order = (int) $autoIncrement->current();
return [
// Generate Dummy Data
'order' => $order,
'name' => $faker->words(4, true),
'created_at' => $DateTime,
'updated_at' => $DateTime,
];
});
function autoIncrement()
{
for ($i = 0; $i < 5; $i++) {
yield $i;
}
}
Edit: Put a bounty on this question, as I think it would be helpful for the community to get a detailed answer. I'm looking for help to explain how to go about making sure I'm grabbing the same entry through each loop.
FINALLY SOLVED!
So I took in everyone's answers, and thought long and hard about using a for loop to create the order number. 1-5. The problem that I was running into at the end was that the $i variable was not resetting. So after the yield I had to check if the $i variable equalled 5 and then reset it back to zero.
Heres the code!
StepCategories.php
use Faker\Generator as Faker;
$autoIncrement = autoIncrement();
$factory->define(App\StepCategory::class, function (Faker $faker) use ($autoIncrement) {
// Generate Created At and Updated at DATETIME
$DateTime = $faker->dateTime($max = 'now');
// Get the next iteration of the autoIncrement Function
$autoIncrement->next();
// Assign the current $i value to a typecast variable.
$order = (int) $autoIncrement->current();
return [
// Generate Dummy Data
'order' => $order,
'name' => $faker->words(4, true),
'created_at' => $DateTime,
'updated_at' => $DateTime,
];
});
function autoIncrement()
{
// Start a loop
for ($i = 0; $i <= 5; $i++) {
// Yield the current value of $i
yield $i;
// If $i is equal to 5, that must mean the start of a new loop
if($i == 5) {
// Reset $i to 0 to start over.
$i = 0;
}
}
}
DatabaseSeeder.php
// Generate Dummy Categories
// Run the factory 12 times
foreach(range(1, 12) as $i) {
// Generate 5 entries each time
factory(App\StepCategory::class, 5)->create([
// Since all steps have a number 1-12 grab the step by the number column and get it's ID
'step_id' => App\Step::where('number', '=', $i)->first()->id,
]);
}
Thanks to all who helped!
Sorry if you don't understand my point so I'll try to explain it in code
use Illuminate\Database\Seeder;
$factory->define(App\StepCategory::class, function (Faker $faker) {
// Generate Created At and Updated at DATETIME
$DateTime = $faker->dateTime($max = 'now');
$step_id = function () {
return factory('App\Step')->create()->id;
};
return [
// Generate Dummy Data
'step_id' => $step_id,
'order' => uniqueOrder($step_id),
'name' => $faker->words(4, true),
'created_at' => $DateTime,
'updated_at' => $DateTime,
];
});
function uniqueOrder($step_id)
{
$unique = rand(1,5);
do {
$unique = rand(1,5);
}
while(StepCategory::where('step_id', $step_id)->andWhere( 'order', $unique)->exists())
return $unique;
}
for example if your Step model name is Steps :
$allSteps = Steps::all();
foreach($allSteps as $step){
for($i=1;$i<6;$i++){
//insert to table $step->id , $i for example
DB::table('yourTableName')->insert([
'name'=>'Step '.$step->id.'- Category '.$i ,
'order'=>$i ,
'step_id'=>$step->id
]);
}
}

How to select the last row from database in laravel [duplicate]

This question already has answers here:
Select Last Row in the Table
(22 answers)
Closed 4 years ago.
public function addNewPost(Request $request)/****ADD new POST****/
{
$this->validate($request,['post_title'=>'required|min:4|max:100',
'post_description'=>'required|min:20|max:500'
]);
$user_name = Session::get('name');
$post_title = $request->input('post_title');
$post_description = $request->input('post_description');
$addPost = new AddNewPost(['user_name'=> $user_name, 'post_title'=> $post_title, 'post_description'=> $post_description]);
$addPost->save();
$addPost->post_id;
//$addPost = DB::table('userposts')->where(['user_name'=>$user_name ])->orderBy('post_id', 'desc')->get();
print_r($addAdmin->post_id); //This is printing nothing, i.e. blank.
}
post_id column in userposts table is auto incremented. I am trying to get the last post id of the user by user_name. I have seen some tutorials and also checked some questions over internet but unable to do what I am trying to get. Can anybody know how to do it. Thank you.
Try first() instead of get() in a query it might help you
$lastdata = DB::table('userposts')->where(['user_name'=>$user_name ])->orderBy('post_id', 'desc')->first();
print_r($lastdata);
Laravel has the last() method that you can use.
This is from the docs:
last()
The last method returns the last element in the collection that passes a given truth test:
collect([1, 2, 3, 4])->last(function ($value, $key) {
return $value < 3;
});
// returns 2
You may also call the last method with no arguments to get the last element in the collection. If the collection is empty, null is returned:
collect([1, 2, 3, 4])->last();
//returns 4
Here is the example for getting only the last id:
Model::pluck('id')->last();
DB::table('userposts')->last()->pluck('user_name') Is the fastest way .
Make sure to apply last() first to avoid unnecessary workload
Simple method which will not takes much processing is
DB::getPdo()->lastInsertId();
Hope this helps
You can also try
$addPost = new AddNewPost(['user_name'=> $user_name, 'post_title'=> $post_title, 'post_description'=> $post_description]);
$addPost->save();
$addPost->update();
print_r($addPost->post_id); //It will print id..
P.S second method is kind of redundant
Hope this helps
Please have a closer look at your print statement:
print_r($addAdmin->post_id);
The $addAdmin is not defined within the scope of your function. The best way to get the last row from your database:
DB::table('name_of_table')->last()->pluck('user_name')
Here is the documentation on using DB: https://laravel.com/docs/5.6/database

Laravel 5.5 get multiple records which are recently updated

I am displaying multiple records which changed recently. In previous view there is a button that when I click, all records' kitchen_status becomes 1 from 0. After that if I add more records and change its kitchen_status to 1, then I only want to display latest records which has kitchen_status as 1. Here is what I had tried to get:
$orders = Order::where([
'kitchen_status' => 1,
'delivery_status' => 0,
])
->where('updated_at', \DB::raw("(select max(`updated_at`) from orders)"))
->get();
This works good, but when I add new record that kitchen_status with default value of 0, then none records display. I know that last ->where() is wrong but how can I make it right?
In short, I want to display all records with latest updated_at. Some little help will save my day.
I think this can help.
$orders = Order::where([
'kitchen_status' => 1,
'delivery_status' => 0,])->orderBy('update_at','DESC')->paginate(15);
I had tried this code and it works perfect but still I am looking short and pure method. Here is code that I found:
$orders = Order::select('orders.*')
->where('kitchen_status', 1)
->where('delivery_status', 0)
->where('updated_at', \DB::raw("(SELECT max(updated_at) FROM orders WHERE kitchen_status = 1 AND delivery_status = 0)"))
->get();
Is it good to check this answer as right answer or please add more answer.
You can limit the number of the most recent entries you want as
$orders = Order::where([
'kitchen_status' => 1,
'delivery_status' => 0,
])->orderBy('updated_at','DESC')->limit(20)
->get();
You can change the number to what you want.
I am not sure I understand the question 100% But I think what you are looking for is
Model::whereDate('updated_at', '>', \Carbon::now()->subHours(2));
Which will give you all the records where updated_at is older than 2 hours. The parameter can be changed to something else like 10 for hours etc, there is also a subDays(), subMonths() etc, if you need a bigger range.

laravel 4: how to subtract one from current value of column when updating rows?

I was wondering how to perform something like this:
Table::update(array('position'=>'position+1'));
As far as I know, laravel 4 handles 'position+1' as a string, thus is becomes 0.
I want to perform something like
UPDATE table SET position = position + 1
Can I do that using eloquent?
EDIT: nevermind, doh.."DB::table('users')->increment('votes');"
Simply make use of the increment method:
DB::table('users')->increment('position');
The same is valid for decrement:
DB::table('users')->decrement('rank');
You may even set the second parameter to the amount you want to add/subtract:
DB::table('users')->increment('posts', 5);
DB::table('users')->decrement('likes', 3);
Also, if you need to update other columns along with it, you pass it as the third parameter:
DB::table('users')->increment('range', 3, array(
'name' => 'Raphael',
'rank' => 10
));
And the same goes for Eloquent models, as well:
$firstUser = User::find(1);
$firstUser->increment('height', 0.1, array(
'active' => false
));
you can also do with DB::raw method like this:
DB::table('tablename')->where(your condition)->update(['position' => DB::raw('position+1')]);
you can also do other operations with this like
DB::table('tablename')->where(your condition)->update(['position' => DB::raw('position * 2')]);
This worked fine for me
\Models\User::where("id", $userId)->increment("points");
simply you can use the DB::raw method like this:
Table::update(DB::raw('position=position+1'));

Stripe API: List all Charges

I am using https://stripe.com/docs/api?lang=php#list_charges to get List all Charges but here they specify
count optional — default is 10 A limit on the number of objects to be
returned. Count can range between 1 and 100 items.
and I have thousands of entries, now how can I get all. Though if I set count to 100 it returns 110 records.
You can use the offset argument.
Once you get the 100 transactions, then make another call by adding offset=100 in URL.
This will bring the next 100 transactions, then make offset=200 and so on.
Update:
offset parameter is partly deprecated: API changelog - 2015-09-23
$charges = \Stripe\Charge::all();
foreach ($charges->autoPagingIterator() as $charge) {
// Do something with $charge
}
Reference.
Yes I got it with offset we can get all records.
Here's a PHP example: \Stripe\Charge::all(array("limit" => 3, "offset" => 10));
A Ruby example:
Stripe::Charge.all(limit: 3, offset:3)
As good as the Stripe API docs are, they could be clearer on how to filter.
source: https://stripe.com/docs/api/php#list_charges, https://stripe.com/docs/api/ruby#list_charges
in case offset is deprecated
$result = [];
$created_at = strtotime($request->end_data);
//created_at should be today's date epoch. search google for epoch
$has_more = false;
$a = 0;
do{
print_r($a);
\Stripe\Stripe::setApiKey(env('STRIPE_SECRET'));
$temp = \Stripe\BalanceTransaction::all( array(
'limit' => 100,
'created' => array(
'lte' => $created_at,
)
));
$result = array_merge($temp->data,$result);
$created_at = $temp->data[99]->created_at;
//api returns a parameter has_more(boolean), which means there is more
//data or not so you can also put that in while condition, for ex.
// $has_more = $temp->has_more;
$a++;
}while($a < 5);
dd($result);
this worked for me i was able to get 500 records at once as $a < 5 the api hits 5 times and each time created parameter which is lte (less than equal) changes for each api request and return previous records than current request provide. also i am appending the result of each api call to another result array
Unfortunately you can't.
I can see where such a feature would be nice for accounting purposes or whatever, but it's generally a better user experience to implement some sort of paging when displaying copious amounts of data to the user.
If you need absolute control over how many records to display at a time, I would suggest setting up a webhook on the charge.succeeded event and store your charges locally.

Categories