如何将此Laravel PHP代码简化为一个雄辩的查询?
我假设这一切都应该在一个查询中,以防止数据库中出现重复数据。这是正确的吗 如何将此代码简化为一个雄辩的查询如何将此Laravel PHP代码简化为一个雄辩的查询?,php,mysql,database,laravel,eloquent,Php,Mysql,Database,Laravel,Eloquent,我假设这一切都应该在一个查询中,以防止数据库中出现重复数据。这是正确的吗 如何将此代码简化为一个雄辩的查询 $user = User::where( 'id', '=', $otherID )->first(); if( $user != null ) { if( $user->requestReceived() ) accept_friend( $otherID ); else if( !$user->requestSent() )
$user = User::where( 'id', '=', $otherID )->first();
if( $user != null )
{
if( $user->requestReceived() )
accept_friend( $otherID );
else if( !$user->requestSent() )
{
$friend = new Friend;
$friend->user_1= $myID;
$friend->user_2 = $otherID;
$friend->accepted = 0;
$friend->save();
}
}
您可以使用
firstOrCreate
/firstOrNew
方法()
示例(来自文档):
使用“firstOrCreate”它将执行与手动相同的操作 从Laravel手册中复制的Firstor或Create的定义 firstOrCreate方法将尝试使用给定的列/值对定位数据库记录。如果在数据库中找不到该模型,将插入具有给定属性的记录 因此,根据这一点,您应该尝试:
$user = User::where( 'id', '=', $otherID )->first();
$friend=Friend::firstOrCreate(['user_id' => $myId], ['user_2' => $otherId]);
如果不存在,它将检查两个ID,然后在friends表中创建记录。我想说,如果
用户
和朋友
之间存在关系,您可以简单地使用Laravel的模型关系,例如:
$status = User::find($id)->friends()->updateOrCreate(['user_id' => $id], $attributes_to_update));
这就是我要做的,以确保更新新数据或创建新数据
注:我仅在Laravel 5.2.*上使用了updateOrCreate()。另外,在更新之前对用户是否存在进行一些检查也会很好,否则可能会为null抛出一些错误
更新
我不知道该怎么办。你能再解释一下我该怎么做吗?$attributes\u to\u更新怎么样 好的。根据friends表中的哪些字段标记这两个朋友,现在使用您的示例
user_1
和user_2
。根据我给出的示例,$attributes\u to\u update
将是(假设otherID
是新朋友的id):
如果正确设置了User
和Friend
之间的关系,则User\u 1
将已包含在插入中
此外,在这个updateOrCreate函数上:
updateOrCreate($attributes_to_check, $attributes_to_update);
$attributes\u to\u check
意味着在创建/更新新字段之前,您要检查这些字段是否已经存在,因此如果我想确保在接受时进行检查为0
则我可以传递这两个字段,比如说“['user\u 1'=>1,'accepted'=>0]
希望现在情况更清楚
我假设这一切都应该在一个查询中,以防止
数据库中存在重复数据。这是正确的吗
这是不对的。您可以通过在数据库级别上放置unique
约束来防止重复
如果您的表上没有唯一的键,您可以在php或任何其他语言中做任何事情来防止重复。这是一个简单的事实,如果有人告诉你任何不同的事情,那人是大错特错的。我可以解释原因,但解释会很长,所以我将跳过它
您的代码应该非常简单-只需插入数据。由于不清楚如何处理唯一性(似乎是user_2,已被接受
,但存在一个边缘情况),如果您没有更多的数据,就不可能提出完整的解决方案
你总是可以忽略我写的内容,尝试使用建议的解决方案,但它们会失败得很惨,最终你会得到重复的解决方案。我假设这里的“朋友”代表了用户之间的多对多关系。显然,朋友请求是从一个用户(myID
)到另一个用户(otherId
)
你可以用雄辩的语言来表达:
class User extends Model
{
//...
public function friends()
{
return $this->belongsToMany(User::class, 'friends', 'myId', 'otherId')->withPivot('accepted');
}
}
也就是说,不需要Friend
模型
那么,我认为这相当于您想要实现的目标(如果没有,请更新并澄清):
(已接受
0或1,根据您的业务逻辑)
此sync
方法防止重复插入,并为给定的“myId-otherId”对更新或创建任何行。可以使用此方法在透视表中设置任意数量的其他字段
但是,我也同意在数据库级别设置唯一约束。对于此类问题,首先,如果您在laravel工作,您必须享受代码和数据库。首先,在数据库和模型中创建表friend
和user
之间的关系。您还必须在数据库中使用unique
$data= array('accepted' => 0);
User::find($otherID)->friends()->updateOrCreate(['user_id', $otherID], $data));
这是您可以使用的查询。也可以在这里传递多个条件。感谢重要的是要知道,first或create
会将信息持久化到数据库并返回实例,而first或new
只会返回实例而不持久化这就是为什么我会给出注释:)这与我做的不完全相同。您的解决方案不会防止重复。first或create
将涵盖根据给定的数组,您似乎不理解我想说的内容-不会的。您不能使用PHP或任何其他语言来保证唯一性。这不是处理数据库完整性的方法。$user->requestReceived()
在做什么?生成的SQL是什么?什么是“防止数据库中的重复数据”在确定“重复”的列上是否有一个唯一的索引?可能没有主题,但使用$user=user::find($otherID);而不是$user=user::where('id','=',$otherID)->first();这是否会生成INSERT。。。在重复密钥更新中…
?@RickJames否。它正在执行选择*。。。其中user_id=?
。如果未返回任何行-插入新行。否则,更新该行。False——一个单独的线程可能会滑入SELECT
和INSERT
之间,并自行执行INSERT
,从而把事情搞砸<代码>选择,如果,…
需要一个事务。@RickJames误读了我的评论?我没有写“不需要任何事务”。选择也可以在事务中,选择进行更新。否则,选择
class User extends Model
{
//...
public function friends()
{
return $this->belongsToMany(User::class, 'friends', 'myId', 'otherId')->withPivot('accepted');
}
}
$me = User::find($myId);
$me->friends()->syncWithoutDetaching([$otherId => ['accepted' => 0]]);
$data= array('accepted' => 0);
User::find($otherID)->friends()->updateOrCreate(['user_id', $otherID], $data));