Fat-Free-Framework / F3 access a hive variable in a mapper callback - fat-free-framework

I'm using the Fat Free Framework ORM Mapper functionality to insert a set of records passed from the client in an array. The Mapper function has callbacks to for aftersave which pass an array of keys and the mapper object.
I want to be able to loop through the records and use the mapper to insert the records one by one, storing the inserted record's id in an array ('resultsArray') which is set in the F3 hive in the parent function:
function myFunction (\Base $f3, $params) {
// array of records to insert
$mappedArray = json_decode( $f3->get('BODY'), true );
$f3->set('mapper', new mapper($db,'mytable'));
$mapper = $f3->get('mapper');
// create an array in the hive to store the results of the inserts
$f3->set('resultsArray', array());
// set mapper callbacks
$mapper->aftersave(function($self,$pkeys){
// update the resultsArray in the hive?
});
$recordsInArray = count($mappedArray);
// loop through the array of objects
for ($loop = 0; $loop<$recordsInArray; $loop++){
$newRecord = $mappedArray[$loop];
try{
// clear the mapper down
$mapper->reset();
// set the array in the hive
$f3->set('data', $newRecord );
$mapper->copyFrom('data');
$mapper->save();
} catch(\PDOException $e) {
// do something
exit;
}
}
echo "done";
}
Is there a way to access the resultsArray variable I set in the hive in the aftersave callback?
Thanks
Matt

Are you sure that you need to do all these things to achieve what you want?
To be able to store the IDs of inserted records and put it in the F3's hive, I would do the following:
<?php
function myFunction (\Base $f3, $params) {
// array of records to insert
$mappedArray = json_decode( $f3->get('BODY'), true );
//mapper (no need to put it into hive):
$mapper = new mapper($db,'mytable');
// array with IDs:
$resultsArray = [];
// loop through the array of objects
for ($loop = 0; $loop<count($mappedArray); $loop++){
try{
// clear the mapper down
$mapper->reset();
// map the content (no need to put it in the hive):
$mapper->copyFrom($mappedArray[$loop]);
// insert new record:
$mapper->save();
// get the ID of the inserted record and put it in the array:
$resultsArray[] = $mapper->_id;
} catch(\PDOException $e) {
// do something
exit;
}
}
// put the array of IDs in the hive:
$f3->set("newIDs", $resultsArray);
}

You can access the hive within the aftersave handler with the php use feature:
function myFunction (\Base $f3, $params) {
// ...
$mapper->aftersave(function($self,$pkeys) use($f3) {
$f3->get('resultsArray');
});
}

Related

Why does Laravel redirect to a wrong id after DB::listen?

I would like to store every query I run inside my application. To do that, I've created a "loggers" table, a Logger modal and this function inside my boot AppServiceProvider
DB::listen(function($query) {
$logger = new Logger;
$logger->query = str_replace('"', '', $query->sql);
$logger->bindings = json_encode($query->bindings);
$logger->created_at = Carbon::now();
$logger->save();
});
Well, anytime I run an insert query, Laravel returns the loggers table ID instead of the model last inserted ID.
Why on earth does this happen?
public function store(CycleRequest $request) {
$appointment = new Appointment;
$appointment-> ... same data ...
$appointment->save();
if ( ! $errors ) ){
$msg['redirect'] = route('appointments.edit', $appointment);
// The page redirects to last logger id
}
}
I think you want to do triggers so I recommend use events for this, o maybe you can take the structure of you table "loggers" and do two differents querys each time that you do querys.
After searching a lot, I found a solution creating a Middleware. Hope this may help someone else.
I've created a QueryLogMiddleware and registered in 'web' middleware, but you may put it everywhere you want:
public function handle($request, Closure $next)
{
\DB::enableQueryLog();
return $next($request);
}
public function terminate($request, $response)
{
$queries = \DB::getQueryLog();
foreach ($queries as $query)
{
// Save $query to the database
// $query["query"]
// $query["bindings"]
...
}
\DB::disableQueryLog();
\DB::flushQueryLog();
}

javascript auto call function in object

I need to create a dynamic object. I'll store all of these objects in an array. Each object will have some property and objects. After the object is created, I need to do an auto execute method from it. I can't call in my code like this: obj.doSomething because some users have 2 objects, and other users 300 objects.
Something like this:
class Select {
constructor(el,input){
this.el = el;
this.input = input
}
AutoExecture(){
// I need these function to execute immediately;
console.log(this.input);
}
}
Perhaps you want something like this:
class Select {
constructor(el,input){
this.el = el;
this.input = input;
// This code will autoExecute when you construct an object
console.log(this.input);
}
}
You can run this code in the console with something like:
var a = new Select("hi", "bye");

Perl parse JSON response as an array

