PHP / Laravel Firebase Realtime Database updating a specific field - php

I'm trying to update firebase realtime database using kreait/firebase-php package.
Here's my tree:
I need to update the child of /detail/pesan/1/<unique ID> which have is_read value of false and update it to true.
Here's part of my code:
$database = $firebase->getDatabase();
$id_pesan=1;
/*
Update Firebase is_read
*/
$update = ['/is_read' => "true"];
$updatePesan_1 = $database
->getReference('chat/detail/'. $id_pesan)
->orderByChild('is_read')
->equalTo('false')
->update($update);
But i get this error :
Call to undefined method Kreait\Firebase\Database\Query::update()
when I change it to get the value first then update / set it :
$updatePesan_1 = $database
->getReference('chat/detail/'. $id_pesan)
->orderByChild('is_read')
->equalTo('false')
->getValue()
->set($update);
I get this error :
{"status":"error","error":400,"message":"Index not defined, add \".indexOn\": \"is_read\", for path \"/chat/detail/1\", to the rules"}
What I'm trying to do is filter / query database first to find child of specific tree which have is_read = false and update the value from "false" to "true".
Is it possible to do query of firebase database then updating it?
If yes how do I fix my code to achieve that?

Here's my solution
Okay so after many research and trial and error.
I did a couple of things :
Change the new rule to enable editing specific field on firebase database
Change the PHP code since I am unable to do filter / query then update. so I had to do it without filter / query and then updating data
1. Changes to Firebase database Rule
I change the rule to this :
{
"rules": {
".read": true,
".write": true,
"chat": {
"detail": {
"$id_pesan" :{
".indexOn": ["is_read"]
}
}
}
}
}
Some short explaination :
The data is stored in chat/detail///
since I need to be able to change what's inside I added ".indexOn" : ["is_read"] I change the rule and put indexing inside chat/detail/.
2. Change PHP code
At first what I want to do is this :
Initialize Firebase
Set references
Do Update call while query-ing field (in 1 call)
But it seems the package doesn't support what I wanted to do. so instead what I had to do is I have to query the field and get the unique ID value first. Then I made it into an Associative Array, then use it to update Database
here's the new code
//initialize
$database = $firebase->getDatabase();
//get value of all the unique ID
$getValue = $database
->getReference('chat/detail/'. $id_pesan)
->orderByChild('is_read')
->equalTo('false')
->getValue();
//initialize Array
$update = [];
//make the array necessary to update the firebase database
/*
What the Array should looks like
<Unique ID>/<variable I wanted to change> => "<new Value>"
Example :
"-IUAYS678/is_read" => "true"
"-JVHBY817/is_read" => "true"
*/
foreach($updatePesan_1 as $k => $v)
{
$update[$k. "/is_read"]="true";
}
//Update the Firebase Database
$updatePesan_1_process=$database->getReference('chat/detail/'. $id_pesan)
->update($update);
I hope this helps

Related

Codeingiter 4 : "there is no data to update" exception

i'm trying to understand up Codeingiter works with entity.
Here's my code from InterventionController.php :
$intervention = $this->interventionsModel->find($id);
$intervention->title = $this->request->getVar("title");
$this->interventionsModel->save($intervention);
-> if i change the title into the form and if i click the "update" button : it works well (database get updates)
-> When i don't change the title and i just click the "update" button : it throws an exception : "There is no data to update."
How can i use codeingiter 4 without getting that exception if no data have been changed by the user ?
Thanks
Save is a wrapper for update/insert. When you know you're updating a record, you can use the update function, pass the variables in and the update will save, regardless of whether the properties of the record have changed.
$intervention = $this->interventionsModel->find($id);
$intervention->title = $this->request->getVar("title");
$this->interventionsModel->update($id, [
"title" => $intervention->title
]);
I think there should be a property of the model that turns this functionality off for the save() wrapper, but it doesn't appear there is.
Documentation: https://codeigniter.com/user_guide/models/model.html?highlight=data%20update#saving-data
try this
$this->obj->update($id, $p);
instead of
$this->obj->where('id',$id)->update( $p);
You can check if the value from form is empty or not and use the IF Condtion
$intervention = $this->interventionsModel->find($id);
if($this->request->getVar("title"))
{
$intervention->title = $this->request->getVar("title");
$this->interventionsModel->save($intervention);
} else {
// title is empty or null;
}

Laravel Crud Editing makes a new record

