Not able to retrieve data from firestore - firebase

I have a collection 'posts' which has documents as uid of the particular users, under each document I have array 'posts' which contains a string 'likes' and a map 'post' which again contain a string 'userpost'.
I need to show data of the 'userpost' as a list in my homepage. Can someone suggest me a query for this.
I tried this:
return Firestore.instance.collection('posts').where('posts', arrayContains: 'post').snapshot();
And in my home page under listview.builder I'm retrieving data like this:-
Text( snapshot.data.documents[i].data['userpost'], )
But after running It isn't showing anything in the homepage and an execption is thrown: A build function returned null.

Firestore QuerySnapshot which you have to loop over to get the actual document map
Should try this
snapshot.data.documents.map((DocumentSnapshot doc){
if(doc.data.hasdata)){
return Text( doc.data.data['userpost'], );
}
return Text('Loading');
}).toList()

Related

Flutter delete array from document [duplicate]

I'm making a Flutter application.
But, I cannot delete a field in the Firestore document.
In another language I know to use FieldValue.delete() to delete a file in Firestorm document.
In Dart, How do I delete?
Update Oct,2018: This is Now Possible:
In order to delete a particular field from a Cloud Firestore document - make sure you are using Plugin version 0.8.0 or Above. Now a E.g If you have a document having a field 'Desc' with contain some Text. In Order to Delete it.
Firestore.instance.collection('path').document('name').update({'Desc': FieldValue.delete()}).whenComplete((){
print('Field Deleted');
});
This will Delete 'Desc' Field from the Document 'name'
I think this is currently impossible in standard, non hacky way.
There is an open issue https://github.com/flutter/flutter/issues/13905 in Flutter which have to be resolved first.
Get the DocumentReference, invoke update with a map which has a key you want to delete and value FieldValue.delete().
var collection = FirebaseFirestore.instance.collection('collection');
collection
.doc('document_id')
.update({
'field_to_delete': FieldValue.delete(),
}
);
Here is an official solution for deleting Field Path when programming in Flutter/Dart
Here is how a sample Firestore collection looks like:
{
'path': {
'name': {
'title': 'my title'
'description': 'my description',
}
}
}
In order to delete description field, you can do this:
Firestore.instance.collection('path').document('name').set(
{'description': FieldValue.delete()},
SetOptions(
merge: true,
),
)
And the collection will look like this:
{
'path': {
'name': {
'title': 'my title'
}
}
}
if you have nested fields then use the '.' (Dot) notation to specify the field.
E.g if your data is nested Map then this is handy.
Firestore.instance.collection('path').document('name').update({'address.town': FieldValue.delete()}).whenComplete((){
print('Field Deleted');
});

How to properply update an entity which contains an Image path?

I have a form that I use both for registration and edition of the user informations. This form contains a profile picture property on which I put #Assert\Image.
I succeed in creating a new user through my registration form but when I try to edit the user informations (with a PATCH method, just to update what need to be updated) I encounter an error with a 'File could not be found' message.
I suppose it's because the path stored in the database is a string and my #Assert\Image want an image.
I'm not sure about how I should manage this kind of update.
When I dd() the $user right after the submission, I see that the profilePicture property still contains the path saved in the database.
Here is my function regarding the form handling:
public function myProfile(Request $request)
{
$user = $this->getUser();
$form = $this->createForm(UserFormType::class, $user, ['method' => 'PATCH']);
if ($request->isMethod('PATCH')){
$form->submit($request->request->get($form->getName()), false);
if ($form->isSubmitted() && $form->isValid()) {
//...
}
}
//if no request just display the page
return $this->render('connected/myProfile.html.twig', [
'user' => $user,
'userProfileForm' => $form->createView()
]);
}
The Validator will check if your object contains a image and that seems not the case when you’re updating your object.
A workaround is to use group validation you define a specific group to the property that have the assert Image and in the method getGroupSequence you return the group if you’re in creation (id == null) or if the property is setted.

how to show username with user field type in advanced custom fields plugin

i create a user relational type field in acf, after selecting user, acf just returns user id, my question is how to return the selected user "first name" or email address on my page?
i tried User Array and User Object mode, but i did not get the result.
Can anyone guide me to work with User Array / User Object mode.
i cant find documents in acf website about this.
thanks
i use this code:
php the_field('inscourse');
For User Array selected, just put something like this to see the returned vales:
$inscourse = get_field('inscourse');
echo '<pre>';
print_r($inscourse);
echo '</pre>';
This will output a nested array like:
array(
[ID] => 123
[user_firstname] => Joe
[user_lastname] => Jackson
....
[user_nicename] => joe-jackson
[display_name] => Joe
....
)

Getting An Error when trying to create a subcollection in Firestore

