如果用户等级不存在,则为下一个用户添加值的laravel迭代



我有一个函数,它将根据parent_id向用户插入一个金额,直到最后一个排名。我可以让parent_id达到最后一个等级,这很好,我正在使用iteration或类似recursion的东西。但如果用户排名不存在,我无法添加金额。

该函数的预期结果是向每个User Rank插入一个量,如果迭代/递归没有找到具有rank的用户,则将向其插入的量添加到下一个user rank

该函数将在用户购买product后触发,因此无论用户购买产品,都将获得他的parent_id,并插入分配给该级别的amount

我有一份in order级别的名单,谁将收到这笔金额。

Basic - 50
Junior - 100
Premium - 150
Advanced - 200
Senior - 250

数据库:

+------+------------+-------------+------------+
|  id  |  username  |  parent_id  |   rank     |
+------+------------+-------------+------------+
|  1   |   john     |    NULL     |  Senior    |
|  2   |   jane     |    1        |  Advanced  |
|  3   |   josh     |    2        |  Premium   |
|  4   |   joey     |    3        |  Junior    |
|  5   |   jade     |    4        |  Basic     |
------------------------------------------------

例如:

Jade买了一件商品,一旦订单成功,我会调用函数插入earnings

在这种情况下,Joey, Josh, Jane and John将基于其rank的相应金额来接收其收益。

在这种情况下,这很好,因为所有列都存在,但我的问题是,如果用户不在iteration中,则将amount设置为rank

例如,具有rank - JuniorJoey不在迭代中,指定给他的100的量将被添加到作为Premium的下一个rank上,并在下一个秩上进行收益插入,但阻止将amount添加到它们,因为如果具有该秩的用户不在迭代中将should only be added添加到下一个阶。

// successfully bought a product and saved to database
$user_id = 5; // jade
$parent_id = 4;

// call the function to insert the earnings
self::insertEarnings($user_id,$parent_id);

这是将插入收益的函数:

private function insertEarnings($user_id,$parent_id) {
if ($parent_id > 0) {

$user_parent = $parent_id;

$has_parent = true;

// start iteration
while($has_parent == true){

$account = User::where('id',$user_parent)->first();

$amount = 0;
if ($account->rank == "Junior" ) {

$amount = 100;

} elseif ($account->rank == "Premium") {
$amount = 150;
} elseif ($account->rank == "Advanced") {
$amount = 200;

} elseif ($account->rank == "Senior") {
$amount = 250;

// set to false to stop the iteration
$has_parent = false;
}
$earnings = new Earnings;
$earnings->user_id = $account->id;
$earnings->amount = $amount;
$earnings->save();

$next_parent = User::where('id',$user_parent)->first();
$user_parent = $next_parent->parent_id;
if($user_parent == 0){
$has_parent = false;
}
}
}
}

收入被插入到Joey、Josh、Jane和John,因为他们都在迭代中,真正的问题是,如果他不在迭代中的话,如何插入分配给排名的金额。

编辑:

有人帮我吗?我真的无法为这段代码制定解决方案。如果在迭代/循环中找不到排名,则将金额添加到下一个用户排名。

Jade订购了一个产品,让我们假设它是成功的。现在我将触发insertEarnings函数。我会得到他的parent_id,也就是Joey

Joey将获得100的金额,Josh, Jane and John他们将根据他们的等级获得金额。

主要问题是,如果有人在迭代/循环中是NOT,那么该rank的数量(无论该级别是什么)将被添加到下一个级别

阅读评论,我认为您现在的问题是,如果某个用户级别不存在,如何汇总金额?

我有一个逻辑可以通过使用这段代码来迭代排名。

public function insertEarnings()
{
// Rank Map
$ranks  = [[
'name' => 'Basic',
'point' => 50,
], [
'name' => 'Junior',
'point' => 100,
], [
'name' => 'Premium',
'point' => 150,
], [
'name' => 'Advanced',
'point' => 200,
], [
'name' => 'Senior',
'point' => 250,
]];
// Find Current Rank & Init Others
$current = array_search($this->rank, array_column($ranks, 'name'));
$rank    = null;
$user    = null;
$amount  = 0;
// Loop while next rank still exist
while (array_key_exists($current + 1, $ranks)) {
// Find next rank, user within that rank, and sum up the amount.
$rank   = $ranks[$current + 1];
$user   = User::where('rank', $rank['name'])->first();
$amount += $rank['point'];
// Add current to iterate trough ranks
$current++;
// If user is found save the earning and restart the amount to 0
if(!is_null($user)){
$earnings = new Earning;
$earnings->user_id = $user->id;
$earnings->amount = $amount;
$earnings->save();
$amount = 0;
}
}
}

使用该代码,我可以通过调用来获得下表所示的收益

$user->insertEarnings()//jane