I have a problem with my Laravel crud application for Registrations.
There are these tables: Registration, ExtraRegistration (with a registration_id, extra_id and extraoptions_id),
Extra and ExtraOptions (with the Extra_id).
In the RegistrationController when i add a Registration it makes a new record in the ExtraRegistration with the extraoptions_id and the extra_id. the extra_id is the name of the option and the extraoptions_id is the id of the option you selected.
But now, when you click on edit a record, it shows all the information. the problem is that when you change the extraoption, it makes another record, and not change the select.
And when you have edited something and you look at it again, it still shows the option before you edited it.
RegistrationController
$options = Extra::where("exa_form_id", $distance->asd_form_id)->get();
foreach($options as $option){
$input_name = "option_" . $option->exa_id;
$input_option = $request->$input_name;
if(!is_null($input_option)){
$input_name_extra = "extraoptions_" . $option->exa_id;
$input_option_extra = $request->$input_name_extra;
$registrationextra = new ExtraRegistration();
$registrationextra->iea_registration_id = $registration->isg_id;
$registrationextra->iea_extra_id = $input_option;
$registrationextra->iea_extraoption_id = $input_option_extra;
$registrationextra->iea_price = $option->exa_price;
$registrationextra->save();
}
}
$registration->isg_options = $input_option;
$registration->isg_option_extra_id = $input_option_extra;
I want a check before it makes a new ExtraRegistration. that it only makes a new registration if the registration_id with that extra_id doesn't already exists. (Not 100% sure though).
Thanks in advance!
you make a new object of ExtraRegistration so its always make a new entry for update first get object of those id after that update
check the below link
https://laravel.com/docs/5.8/eloquent#updates
This happens because you're creating a new ExtraRegistration record:
$registrationextra = new ExtraRegistration();
If you want to update it, you need to find the related $registrationextra for your $options, and then update them (assuming you have relations set up):
$registrationextra = ExtraRegistration::where('options_id', $option->id);
$registrationextra->update([
'your_fields' => value
// etc...
]);
If you want to check if ExtraRegistration exists, and depending on that, create or update it, you can do something like this:
$registrationextra = App\ExtraRegistration::updateOrCreate(
['your_fields' => 'value'],
);
You can read more on official documentation.

CakePHP how to add data from another field of a related model

