如何将这个Laravel PHP代码简化为一个Eloquent查询?

时间:2022-10-25 07:48:01

I assume that this should all be in one query in order to prevent duplicate data in the database. Is this correct?

我假设这应该都在一个查询中,以防止数据库中的重复数据。它是否正确?

How do I simplify this code into one Eloquent query?

如何将此代码简化为一个Eloquent查询?

$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();
    }
}

6 个解决方案

#1


8  

I assume that this should all be in one query in order to prevent duplicate data in the database. Is this correct?

我假设这应该都在一个查询中,以防止数据库中的重复数据。它是否正确?

It's not correct. You prevent duplication by placing unique constraints on database level.

这不对。通过在数据库级别放置唯一约束来防止重复。

There's literally nothing you can do in php or any other language for that matter, that will prevent duplicates, if you don't have unique keys on your table(s). That's a simple fact, and if anyone tells you anything different - that person is blatantly wrong. I can explain why, but the explanation would be a lengthy one so I'll skip it.

如果您的桌子上没有唯一的密钥,那么在PHP或任何其他语言中你几乎无法做任何事情,这将防止重复。这是一个简单的事实,如果有人告诉你任何不同的事情 - 那个人是公然错误的。我可以解释原因,但解释会很冗长,所以我会跳过它。

Your code should be quite simple - just insert the data. Since it's not exactly clear how uniqueness is handled (it appears to be user_2, accepted, but there's an edge case), without a bit more data form you - it's not possible to suggest a complete solution.

您的代码应该非常简单 - 只需插入数据即可。由于不清楚如何处理唯一性(它似乎是user_2,被接受,但是有一个边缘情况),没有更多的数据形式 - 你不可能建议一个完整的解决方案。

You can always disregard what I wrote and try to go with suggested solutions, but they will fail miserably and you'll end up with duplicates.

你可以随时忽略我写的内容并尝试使用建议的解决方案,但是它们会失败并且你最终会重复。

#2


8  

I would say if there is a relationship between User and Friend you can simply employ Laravel's model relationship, such as:

我想说如果用户和朋友之间存在关系,您可以简单地使用Laravel的模型关系,例如:

$status = User::find($id)->friends()->updateOrCreate(['user_id' => $id], $attributes_to_update));

Thats what I would do to ensure that the new data is updated or a new one is created.

多数民众赞成我将采取哪些措施来确保更新新数据或创建新数据。

PS: I have used updateOrCreate() on Laravel 5.2.* only. And also it would be nice to actually do some check on user existence before updating else some errors might be thrown for null.

PS:我在Laravel 5.2上使用了updateOrCreate()。*。并且在更新之前实际上对用户存在进行一些检查会很好,否则可能会抛出一些错误。

UPDATE

UPDATE

I'm not sure what to do. Could you explain a bit more what I should do? What about $attributes_to_update ?

我不知道该怎么做。你能解释一下我应该做些什么吗? $ attributes_to_update怎么样?

