I'm using php sdk to delete some fields from firestore database,
i want to delete a map from an array inside a document, but instead the function used delete all maps inside the parent array.
My firestore database looks like this
What i'm trying to do is remove a specific index ex: index 0 with it's children from imageUrls array not all the maps inside it.
I tried these 2 functions :
$usersRef->update([
['path' => 'imageUrls.image_url', 'value' => FieldValue::arrayRemove(['image.png'])]
]);
and this one
$usersRef->update([
['path' => 'imageUrls.image_url', 'value' => FieldValue::deleteField()]
]);
The first function remove all imageUrls childrens and change imageUrls type from array to map, while the second one nothing happened. All the fields still exist in the document and no deletion occurd
<?php
namespace App\Services;
use Google\Cloud\Firestore\FirestoreClient;
use Google\Cloud\Firestore\FieldValue;
use Google\Cloud\Firestore\FieldPath;
class FirebaseService
{
public function delete()
{
// Create the Cloud Firestore client
$db = new FirestoreClient(
['projectId' => 'MyProjectId']
);
$usersRef = $db->collection('NewStories')->document('1');
$usersRef->update(
[
['path' =>'imageUrls.image_url',
'value' => FieldValue::arrayRemove(['image.png'])]
]);
}
}
This can be achieved using the arrayRemove() method. As the PHP Client for Firestore says
Returns a special value that can be used with set(), create() or update()
that tells the server to remove the given elements from any array value
that already exists on the server. All instances of each element
specified will be removed from the array. If the field being modified is
not already an array it will be overwritten with an empty array.
Update:
Firebase does not support updating an existing element in an indexed array.
More information can be found in the Official Documentation.
Workaround:
Reading the entire array out of the document, make modifications to it in memory, then update the modified array field entirely.**
Credits to this Firestore Update single item in an array field case.
Related
I have an object that stores another subObject in it's data attribute. The subObject in the data attribute can be called vie a magic method like this:
$object->subObject. The subObject also has a data attribute in which it's value is stored. Currently when I do $object->subObject it automatically returns the value stored in the data attribute of the subObject. So basically the whole structure looks somewhat like this:
object [
data => subObject [
data => 'value'
]
]
$object->subObject //returns 'value'
I hope that this is understandable so far. Now I want to have the ability to execute someFunc() on the subObject: $object->subObject->someFunc(). That is generally not a problem. But I also want that, if I don't call a method on the subObject at all, the value of it's data attribute is returned ('value'). Is it possible to figure out within an object/a class if a method is called on it or not and act accordingly?
This is not possible. When you access a value, you get the same result regardless of what is going to be done with that value. It can't be different depending on whether you're going to call another method on it.
Remember that
$object->subObject->someFunc();
is essentially equivalent to
$temp = $object->subObject;
$temp->someFunc();
If the $object->subObject returned 'value', the first line would set $temp = 'value', and then $temp->someFunc() wouldn't work.
I need to apply a required rule to a array field in my form request when the another array field, in the same index, has a certain value. Example:
public function rules(): array
{
return [
'data' => 'array',
'data.*.is_admin' => 'required|boolean',
'data.*.area' => [
'nullable',
Rule::requiredIf($condition),
// other rules...
]
]
}
When evaluating the first item in the array, if data.0.is_admin = 1, I'll add required to data.0.area. The problem is that I'm unable to access the current index inside the requiredIf method.
Using closures I was able to access the current index, but I can't override the nullable rule unless I add a required one and I need to be able to pass null to area. I can't use sometimes because I need to ignore the other rules when area = null.
Right now I'm looping through $request->data and adding the rules conditionally for each index. I wonder if there is a way I can achieve this using Laravel's array sintax.
Thank you
I would like to return a model's Resource while appending a local change to some attributes that already exist in the model (in a way that it does not change database values). What is the correct method to call to achieve this (because append function is not correct)?
// exists $model->currency
// Version: Laravel 7.x
// ModelResoruce is a Illuminate/Http/JsonResource
$tempCurrency = $this->findCurrecy($model->currency);
return ok(ModelResource::make($model)->append(['currency' => $tempCurrency, /* multiple dynamic changes*/]);
// updated: more real scenario:
// $localized has MANY dynamic keys that exist in model but MAYBE different values
$localized= ['currency' => 'x', 'name' => 'y',];
ok(ModelResource::make($model)->append($localized);
// I want: user will see temp but data is not modified
// What happens: append does not change currency's value
This won't modify the database:
$tempCurrency = $this->findCurrecy($model->currency);
$model->currency = $tempCurrency;
As long as you don't call save() on $model later on, the database won't be affected.
I'm creating a class with different methods to get values out of Podio fields.
My idea was to create a program being able to get an X number of fields from an app. And it should be possible to delete fields or create new fields in the Podio app.
I have created the application but somehow the program stops getting the values from the app, when I make some changes in Podio. I think the issue is in this method. This method should get all the external values of the fields, but the method stops getting some of the them when I change the app in Podio.
I hope it makes sense. Otherwise please ask me for further details. The method is here:
public function getAllExternalIds(){
// Get the first item of the app, only 1 item
$items = PodioItem::filter($this->app_id,array('limit' => 1));
// Create external_id array
$exIds = array();
// find all the external Ids of the item and put them in the array
for($j=0;$j <count($items['items'][0]->fields) ;$j++){
$exIds[$j] = $items['items'][0]->fields[$j]->external_id;
}
//return the external Id array;
return $exIds;
}
The same issue is in this method:
public function getAllFieldNames(){
$items = PodioItem::filter($this->app_id,array('limit' => 1));
$fieldNames = [];
for($j=0;$j <count($items['items'][0]->fields) ;$j++){
$fieldNames[$j] = $items['items'][0]->fields[$j]->label;
}
return $fieldNames;
}
Podio is extremely flexible platform and you can change app template (list of fields) and keep existing items unchanged, and I'm afraid that this is exactly what you are facing.
Let's review it on example:
There is an app, let's call it 'Projects', and app template has only 2 fields: 'Title' and 'Deadline'.
Then you create 1 item with 'Title' and 'Deadline' fields.
Then you can change app template and add 'Details' field and remove 'Deadline' field.
And create 1 more item.
And then you can change app template again and remove both
'Title' and 'Details' fields and add 'Responsible' field.
Now items_1 has 'Title' and 'Deadline' fields and your methods will get those 2 fields, and item_2 has 'Title' and 'Details' fields, and app template actually has only 'Responsible' field and doesn't match none of those.
So, you should probably use https://developers.podio.com/doc/applications/get-app-22349 method to read current app configuration and settings.
I retrieved a record like so:
$record = $collection->find(array(
'name' => $name
));
Is there any way to update the record directly without having to requery the collection, or is it a shallow copy with no reference?
I guess you need
findAndModify
The findAndModify command atomically modifies and returns a single document. By default, the returned document does not include the modifications made on the update. To return the document with the modifications made on the update,new option can be used.