This is one of my first applications out of tutorials so I don't know how to express my issue well.
Well I have these 2 tables:
User ( id, code )
Hours ( id, user_id, created)
I want to know how I can add an entry to the Hours table using the user_code.
I tried to grab the data of the User table with the code value and then findBy and pass for the patchEntity but it did not work.
I don't have a whole lot of information to work with, but I'll give it a go.
I want to know how I can add an entry to the Hours table using the
user_code
You mention using patchEntity, so that's updating information that's already there. Assuming user_code is the 'code' column you're talking about there, first find the user by his code:
$users_tbl = TableRegistry::get('Users');
// find the user
$user = $users_tbl->findByCode($user_code)->first();
if ($user) {
// replace '$this->request->data() with whatever patch data you wanted
$users_tbl->patchEntity($user, $this->request->data(), [
'associated' => ['Hours']
]
if ($users_tbl->save($user)) {
// success!
} else {
// error!
}
} else {
// error!
}
It will also depend on how you have the data you passed in (where my '$this->request->data() is, or whatever your array might be) - it needs to match the right column names and be in the correct format listed here.
However, this is updating the data. Just adding the data, you can load the hours table and add a new entry with the user_id acquired from the user search:
$hours_tbl = TableRegistry::get('Hours');
$hours = $hours_tbl->newEntity([
'user_id' => $user->id // $user populated from same method earlier
]);
/* assumed 'id' was autoincrementing and 'created' was populated
through Timestamp behavior */
if ($hours_tbl->save($hours)) {
// yay!
} else {
// boo
}

Delete Items API for iOS App (calls to PHP for the API call)

Here is our current set up. We have an iOS app that makes API calls to my PHP script which handles the request and queries a database via PDO and MySQL. So in this case there is an update_items.php API that the iOS app sends parameter values to and based on whether the user is updating an item or deleting an item, the API handles it accordingly and queries the database multiple times (all in one request).
Here's my predicament. I have the update bit working, but how can I use the same update API to delete an item via POST request? A quick remedy my iOS developer came up with is that if a user swipes to delete an item, he sends the item's name as "DELETE" or something along those lines. This initiates a delete query for the database record. I don't like this because anyone could figure this out and exploit the system. For example, while editing an item all I have to do is enter in DELETE for the item's name and the API would process it the same as a delete request. There has to be a better way and I would appreciate any suggestions. Below is my current PHP code that handles the API call. My suggestion, however, was to simultaneously send two API calls after a user clicks DONE for editing their item page. One to update.php if the user updates an item and another delete.php if a user decides to delete an item.
// now check for updating/deleting ingredients for the menu item
if( isset($the_request['id']) ) {
/*
iterate through avalialable values because there could be multiple ingredient ids involved. handle it.
*/
for( $i=0;$i<count($the_request['id']);$i++ ) {
// the queries. check if ingredient is being deleted or not via passed paramater value
switch($the_request['name'][$i]) {
case 'DELETE':
// assign passed parameter for delete query
$params = array(
':id' => $the_request['id'][$i]
);
// the query
$query = 'DELETE FROM TABLE WHERE id = :id';
break;
default:
// assign passed parameters for query
$params = array(
':name' => $the_request['name'][$i],
':price' => $the_request['price'][$i]
);
// Remove the empty values
$params = array_filter($params, function($param) { return !empty($param); });
// Build an array of SET parameters
$set = array_map(function($key) {
return sprintf('%s = %s', substr($key, 1), $key);
}, array_keys($params));
// don't forget the id
$params[':id'] = $the_request['id'][$i];
// the query
$query = sprintf('UPDATE TABLE SET %s WHERE id = :id', implode(', ', $set));
}
// prepare statement
if( $ingStmt = $dbh->prepare($query) ) {
$ingStmt->execute($params);
} else {
echo json_encode(array('error' => $dbh->errorInfo().__LINE__));
}
}
$ingStmt->closeCursor();
}
The REST answer is don't use a POST request, use a separate DELETE request.

setting persistent plugin parameters in Joomla 3

I'm developing a Joomla 3.x plugin, and want to be able to change the plugin parameter set in the plugin's manifest file programmatically. I believe I need to use a JRegistry object, but I'm not sure about the syntax.
Here's the issue:
// token A is set in plugin params as defined in plugin's XML manifest
var_dump($this->params->get('token')); // prints token "A" as expected
// do some stuff to get a fresh access token, called token "B"
$tokenB = $function_to_get_fresh_token();
// set the new token
if ($tokenB) $this->params->set('token', $tokenB);
var_dump($this->params->get('apptoken')); // prints token "B" as expected
the problem is that on subsequent page reloads, the token reverts to tokenA rather than what I assumed would be the stored value of tokenB.
How do I store the tokenB value in the plugin's parameters in the database?
This is a working example of how to change plugin params from within the plugin (J! 3.4):
// Load plugin called 'plugin_name'
$table = new JTableExtension(JFactory::getDbo());
$table->load(array('element' => 'plugin_name'));
// Params can be changed like this
$this->params->set('new_param', 'new value'); // if you are doing change from a plugin
$table->set('params', $this->params->toString());
// Save the change
$table->store();
Note: If new params are added by plugin dynamically and the plugin is saved afterwards, these new params gets deleted. So one way to deal with it is to add those params as hidden fields to plugin's config XML.
This is just an outline, but something along these lines
$extensionTable = new JtableExtension();
$pluginId = $extensionTable->find('element', 'my_plugin');
$pluginRow = $extensionTable->load($pluginId);
// Do the jregistry work that is needed
// do some stuff to get a fresh access token, called token "B"
$tokenB = $function_to_get_fresh_token();
// set the new token
if ($tokenB) $this->params->set('token', $tokenB);
// more stuff
$extensionTable->save($pluginRow);
I spent a lot of time googling and reading and found no real answer to this. Oddly enough this doesn't seem to have been provided for in Joomla. So here's what I ended up doing:
1) build a function to get your plugin ID, since it will change from one installation to another
private function getPlgId(){
// stupid hack since there doesn't seem to be another way to get plugin id
$db = JFactory::getDBO();
$sql = 'SELECT `extension_id` FROM `#__extensions` WHERE `element` = "my_plugin" AND `folder` = "my_plugin_folder"'; // check the #__extensions table if you don't know your element / folder
$db->setQuery($sql);
if( !($plg = $db->loadObject()) ){
return false;
} else {
return (int) $plg->extension_id;
}
}
2) use the plugin id to load the table object:
$extension = new JTableExtension($db);
$ext_id = $this->getPlgId();
// get the existing extension data
$extension->load($ext_id);
3) when you're ready to store the value, add it to the params, then store it:
$this->params->set('myvalue', $newvalue);
$extension->bind( array('params' => $this->params->toString()) );
// check and store
if (!$extension->check()) {
$this->setError($extension->getError());
return false;
}
if (!$extension->store()) {
$this->setError($extension->getError());
return false;
}
If anyone knows a better way to do this please let me know!

Categories