+------+--------+----------+
|  id  |  name  |  amount  | 
+------+--------+----------+
|  1   |  josh  |  250     |
|  2   |  jane  |  200     |
|  3   |  john  |  250     |
----------------------------

这就是你想要实现的吗?

我真的不确定我是否理解你在这里想要做什么,但根据我的理解,如果购买物品的用户不在你的列表底部(在你的示例Jadeid=5中),你就有问题了。

因此,如果例如Josh将购买该物品,JoeyJade将错过他们的收入,因为它们在数据库中看起来更低。您在parent_id=2中使用Josh的父ID开始循环,并将指针设置到数据库中更靠前的下一个条目(代码中的逻辑在这里真的很混乱,可能需要进行一些清理甚至重新考虑)。

无论如何,如果您仍然想考虑所有其他候选项——在我们的示例JohnJaneJoeyJade中——您需要首先获取最后一个数据库条目,然后启动循环

private function insertEarnings($user_id, $parent_id) {
$mumEntries = User::where('id')->last() // not sure if this is the right syntax but you get the point! You want the highest possible user ID in the DB.
for ( $i=$numEntries; $i>=0; $i—- ) {

if ( $i !== $user_id ) { // skip the user who has purchased an item
$user = User::where(‘id’, $i) // again, only if this means ‘get user with id=$i’

// ... do logic with $amount

$earnings = new Earnings;
$earnings->user_id = $i;
$earnings->amount = $amount;
$earnings->save();
}
}
}

我现在还没有考虑到Laravel数据库对象的语法,但我希望这会有所帮助。

我花了30分钟试图理解你想要什么,但这里有一个改进的、更干净的功能供你使用:

public function insertEarnings($user_id) {
$ranks = [
'Basic' => 50,
'Junior' => 100,
'Premium' => 150,
'Advanced' => 200,
'Senior' => 250
];
$user = User::find($user_id);
if($user) {
//create earning for current user
if(array_key_exists($user->rank, $ranks)) {
$earnings = new Earnings();
$earnings->user_id = $user->id;
$earnings->amount  = $ranks[$user->rank];
$earnings->save();
}
if($user->parent_id != null) {
$this->insertEarnings($user->parent_id);
}
}
return false;
}

为了实现您想要做的事情,您需要编辑如何从数据库中删除用户。

这是软删除文档的链接。这可以应用于具有新迁移的现有数据库结构。请在投入生产前进行测试。https://laravel.com/docs/8.x/eloquent#soft-删除

一旦我们有了软删除,我们就可以修改插入收益函数。

// passed in the id of user that made a purchase
private function insertEarnings($user_id) {
$user = User::where('id',$user_id)->first();
if ($user->parent_id > 0) {

$next_parent_id = $user->parent_id;

$has_parent = true;
$amount = 0;

// start iteration
while($has_parent === true){

$parent = User::withTrashed()->where('id',$next_parent_id)->first();
if ($parent->rank == "Junior" ) {

$amount += 100;

} elseif ($parent->rank == "Premium") {
$amount += 150;
} elseif ($parent->rank == "Advanced") {
$amount += 200;

} elseif ($parent->rank == "Senior") {
$amount += 250;

// set to false to stop the iteration
$has_parent = false;
}
if (!$parent->trashed()) {
$earnings = new Earnings;
$earnings->user_id = $parent->id;
$earnings->amount = $amount;
$earnings->save();
$amount = 0;
}

$next_parent_id = $parent->parent_id;
if($user_parent_id === 0){
$has_parent = false;
}
}
}

我已经稍微清理了一下你的原始函数,但我想参考Konjesh Esbrading来获得一个更干净的例子。对我所做事情的解释。如果父母已从数据库中软删除,他们将不会获得收入,$amount也不会重置为0。下一个可用的家长将同时获得这两个金额。

由于迭代循环,在较大的数据库上可能需要一段时间,这可能会导致超时错误。为了防止这种情况发生,我建议您考虑使用队列和作业:https://laravel.com/docs/8.x/queues

在访问属性之前,您不会检查模型的存在。也许这是个问题。

private function insertEarnings($user_id,$parent_id) {
if ($parent = User::find($parent_id)) {

$has_parent = false;
// start iteration
while($has_parent){
$amount = 0;
if ($parent->rank === "Junior" ) {
$amount = 100;
} elseif ($parent->rank === "Premium") {
$amount = 150;
} elseif ($parent->rank === "Advanced") {
$amount = 200;
} elseif ($parent->rank == "Senior") {
$amount = 250;
// set to false to stop the iteration
$has_parent = false;
}
$earning = Earnings::create([
'user_id' => $parent->id,
'amount'  => $amount,
]);
if($parent->parent()->exists()){ // define hasOne() relation in model
$parent = $parent->parent;
} else {
$has_parent = false;
}
}
}
}

最新更新