Okay. Depending on what fields in the friends table marks the two friends, now using your example user_1 and user_2. By the example I gave, the $attributes_to_update would be (assuming otherID is the new friend's id):

好的。根据friends表中的哪些字段标记这两个朋友,现在使用您的示例user_1和user_2。通过我给出的示例,$ attributes_to_update将是(假设otherID是新朋友的id):

$attributes_to_update = ['user_2' => otherID, 'accepted' => 0 ];

If your relationship between User and Friend is set properly, then the user_1 would already included in the insertion.

如果您正确设置了User和Friend之间的关系,那么user_1已经包含在插入中。

Furthermore,on this updateOrCreate function:

此外,在此updateOrCreate函数上:

updateOrCreate($attributes_to_check, $attributes_to_update);

$attributes_to_check would mean those fields you want to check if they already exists before you create/update new one so if I want to ensure, the check is made when accepted is 0 then I can pass both say `['user_1' => 1, 'accepted' => 0]

$ attributes_to_check意味着你要在创建/更新新字段之前检查它们是否已经存在,所以如果我想确保,当接受为0时进行检查然后我可以传递两个说'['user_1'=> 1 ,'接受'=> 0]

Hope this is clearer now.

希望现在更清楚了。

#3


5  

I'm assuming "friends" here represents a many-to-many relation between users. Apparently friend requests from one user (myID) to another (otherId).

我假设“朋友”在这里表示用户之间的多对多关系。显然是朋友请求从一个用户(myID)到另一个用户(otherId)。

You can represent that with Eloquent as:

你可以用Eloquent表示:

class User extends Model
{
    //...

    public function friends()
    {
        return $this->belongsToMany(User::class, 'friends', 'myId', 'otherId')->withPivot('accepted');
    }
}

That is, no need for Friend model.

也就是说,不需要Friend模型。

Then, I think this is equivalent to what you want to accomplish (if not, please update with clarification):

然后,我认为这相当于你想要完成的事情(如果没有,请更新澄清):

$me = User::find($myId);

$me->friends()->syncWithoutDetaching([$otherId => ['accepted' => 0]]);

(accepted 0 or 1, according to your business logic).

(根据您的业务逻辑,接受0或1)。

This sync method prevents duplicate inserts, and updates or creates any row for the given pair of "myId - otherId". You can set any number of additional fields in the pivot table with this method.

此同步方法可防止重复插入,并为给定的“myId - otherId”对更新或创建任何行。您可以使用此方法在数据透视表中设置任意数量的其他字段。

However, I agree with @Mjh about setting unique constraints at database level as well.

但是,我同意@Mjh关于在数据库级别设置唯一约束。

#4


4  

For this kind of issue, First of all, you have to enjoy the code and database if you are working in laravel. For this first you create realtionship between both table friend and user in database as well as in Models . Also you have to use unique in database .

对于这类问题,首先,如果你在laravel工作,你必须享受代码和数据库。首先,您在数据库和模型中创建表朋友和用户之间的关系。此外,您必须在数据库中使用唯一。

$data= array('accepted' => 0);
User::find($otherID)->friends()->updateOrCreate(['user_id', $otherID], $data));

This is query you can work with this . Also you can pass multiple condition here. Thanks

这是您可以使用此查询的查询。你也可以在这里传递多个条件。谢谢

#5


-3  

You can use firstOrCreate/ firstOrNew methods (https://laravel.com/docs/5.3/eloquent)

您可以使用firstOrCreate / firstOrNew方法(https://laravel.com/docs/5.3/eloquent)

Example (from docs) :

示例(来自docs):

// Retrieve the flight by the attributes, or create it if it doesn't exist...
$flight = App\Flight::firstOrCreate(['name' => 'Flight 10']);

// Retrieve the flight by the attributes, or instantiate a new instance...
$flight = App\Flight::firstOrNew(['name' => 'Flight 10']);

#6


-3  

use `firstOrCreate' it will do same as you did manually.

使用`firstOrCreate'它会像你手动一样。

Definition of FirstOrCreate copied from the Laravel Manual.

从Laravel手册复制的FirstOrCreate的定义。

The firstOrCreate method will attempt to locate a database record using the given column / value pairs. If the model can not be found in the database, a record will be inserted with the given attributes.

firstOrCreate方法将尝试使用给定的列/值对定位数据库记录。如果在数据库中找不到该模型,则将插入具有给定属性的记录。

So according to that you should try :

所以根据你应该尝试:

$user = User::where( 'id', '=', $otherID )->first();
$friend=Friend::firstOrCreate(['user_id' => $myId], ['user_2' => $otherId]);    

It will check with both IDs if not exists then create record in friends table.

如果不存在,它将检查两个ID,然后在friends表中创建记录。

#1


8  

I assume that this should all be in one query in order to prevent duplicate data in the database. Is this correct?

我假设这应该都在一个查询中,以防止数据库中的重复数据。它是否正确?

It's not correct. You prevent duplication by placing unique constraints on database level.

这不对。通过在数据库级别放置唯一约束来防止重复。

There's literally nothing you can do in php or any other language for that matter, that will prevent duplicates, if you don't have unique keys on your table(s). That's a simple fact, and if anyone tells you anything different - that person is blatantly wrong. I can explain why, but the explanation would be a lengthy one so I'll skip it.

如果您的桌子上没有唯一的密钥,那么在PHP或任何其他语言中你几乎无法做任何事情,这将防止重复。这是一个简单的事实,如果有人告诉你任何不同的事情 - 那个人是公然错误的。我可以解释原因,但解释会很冗长,所以我会跳过它。

Your code should be quite simple - just insert the data. Since it's not exactly clear how uniqueness is handled (it appears to be user_2, accepted, but there's an edge case), without a bit more data form you - it's not possible to suggest a complete solution.

您的代码应该非常简单 - 只需插入数据即可。由于不清楚如何处理唯一性(它似乎是user_2,被接受,但是有一个边缘情况),没有更多的数据形式 - 你不可能建议一个完整的解决方案。

You can always disregard what I wrote and try to go with suggested solutions, but they will fail miserably and you'll end up with duplicates.

你可以随时忽略我写的内容并尝试使用建议的解决方案,但是它们会失败并且你最终会重复。

#2


8  

I would say if there is a relationship between User and Friend you can simply employ Laravel's model relationship, such as:

我想说如果用户和朋友之间存在关系,您可以简单地使用Laravel的模型关系,例如:

$status = User::find($id)->friends()->updateOrCreate(['user_id' => $id], $attributes_to_update));

Thats what I would do to ensure that the new data is updated or a new one is created.

多数民众赞成我将采取哪些措施来确保更新新数据或创建新数据。

PS: I have used updateOrCreate() on Laravel 5.2.* only. And also it would be nice to actually do some check on user existence before updating else some errors might be thrown for null.

PS:我在Laravel 5.2上使用了updateOrCreate()。*。并且在更新之前实际上对用户存在进行一些检查会很好,否则可能会抛出一些错误。

UPDATE

UPDATE

I'm not sure what to do. Could you explain a bit more what I should do? What about $attributes_to_update ?

我不知道该怎么做。你能解释一下我应该做些什么吗? $ attributes_to_update怎么样?

Okay. Depending on what fields in the friends table marks the two friends, now using your example user_1 and user_2. By the example I gave, the $attributes_to_update would be (assuming otherID is the new friend's id):

好的。根据friends表中的哪些字段标记这两个朋友,现在使用您的示例user_1和user_2。通过我给出的示例,$ attributes_to_update将是(假设otherID是新朋友的id):

$attributes_to_update = ['user_2' => otherID, 'accepted' => 0 ];

If your relationship between User and Friend is set properly, then the user_1 would already included in the insertion.

如果您正确设置了User和Friend之间的关系,那么user_1已经包含在插入中。

Furthermore,on this updateOrCreate function:

此外,在此updateOrCreate函数上:

updateOrCreate($attributes_to_check, $attributes_to_update);

$attributes_to_check would mean those fields you want to check if they already exists before you create/update new one so if I want to ensure, the check is made when accepted is 0 then I can pass both say `['user_1' => 1, 'accepted' => 0]

$ attributes_to_check意味着你要在创建/更新新字段之前检查它们是否已经存在,所以如果我想确保,当接受为0时进行检查然后我可以传递两个说'['user_1'=> 1 ,'接受'=> 0]

Hope this is clearer now.

希望现在更清楚了。

#3


5  

I'm assuming "friends" here represents a many-to-many relation between users. Apparently friend requests from one user (myID) to another (otherId).

我假设“朋友”在这里表示用户之间的多对多关系。显然是朋友请求从一个用户(myID)到另一个用户(otherId)。

You can represent that with Eloquent as:

你可以用Eloquent表示:

class User extends Model
{
    //...

    public function friends()
    {
        return $this->belongsToMany(User::class, 'friends', 'myId', 'otherId')->withPivot('accepted');
    }
}

That is, no need for Friend model.

也就是说,不需要Friend模型。

Then, I think this is equivalent to what you want to accomplish (if not, please update with clarification):

然后,我认为这相当于你想要完成的事情(如果没有,请更新澄清):

$me = User::find($myId);

$me->friends()->syncWithoutDetaching([$otherId => ['accepted' => 0]]);

(accepted 0 or 1, according to your business logic).

(根据您的业务逻辑,接受0或1)。

This sync method prevents duplicate inserts, and updates or creates any row for the given pair of "myId - otherId". You can set any number of additional fields in the pivot table with this method.

此同步方法可防止重复插入,并为给定的“myId - otherId”对更新或创建任何行。您可以使用此方法在数据透视表中设置任意数量的其他字段。

However, I agree with @Mjh about setting unique constraints at database level as well.

但是,我同意@Mjh关于在数据库级别设置唯一约束。

#4


4  

For this kind of issue, First of all, you have to enjoy the code and database if you are working in laravel. For this first you create realtionship between both table friend and user in database as well as in Models . Also you have to use unique in database .

对于这类问题,首先,如果你在laravel工作,你必须享受代码和数据库。首先,您在数据库和模型中创建表朋友和用户之间的关系。此外,您必须在数据库中使用唯一。

$data= array('accepted' => 0);
User::find($otherID)->friends()->updateOrCreate(['user_id', $otherID], $data));

