I have some documents in mongodb that look like this
{ "_id" : ObjectId("576f46ca6803fab30e7b23c8"),
"username" : "Dallas",
"likes" : [ "576f46ca6803fab30e7b23c8", "576f4c446803faae0e7b23c9" ]}
{ "_id" : ObjectId("576f46ca6803fab31e7b23c8"),
"username" : "Dallas",
"likes" : [ ]}
<?php
$m = new MongoClient();
$db = $m->testing;
$collection = $db->testCollection;
addLike();
//Add likes
function addLike()
{
$id = new MongoId("576f46ca6803fab30e7b23c8");
$collection->update(array('_id' => $id),array('$addToSet' => array('likes' => '4d0b9c7a8b012fe287547157')));
echo 'addLike seemed to work';
}
I know the line of code that is wrong (syntax-wise I'm guessing) is the line that does the ...->update()
If i comment this out, I make it to the echo.
What I'm trying to do is store all of the user ids inside of the likes array, as you see one of the posts has an empty array, that's how I plan to start all posts.
I am confused as to why this code doesn't work, I pretty much copied it directly from here
EDIT:
To add, I really like what the above post says about it not allowing it to make duplicates when using $addToSet. As it shouldn't be possible for the user to like a post more than once, there is never a time the id should be in more than once
It appears all of my code was actually correct, except for some failure to understand php syntax.
I was under the impression that creating a collection variable outside of the function was global, It turned out that it didn't want me to call collection inside of that function so by deleting the function it was fixed.
Related
I want to use laravels FormRequest to validate before updating some fields. This works fine if i just use:
User::find($application->userid)->fill($request->only('first_name'...
but the request also contains sub array ($request->programmeData).
array:2 [▼
"programme_id" => 5
"programme_title" => "some programme title"
]
if i try access that the same way i get 'Call to a member function only() on array':
Course::find($application->userid)->fill($request->programmeData->only('programme_id...
I've tried a handful of things, but not sure best way to go with this?
Update
I'm now using a foreach loop to save two items in the array. the example below saves the second value for both user_ids. any reason this isn't saving the first value for the first user_id?
foreach ($request->programmeData['userProgrammes'] as $key=>$userProgrammes) {
Course::where('application_id', $application->id)->get()[$key]->fill(Arr::only($request->programmeData['userProgrammes'][$key], ['programme_id']))->save();
}
but nothing updates. Any ideas on this one?
You can use Array::only() helper for this:
foreach ($request->programmeData['userProgrammes'] as $key=>$userProgrammes) {
Course::where('application_id', $application->id)->first()->fill([
$key => Arr::only($request->programmeData['userProgrammes'][$key], ['programme_id'])
])->save();
// or
$course = Course::where('application_id', $application->id)->first()
$course->$key = Arr::only($request->programmeData['userProgrammes'][$key], ['programme_id']);
$course->save();
}
//Arr::only($request->programmeData, ['programme_id', ...]);
In my HTML frontend, I have a jQuery DataTable displaying all records fetched via AJAX from the database - a rather pretty straight forward thing. I use the Laravel Collection's ->transform(function($o){ . . . }) to iterate through the collection and return it in an array-esque manner. Just think of the following piece of code in a controller:
$cAllRecords = DatabaseRecord::all();
if(!empty($aData['sFilterIds']))
{
$cAllRecords = $cAllRecords->whereIn('creator', explode(',', $aData['sFilterIds']));
}
return response()->json(['data' => $cAllRecords->transform(function ($oDatabaseRecord) {
/** #var $oDatabaseRecord DatabaseRecord */
$sActionsHtml = 'edit';
$sUrl = route('some.route', ['iDatabaseRecordId' => $oDatabaseRecord->getAttribute('od')]);
return [
$oDatabaseRecord->getAttribute('id'),
$oDatabaseRecord->getAttribute('updated_at')->toDateTimeString(),
$oDatabaseRecord->getAttribute('created_at')->toDateTimeString(),
$sActionsHtml
];
})]);
I'm actually just filtering for records created by certain user IDs (the whereIn() call in line 4. However, the response sent back to the client looks different for different users filtered leading the jQuery table to show 'no records available', as it had received an malformed answer from the server. For one user, the response looks like this:
{
"data":[
[
1,
"2019-05-29 16:44:53",
"2019-05-29 16:44:53",
"<a href=\"#\">edit<\/a>"
]
]
}
This is a correctly formed server response and will show up in the table regularly. Great! Now something that drives me insane - the same code for another user (ID 1, while the first request was for user ID 2) returns this:
{
"data":{
"1":[
3,
"2019-05-29 17:08:49",
"2019-05-29 17:08:49",
"<a href=\"#\">edit<\/a>"
]
}
}
which, pretty obviously, is malformed and is not correctly parsed by the datatable. OK, now combing them two filters and filtering for user ID 1 and 2 will, again, return the response correctly formatted:
{
"data":[
[
1,
"2019-05-29 16:44:53",
"2019-05-29 16:44:53",
"<a href=\"#\">edit<\/a>"
],
[
3,
"2019-05-29 17:08:49",
"2019-05-29 17:08:49",
"<a href=\"#\">edit<\/a>"
]
]
}
I tried a number of things, none of which had worked since it's merely guessing why it could work with one user and not with another. (Things like reversing the order of IDs to be filtered, etc., but I found out that the filtering is not the problem. It MUST be the transform, which behaves inconsistent.)
Any ideas on why this happens and how to tackle it? I mean, it's not the only way to achieve what I'm after, I was using ->each() and array_push for all the time before but wanted to get rid of it for the sake of making use of Laravel's helpers (or possibilites) - the manual iteration and array pushing process worked out seamlessly before, and even other parts of the app work well with the Collection transform over array iteration and pushing. Why doesn't it here?
Update: The ->map() collection method behaves exactly same. Map, as opposed by transform, does not alter the collection itself. However, this should not be a relevant part within this application any way. I really can't understand what's going wrong. Is this possibly Laravel's fault?
Please note that transform method returns a Illuminate\Support\Collection.
It's better that you call all() after the transform to get an array result.
Like this:
...
return response()->json(['data' => $cAllRecords->transform(function ($oDatabaseRecord) {
/** #var $oDatabaseRecord DatabaseRecord */
$sActionsHtml = 'edit';
$sUrl = route('some.route', ['iDatabaseRecordId' => $oDatabaseRecord->getAttribute('od')]);
return [
$oDatabaseRecord->getAttribute('id'),
$oDatabaseRecord->getAttribute('updated_at')->toDateTimeString(),
$oDatabaseRecord->getAttribute('created_at')->toDateTimeString(),
$sActionsHtml
];
})->all()]);
#Cvetan Mihaylov's answer made me look at all the available collection methods (https://laravel.com/docs/5.8/collections#available-methods) and I found ->values() to return the values reindexed. And - that did the trick! :-)
return response()->json(['data' => $cAllRecords->transform(function ($oDatabaseRecord) {
/** #var $oDatabaseRecord DatabaseRecord */
$sActionsHtml = 'edit';
$sUrl = route('some.route', ['iDatabaseRecordId' => $oDatabaseRecord->getAttribute('od')]);
return [
$oDatabaseRecord->getAttribute('id'),
$oDatabaseRecord->getAttribute('updated_at')->toDateTimeString(),
$oDatabaseRecord->getAttribute('created_at')->toDateTimeString(),
$sActionsHtml
];
})->values()]);
i am using the "medoo"-php/mysql-class (http://www.medoo.in) for my latest project. I like the quiet easy way to work with my SQL-stuff.
But i wondered if it is possible to change the search term according to an option from an input-select-form. Lets say we got search-option "user by name", we would go with:
$data = $database->select("account", [
"user_name",
"user_id",
"phone",
"email",
"age"], [
"user_name" => $_POST['user_name']]);
Fine so far. Now we get the search option "user by ID". Every thing else stays just the same. So i need only the
["user_name" => $_POST['user_name']]);
to be like
["user_id" => $_POST['user_id']]);
Is there a way to change that without writing the whole statement again?
It is just a example. Moreover for my project i will need to change other options of the query like update to insert oder different join-options. But for the moment i am fine with an answer to that.
Anyway, what do you think about the Medoo-Class. Got any cool alternative Class-solutions for me? Basically i know how to work with SQL querys but getting stuff to the array at the end is always driving me crazy. So i would love to get stuff faster and easier with a class.
Thx a lot for your help!
Best, Lox
You can just change the $where array before running the query like that:
if ($type == 'id')
{
$where = ["user_id" => $_POST['user_id']];
}
if ($type == 'user_name')
{
$where = ["user_name" => $_POST['user_name']];
}
$data = $database->select("account",
[
"user_name",
"user_id",
"phone",
"email",
"age"
],
$where
);
SOLVED
To view the data, I was doing a var_dump on the cursor and you have to loop through the cursor first to var_dump it.
foreach($user_images as $image) {
var_dump($image)
}
Can find out more about this at:
http://php.net/manual/en/class.mongocursor.php
/SOLVED
I have a collection called 'user_image' in my MongoDB. I am using PHP 5.3 with mongoDB db v2.0.5, pdfile version 4.5. I have this setup in my XAMPP. I am simply trying to find all documents in the collection. When I run the information below, nothing returns back even though I can confirm in the terminal running the db.user_image.find() that it returns results.
$m = new Mongo();
$db = $m->selectDB('dev_app');
$collection = new MongoCollection($db, 'user_image');
$collection->find();
If I change the query to simply use findOne by a user_uuid I get a result! Example below:
$collection->findOne(array('user_uuid' => 'de977803-f198-416a-8806-acbc1fa3f718'));
Here is an example document in the collection user_image:
{
"_id" : ObjectId("500c3f13ab8692ced0d9df6f"),
"user_uuid" : "de977803-f198-416a-8806-acbc1fa3f718",
"image_name" : "4a5e286e101429da0a3c3a576ffa4878.jpg",
"image_url" : "/uploaded_files/files/4a5e286e101429da0a3c3a576ffa4878.jpg",
"sm_thumb_url" : "/uploaded_files/thumbnails/4a5e286e101429da0a3c3a576ffa4878.jpg",
"md_thumb_url" : "/uploaded_files/files/4a5e286e101429da0a3c3a576ffa4878.jpg",
"lg_thumb_url" : "/uploaded_files/files/4a5e286e101429da0a3c3a576ffa4878.jpg",
"status" : "A",
"created" : ISODate("2012-07-22T17:57:36.835Z"),
"modified" : ISODate("2012-07-22T17:57:36.835Z"),
"created_by_uuid" : "de977803-f198-416a-8806-acbc1fa3f718",
"modified_by_uuid" : "de977803-f198-416a-8806-acbc1fa3f718"
}
What am I missing in the find query? Can anyone help me? Thanks.
Cursor Object is a 'key' here
The $cursor = $collection->find(); find() method will return a Cursor Object.
Now you can use toArray() method to get your data.
$dataArray = $cursor->toArray(); Simple as that. Or use foreach to get documents one by one. Ps. FindOne() which returns an array.
https://www.php.net/manual/en/class.mongodb-driver-cursor.php
I'm having an annoying problem. I'm trying to find out what fields of a form were changed, and then insert that into a table. I managed to var_dump in doUpdateObjectas shown in the following
public function doUpdateObject($values)
{
parent::doUpdateObject($values);
var_dump($this->getObject()->getModified(false));
var_dump($this->getObject()->getModified(true));
}
And it seems like $this->getObject()->getModified seems to work in giving me both before and after values by setting it to either true or false.
The problem that I'm facing right now is that, some how, sfWidgetFormSelect seems to be saving one of my fields as a string. before saving, that exact same field was an int. (I got this idea by var_dump both before and after).
Here is what the results on both var dumps showed:
array(1) {["annoying_field"]=> int(3)} array(1) {["annoying_field"]=>string(1)"3"}
This seems to cause doctrine to think that this is a modification and thus gives a false positive.
In my base form, I have
under $this->getWidgets()
'annoying_field' => new sfWidgetFormInputText(),
under $this->setValidators
'annoying_field' => new sfValidatorInteger(array('required' => false)),
and lastly in my configured Form.class.php I have reconfigured the file as such:
$this->widgetSchema['annoying_field'] = new sfWidgetFormSelect(array('choices' => $statuses));
statuses is an array containing values like {""a", "b", "c", "d"}
and I just want the index of the status to be stored in the database.
And also how can I insert the changes into another database table? let's say my Log table?
Any ideas and advice as to why this is happen is appreciated, I've been trying to figure it out and browsing google for various keywords with no avail.
Thanks!
Edit:
ok so I created another field, integer in my schema just for testing.
I created an entry, saved it, and edited it.
this time the same thing happened!
first if you what the status_id to be saved in the database, you should define your status array like this:
{1 => "a", 2 => "b", 3 => "c", 4 => "d"}
So that way he know that 1 should be rendered like "a" and so on. Then, when saving, only the index should be saved.
About saving in another database, my advise is to modify the doSave method defined by the Form class yo match your needs. I only know how Propel deals with it, maybe this could help:
the doSave method dose something like this:
protected function doSave($con = null)
{
if (null === $con)
{
$con = $this->getConnection();
}
$old = $this->getObject()->getModifiedValues($this);//Define this
$new_object = new Log($old);//Create a new log entry
$new_object->save($con));//save it!
$this->updateObject();
$this->getObject()->save($con);
// embedded forms
$this->saveEmbeddedForms($con);
}
Hope this helps!
Edit:
This is an example extracted from a model in one of my applications and its working ok:
Schema:
[...]
funding_source_id:
type: integer
required: true
[...]
Form:
$this->setWidget('funding_source_id', new sfWidgetFormChoice(array(
'choices' => array(1 => 'asdads', 2 => '123123123' , 3 => 'asd23qsdf'),
)));
$this->setValidator('funding_source_id', new sfValidatorChoice(array(
'choices' => array(1 => 'asdads', 2 => '123123123' , 3 => 'asd23qsdf'),
'required' => true
)));
About the log thing, that could be quite more complex, you should read the current implementation of the doSave method in the base form class, currently sfFomrObject on Symfony1.4., and when and how it delegates object dealing with modified values.
Okay,
It turns out I forgot to do a custom validator to use the array key instead.