I am trying to create a node in Google Firebase, and use its unique id to create a Document in Google Firestore of the same name.
I'm using Google's PHP Firestore Client: https://github.com/GoogleCloudPlatform/google-cloud-php-firestore
And I've read through their documentation: http://googlecloudplatform.github.io/google-cloud-php/#/docs/cloud-firestore/v0.5.1/firestore/writebatch
Here is my code:
<?php
use \Google\Cloud\Firestore\FirestoreClient;
use \Google\Cloud\Core\Timestamp;
use \Google\Cloud\Firestore\Transaction as FirestoreTransaction;
use \grptx\Firebase as FirebaseClient;
class FirestoreTest
{
public function create()
{
$client = new FirebaseClient();
$database = $client->getDatabase();
$org = array(
"acl" => array(),
"people" => array()
);
$ref = $database->getReference("/clients/")->push($org);
$key = $ref->getKey();
$config = array(
"projectId" => "xxx",
"keyFile" => json_decode(file_get_contents("/xxx/firebase_auth.json"), true)
);
$firestore = new FirestoreClient($config);
$batch = $firestore->batch();
$collection = $firestore->collection("clients")->document("-LXXXXXX")->collection("trips");
}
}
And I get this error:
Exception 'Google\Cloud\Core\Exception\BadRequestException' with message '{
"message": "Document name \"projects\/xxx-test\/databases\/(default)\/documents\/clients\/\" has invalid trailing \"\/\".",
"code": 3,
"status": "INVALID_ARGUMENT",
"details": []
}'
Any help is appreciated.
Basically this will happen if you try to put blank as document name.
This is the error that occurs if you try to get a collection as a document. It's kind of tricky because this can also happen if you try to get a document with the name of empty string in a collection.
I don't know PHP, but I would guess that either in your $database->getReference("/clients/")->push($org); call, you were supposed to name a document to push your information to, or in your $firestore->collection("clients")->document("-LXXXXXX")->collection("trips"); call that the document you are trying to get ("-LXXXXXX") has the name empty string. (Of course, this is assuming your document isn't actually named "-LXXXXXX", and you are using that as a substitute for some variable that happens to be equal to "").
For instance, in python this call randomly failed me earlier:
db.collection(u'data').document(current_id)
with the same error: 'Document name ".../documents/data/" has invalid trailing "/". and will exit.' I scratched my head for a while but that's because the variable current_id is the empty string.
Basically, internally Firebase converts it into a long pathname and then tries to get a document or a collection at that pathname depending on what your last call was. This causes an issue if you try to get a document that is named "".

Delete Firebase anonymous users after a while

I am using anonymous auth to allow my users to use the app without logging in. However, Firebase seems to persist these anonymous user IDs indefinitely. Is there a way to automatically purge these or set some sort of expiration rule? I don't want these one-time use IDs to live forever and clutter the actual user data from providers.
Unfortunately this is a "memory leak" (user leak?) Since there is no reasonable way to force an anonymous user to convert, these anonymous user ids will soon become zombies that serve no particular purpose (that I can think of). Furthermore, a single real user might (forgetfully) sign in as an anonymous user, yet again, after already linking their email to a previous incarnation, and then get frustrated when trying to link to their email. Overall, I find the current anonymous user implementation impractical, or at very least far from ideal.
For now I am planning to have an email address which is random but unique for a given user/device for signing in anonymous users, instead of using the builtin anonymous signin (which is disabled). In my opinion there needs to be a setting to tell Firebase to delete an anonymous user id upon sign out (they are useless at that point anyway) and/or after a predefined amount of time. In addition, it might be useful to be able to sign in again, with the same anonymous user id, until the expiration time (like by saving a token/etc.) Lastly, an attempt to link an email that is already in use should just merge the anonymous user id with the existing email/password user id through a verification step.
Somehow, there is a way of delete old anonymous users. I do it with a AppEngine cronjob that runs hourly.
But before you do that you have to define, what a anonymous user is. My users have to validate their email address and therefore I declare all users who are not validated to be anonymously after 90 days.
With the PubSub tick I then collect all users and delete them, here you've got a sample:
export const removeOldUsers = functions.pubsub.topic( "hourly-tick" ).onPublish( event => {
function getInactiveUsers( users: Array<UserRecord> = [], nextPageToken?: string ) {
let userList = users;
return admin.auth().listUsers( 1000, nextPageToken ).then( ( result: any ) => {
console.log( `Found ${result.users.length} users` );
const inactiveUsers = result.users.filter( ( user ) => {
return moment( user.metadata.lastSignInTime ).isBefore( moment().subtract( 90, "days" ) ) && !user.emailVerified;
} );
console.log( `Found ${inactiveUsers.length} inactive users` );
// Concat with list of previously found inactive users if there was more than 1000 users.
userList = userList.concat( inactiveUsers );
// If there are more users to fetch we fetch them.
if ( result.pageToken) {
return getInactiveUsers( userList, result.pageToken );
}
return userList;
} );
}
return new Promise( ( resolve ) => {
console.info( `Start deleting user accounts` );
getInactiveUsers().then( ( users ) => {
resolve( users );
} );
} ).then( ( users: Array<UserRecord> ) => {
console.info( `Start deleting ${users.length} user accounts` );
return Promise.map( users, ( user ) => {
return admin.auth().deleteUser( user.uid ).then( () => {
console.log( "Deleted user account", user.uid, "because of inactivity" );
} ).catch( ( error ) => {
console.error( "Deletion of inactive user account", user.uid, "failed:", error );
} );
}, { concurrency: 3 } );
} ).then( () => {
console.info( `Done deleting user accounts` );
} );
} );
Here I just pushed my class to npmjs #beyond-agentur-ug/firebase-delete-inactive-users
There is no way to bulk-delete, however, the following trick worked for me:
I used Macro Recorder and it worked like a charm. Just recorded a few iterations in the console of me deleting users, set it to repeat 500 times and walked away.
You can use Firebase's admin API to delete users programatically. You'll need to store a user list in your database as Firebase doesn't provide a query for that.
Managing users
Anonymous users can be a starting point before you upgrade them to a non anonymous user (think of an e-commerce site where an anonymous user adds stuff into his cart and then on checkout, upgrades to a Google or email/password user; in this case you probably do not want to lose the user's cart). As explained, this could be useful if you want to persist data from an anonymous user to an upgraded user. If you wish to purge anonymous users, there is no automated way to do so. However as soon as you either sign out the anonymous user or sign in a non anonymous user, the state of the anonymous user will be lost.

Resources