I want to prevent data duplicate in database when user applies a job post multiple times.
I tried firstOrNew() like...
$apply = Applies::firstOrNew(
['user_id' => Auth::id()],
['posts_id' => request('id')]);
$apply->save();
But this time user can't apply other posts anymore .
Edit 1
I tried it but doesn't do anything.
$apply = Applies::firstOrNew(
['user_id' => Auth::id()] && ['posts_id' => request('id')],
['user_id' => request(Auth::id())],
['posts_id' => request('id')]);
$apply->save();
The first array is the "attributes", the where conditions for the look up. You would need to have the user_id and post_id in that array:
Applies::firstOrNew([
'user_id' => ...,
'post_id' => ...,
]);
This will cause it to search for that combination and only if it can't find it will it create a new (non-existing) model instance and fill it with those "attributes".
Related
I have a table that has a column called "items", but not all rows have it, so I want to scan all rows that have "items".
Something like:
$resposta = $clientDB->scan(array(
'TableName' => 'tableName',
'Key' => [
'items' => ['S' => 'exists']
]
));
But I can't figure out how to do it...
The table has 10000 rows, but only 10 of them have "items", and I want to get only these 10 rows.
Edit:
As Seth Geoghegan pointed below, it was necessary create a global secondary indexes on the attribute i wanted to filter.
I ended up here:
$params = [
'TableName' => 'tableName',
'FilterExpression' => "attribute_exists(items)"
];
OR
$params = [
'TableName' => 'tableName',
'FilterExpression' => 'items != :null',
'ExpressionAttributeValues' => [
':null' => null,
],
];
But both didnt worked... First one seens necessary ExpressionAttributeValues to be setup and the second the php stop working with no error logs.
This is a perfect use case for global secondary indexes (GSI)!
You can create a GSI on the items attribute. Items with the items attribute defined will get projected into the GSI. Importantly, items that do not contain this attribute will not be in the index. You could then query the GSI and retrieve the items you're after.
Well, after some effort, i found a way though:
$resposta = $clientDB->scan(array(
'TableName' => 'tableName',
'FilterExpression' => "attribute_exists(items)"
));
After i created another global secondary index (GSI) for "items" (pointed by Seth Geoghegan), i just needed to add in the scan function the FilterExpression the "attribute_exists(items") and it worked.
I want to insert multiple rows in a table, where the data collection I am inserting has a unique number. For example : I am inserting 2 row for a user_id number 1. My codes from controller is : I want to keep DB::table() instead of laravel eloquent
foreach($post_data['user_id'] as $key => $no){
$set_base = DB::table('package_user')
->Insert([
'base_id' => $post_data['base_id'],
'base_title' => $post_data['base_title'],
'user_id' => $no,
'package_id' => $post_data['package_id'],
'plan_id' => $post_data['plan_id'],
'currency' => $post_data['currency'],
'payable_plan_amount' => $post_data['total_amount'],
'created_at' => Carbon::now()
]);
}
Please refer How to insert multiple rows from a single query using eloquent/fluent there is a solution for both eloquent and querybuilder
$data = [
['user_id'=>'Coder 1', 'subject_id'=> 4096],
['user_id'=>'Coder 2', 'subject_id'=> 2048],
];
Model::insert($data); // Eloquent approach
DB::table('table')->insert($data); // Query Builder approach
You can also use fill() method if the model instance already created with the pre-defined populated datas.
<code>
$modelObj = new Model();
$modelCollection = collect($request->input())->all();
$modelObj->fill($modelCollection);
$modelObj->save();
</code>
I know the Question title is a bit murky, but here's what I'm trying to do:
I'm retrieving a list of groups that a user belongs to from a third party api. In some cases, the user will be an 'admin' for a group and other times, just a 'member'.
Specifics aside, I'm calling a method on my api class from my controller that hits the api, retrieves the user's groups, decides if they are an 'admin' or not, then returns an array of arrays with each group's information including a 'role' key that denotes whether or not they are an 'admin'. So my returned array looks something like this:
[
0 => [
'unique_id' => 1243657,
'name' => 'Group1',
'city' => 'Bluesville',
'state' => 'IN',
'role' => 'admin'
],
1 => [
'unique_id' => 4324567,
'name' => 'Group2',
'city' => 'New Curtsbourough',
'state' => 'WI',
'role' => 'member'
],
2=> [
'unique_id' => 87463652,
'name' => 'Group3',
'city' => 'Samsonite',
'state' => 'MN',
'role' => 'member'
]
]
Now, I need to take those groups and store them in the database, which I'm doing by checking first that the group doesn't exist in the database, then adding it if needed. Of course, I'm leaving off the role, as it is only relevant to the current user.
Next, I need to connect the current user to these groups that were just retrieved. I have a pivot table set up that currently holds the user_id and group_id.
The question is, how to best handle this. Before I decided that I needed to know whether or not a member was an 'admin' or not, I simply had my 'createGroups' method return an array of primary keys to me, then passed that array to a call to
$user->groups()->sync($array_of_ids);
However, with the added 'role' information, it's not as cut and dry.
Basically, at this point in the lifecycle, I have access to an array of groups that contains a field 'role'. My thinking says to add a 'role' field to the pivot table, which would then contain 'user_id', 'group_id' and 'role'. This means I'll not only need the $groups array with the retrieved groups, but the ids of those groups as they pertain to my database.
I could make something work, but I'm afraid it would be extremely messy and inefficient.
Thoughts anyone??
Ok, as happens many times on Stackoverflow, I've come to a solution for my own question. I'm posting so that in the off-chance someone stumbles upon my question needing to do something similar, they can at least see how one person handled it.
According to the Laravel docs, if you want to sync relationships with an added column, you need to call sync in the following way:
$user->groups()->sync([
1 => ['role' => 'admin'],
2 => ['role' => 'member'],
3 => ['role' => 'member']
]);
So before I could sync, I needed an array that resembled the array that is being passed to 'sync'.
Since I had an array of 'groups' that included a field called 'role' for each group, I created a 'createGroups' method that basically looped over the $groups array and called the 'insertGetId' method that Laravel provides. This method persists the object to the database and returns the primary key of the created record. For my 'createGroups' method, I did the following:
public function createGroups($groups)
{
$added = array();
foreach($groups as $group){
$id = $this->createGroup($group);
$added[$id] = ['role' => $group['role']];
}
return $added;
}
So as I'm inserting 'groups' into the database, I'm building up the array that is needed by the 'sync' method. Since the 'createGroup' method uses Laravel's 'insertGetId' method, it returns the primary key for that group. Then I use that id as the key to the array. After all groups are inserted, my 'added' array that is returned to my controller, looks like this:
[
1 => ['role' => 'admin'],
2 => ['role' => 'member'],
3 => ['role' => 'member']
]
which is exactly what the 'sync' method needs to do it's thing.
Happy coding!
I'm having trouble composing a CakePHP find() which returns the records I'm looking for.
My associations go like this:
User ->(has many)-> Friends ,
User ->(has many)-> Posts
I'm trying to display a list of all a user's friends recent posts, in other words, list every post that was created by a friend of the current user logged in.
The only way I can think of doing this is by putting all the user's friends' user_ids in a big array, and then looping through each one, so that the find() call would look something like:
$posts = $this->Post->find('all',array(
'conditions' => array(
'Post.user_id' => array(
'OR' => array(
$user_id_array[0],$user_id_array[1],$user_id_array[2] # .. etc
)
)
)
));
I get the impression this isn't the best way of doing things as if that user is popular that's a lot of OR conditions. Can anyone suggest a better alternative?
To clarify, here is a simplified version of my database:
"Users" table
id
username
etc
"Friends" table
id
user_id
friend_id
etc
"Posts" table
id
user_id
etc
After reviewing what you have rewritten, I think I understand what you are doing. Your current structure will not work. There is no reference in POSTS to friends. So based on the schema you have posted, friends CANNOT add any POSTS. I think what you are trying to do is reference a friend as one of the other users. Meaning, A users FRIEND is actually just another USER in the USERS table. This is a self referential HABTM relationship. So here is what I would propose:
1- First, make sure you have the HABTM table created in the DB:
-- MySQL CREATE TABLE users_users ( user_id char(36) NOT NULL,
friend_id char(36) NOT NULL );
2- Establish the relationships in the User model.
var $hasAndBelongsToMany = array(
'friend' => array('className' => 'User',
'joinTable' => 'users_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'friend_id',
'unique' => true,
),
);
var $hasMany = array(
'Post' => array(
'className' => 'Post',
'foreignKey' => 'user_id'
),
);
3- use the scaffolding to insert a few records, linking friends and adding posts.
4- Add the view record function to the Users controller:
function get_user($id)
{
$posts = $this->User->find('first', array(
'conditions' => array('User.id' => $id),
'recursive' => '2'
));
pr($posts);
}
5- Now you can query the User table using recursive to pull the records using the following command:
http://test/users/get_user/USER_ID
6- Your output will show all of the records (recursively) including the friends and their posts in the returned data tree when you pr($posts)
I know this is a long post, but I think it will provide the best solution for what you are trying to do. The power of CakePHP is incredible. It's the learning curve that kills us.
Happy Coding!
If Post.user_id points to Friend.id (which wouldn't follow the convention btw) then it would be
$posts = $this->Post->find('all',array(
'conditions' => array(
'Post.user_id' => $user_id_array
)
);
which would result in .. WHERE Post.user_id IN (1, 2, 3) ..
Depending on your setup, it might be quicker to run two queries rather than trying to chain them together via the Cake stuff. I'd recommend adding something like getFriendsPosts() in the Users model.
<?php
class UserModel extends AppModel {
// ... stuff
function getFriendsPosts( $user_id )
{
$friends = $this->find( ... parameters to get user IDs of all friends );
// flatten the array or tweak your params so they fit the conditions parameter. Check out the Set class in CakePHP
$posts = $this->find( 'all', array( 'conditions' => array( 'User.id' => $friends ) ) );
return $posts;
}
}
?>
Then to call it, in the controller just do
$friends = $this->User->getFriendsPosts( $this->Auth->User('id') );
HTH,
Travis
Isn't CakePHP already generating the efficient code of:
SELECT * from Posts WHERE user_id IN (id1, id2 ...)
if not, you can do
$conditions='NULL';
foreach($user_id_array as $id) $conditions.=", $id";
$posts = $this->Posts->find('all', array(
'conditions' => "Post.user_id IN ($conditions)",
));
If your models are properly associated, Cake will automatically retrieve related model records. So, when you search for a specific user, Cake will automatically retrieve related friends, and related posts of these friends. All you need to do is set the recursion level high enough.
$user = $this->User->find('first', array('conditions' => array('User.id' => $id), 'recursive' => 2));
debug($user);
// gives something like:
array(
User => array()
Friend => array(
0 => array(
...
Post => array()
),
1 => array(
...
Post => array()
)
)
)
All you need to do is extract the posts from the user's friends, which is as easy as:
$postsOfFriends = Set::extract('/Friend/Post/.', $user);
Greetings,
I am trying to tear down query returned from find call using containable in CakePHP.
for example I have 2 models, User and Post. User hasMany Post.
Now when I am using containable on find call like so:
$User->id = 1;
$User->find('first', array(
'fields' => array('id'),
'contain' => array('Post')
))
It will not return the associated Post, instead will just return the id of the user.
It works however if I am trying to fetch the data the other way around.
i.e this works:
$Post->find('first', array(
'fields' => array('id', 'user_id'),
'conditions' => array('Post.user_id' => 1),
'contain' => array('User')
))
this doesn't:
$Post->find('first', array(
'fields' => array('id'),
'conditions' => array('Post.user_id' => 1),
'contain' => array('User')
))
From the returned values I then suppose that for the containable to works, the foreignKey has to be in the fields.
How then would I be able to filter out the User fields on the first call as the association of user is stored in Post.user_id?
Any help is greatly appreciated! Thank's.
-aw
As larryb82 said you'll need to define the relationship in both directions in order to retrieve Posts data from the User model
A user has many posts.
A post belongs to an user
CakePHP Doc example