Reputation: 107
I get 20 rows using Laravel Eloquent Model, with the following code, I want to mark them as locked after getting them and then mark them as unlocked after finish the work with them. But the article_unlock update to 0 is not being executed.
$articles_object = Article::where('article_posted', '=', 0)->where('article_lock', '=', 0)->take(20);
$articles_object->update(array('article_lock' => 1));
$articles = $articles_object->get();
foreach($articles as $article)
{
\\ do the work
}
$articles_object->update(array('article_lock' => 0));
Upvotes: 2
Views: 1152
Reputation: 26467
This happens because you're reusing a builder object, not a data set.
Effectively what happens is your Builder ($articles_object
) creates the basis of a query.
When you run the update method on this Builder object it creates and runs the query.
UPDATE `articles`
SET `article_lock` = 1
WHERE `article_posted` = 0
AND `article_lock` = 0
LIMIT 20
This sets the lock flag to 1 on the 20 rows (because of take()
)
The Builder object is still a Builder object even after you ran this query and has no concept of the rows it originally ran the update on. It's not a collection like you'd get from get()
.
What this means is when you execute the second call to update()
the exact same query as above runs.
The difference here is that your where clause is WHERE article_lock = 0
meaning that it will never find the same rows as previously, because you've just set article_lock to 1 on them.
You'd need to keep track of the Ids you'd just locked, perhaps similarly to the below, and then run a query on those records specifically to zero your lock flag.
$lockedIds = [];
foreach($articles as $article)
{
\\ do the work
$lockedIds[] = $article->id;
}
Articles::whereIn('id', $lockedIds)->update(['article_lock' => 0]);
Upvotes: 4