This is query you can work with this . Also you can pass multiple condition here. Thanks

这是您可以使用此查询的查询。你也可以在这里传递多个条件。谢谢

#5


-3  

You can use firstOrCreate/ firstOrNew methods (https://laravel.com/docs/5.3/eloquent)

您可以使用firstOrCreate / firstOrNew方法(https://laravel.com/docs/5.3/eloquent)

Example (from docs) :

示例(来自docs):

// Retrieve the flight by the attributes, or create it if it doesn't exist...
$flight = App\Flight::firstOrCreate(['name' => 'Flight 10']);

// Retrieve the flight by the attributes, or instantiate a new instance...
$flight = App\Flight::firstOrNew(['name' => 'Flight 10']);

#6


-3  

use `firstOrCreate' it will do same as you did manually.

使用`firstOrCreate'它会像你手动一样。

Definition of FirstOrCreate copied from the Laravel Manual.

从Laravel手册复制的FirstOrCreate的定义。

The firstOrCreate method will attempt to locate a database record using the given column / value pairs. If the model can not be found in the database, a record will be inserted with the given attributes.

firstOrCreate方法将尝试使用给定的列/值对定位数据库记录。如果在数据库中找不到该模型,则将插入具有给定属性的记录。

So according to that you should try :

所以根据你应该尝试:

$user = User::where( 'id', '=', $otherID )->first();
$friend=Friend::firstOrCreate(['user_id' => $myId], ['user_2' => $otherId]);    

It will check with both IDs if not exists then create record in friends table.

如果不存在,它将检查两个ID,然后在friends表中创建记录。