I have a long sql query with a lot of derived columns and I'm trying to get it displayed in an angular page. I reached the point where I'm getting a json response back from the db but its returning each row as one big object instead of an array. I'm using perl to query the db and I've tried a bunch of ways to parse it and I haven't gotten it yet.
The subroutine:
require fileWithAllImports.pl #has CGI, JSON, etc
%response = {};
$response{error}{code} = "0";
$response{error}{message} = "OK";
$sql = "select c.title as Content....";
$sql = &database_escape_sql($sql); #I think its self-explanatory what this does
%hash = &database_select_as_hash_with_auto_key(
$sql,"content ... "); #more columns
foreach $i ( keys %hash ) {
$id = $i;
$response{$i}{content} = $hash{$i}{content};
...
} #again all of the columns
print_json_response(%response);
The angular call:
$http.get("/folder/ofSubroutine.cgi")
.then(function(minutes_results) {
console.log(minutes_results);
and the json repsonse:
{"6":{"derivedcolumn":"123","anotherderived":"987",..},"11":{"derived column":"123"}...}
I believe ng-repeat only works with an array so how would I parse the response from the server into an array?
On the back end, you could place the data into a separate array instead of adding each row to the hash:
foreach $i ( keys %hash ) {
push #{$response{data}}, { id => $i,
content => $hash{$i}{content},
... ,
};
}
print_json_response( %response );
Or on the front end, convert your associative array to a regular array:
$http.get("/folder/ofSubroutine.cgi")
.then(function(minutes_results) {
console.log(minutes_results);
var minutes_results_as_array = [];
for (var key in minutes_results) {
if (key != "error") {
minutes_results[key].id = key;
minutes_results_as_array.push(minutes_results[key]);
}
}
// display minutes_results_as_array as you see fit
} );

Get only values from rows and associations with Sequelize

I am using Sequelize, MySQL and Node to write a web application.
For most of my DB needs, I usually do some verification, then fetch my models (eagerly with associations) and send them back to the client, almost always as-is (at least, up to now).
I wrote a little utility function getValuesFromRows to extract the values from a returned row array:
getValuesFromRows: function(rows, valuesProp) {
// get POD (plain old data) values
valuesProp = valuesProp || 'values';
if (rows instanceof Array) {
var allValues = [];
for (var i = 0; i < rows.length; ++i) {
allValues[i] = rows[i][valuesProp];
}
return allValues;
}
else if (rows) {
// only one object
return rows[valuesProp];
}
return null;
}
// ...
...findAll(...)...complete(function(err, rows) {
var allValues = getValuesFromRows(rows);
sendToClient(errToString(err, user), allValues);
});
However, I am adding more and more complex relations to my DB models. As a result, I get more associations that I have to fetch. Now, I don't only have to call above function to get the values from each row, but also I need more complicated utilities to get the values from all included (eagerly loaded) associations. Is there a way to only get values from Sequelize queries (and not the Sequelize model instance) that also includes all associated values from the instance?
Else, I would have to manually "get all values from each Project and add one item to that values object for the values property of each entry of Project.members" (for example). Note that things get worse fast if you nest associations (e.g. members have tasks and tasks have this and that etc.).
I am guessing that I have to write such utility myself?
I found a simple solution to my problem, by extending my existing POD converting function above with a recursion into all include'd associations of the query. The Solution works with find, findAll, all and possibly other operations with non-trivial results.
Code
/**
* Get POD (plain old data) values from Sequelize results.
*
* #param rows The result object or array from a Sequelize query's `success` or `complete` operation.
* #param associations The `include` parameter of the Sequelize query.
*/
getValuesFromRows: function(rows, associations) {
// get POD (plain old data) values
var values;
if (rows instanceof Array) {
// call this method on every element of the given array of rows
values = [];
for (var i = 0; i < rows.length; ++i) {
// recurse
values[i] = this.getValuesFromRows(rows[i], associations);
}
}
else if (rows) {
// only one row
values = rows.dataValues;
// get values from associated rows
if (values && associations) {
for (var i = 0; i < associations.length; ++i) {
var association = associations[i];
var propName = association.as;
// recurse
values[propName] = this.getValuesFromRows(values[propName], association.include);
};
}
}
return values;
}
Example
var postAssociations = [
// poster association
{
model: User,
as: 'author'
},
// comments association
{
model: Comment,
as: 'comments',
include: [
{
// author association
model: User,
as: 'author'
}
]
}
];
// ...
var query = {
where: ...
include: postAssociations;
};
// query post data from DB
return Post.findAll(query)
// convert Sequelize result to POD
.then(function(posts) {
return getValuesFromRows(posts, postAssociations);
})
// send POD back to client
.then(client.sendPosts);
In the above example, client.sendPosts receives an array. Each entry of the array will have properties author and comments. Each comment in the comments array will also have an author property. The entire array only contains POD (plain old data).

Insert with Linq-to-SQL an object determined through reflection

I am trying to populate a row in a table given a key value list
Using DataContext.Mapping I am able to locate the correct table (given a table name) and create a row.
// Look up the table
MetaTable matchedTable = null;
foreach (MetaTable tableMetaData in db.Mapping.GetTables())
{
if (table.Equals(tableMetaData.TableName))
{
matchedTable = tableMetaData;
break;
}
}
if (matchedTable == null)
{
throw new Exception("Invalid table name specified");
}
I then iterate over the row properties and populate the values.
// Iterate through the dictionary and try to match up the keys with column names
foreach (KeyValuePair<string, string> listItem in list)
{
PropertyInfo propertyInfo = rowType.GetProperty(listItem.Key);
if (propertyInfo == null)
{
throw new Exception("Invalid column name specified");
}
// Set the value on the object
try
{
propertyInfo.SetValue(row, Convert.ChangeType(listItem.Value, propertyInfo.PropertyType), null);
}
catch
{
throw new Exception("Value specified cannot be converted to database type");
}
}
I now need to get this row object inserted back into the DB. I have been playing around with db.GetTable<rowType>(); with no luck. Thanks
I was overthinking it
db.GetTable(rowType).InsertOnSubmit(row);
db.SubmitChanges();