Having an application that returns partial JSON responses, how can I combine objects/variables into one?
I am using
$json = JSON->new->utf8->decode($response->content);
to convert response into object/variable, but that is for each single one.
Now I need it to combine several partial responses into one.
How to do that and how to deal with possible duplicates items to avoid overwriting?
UPDATE:
To better understand the above issue see sample response below.
Every partial response has same structure, but different data in 'Groups' , 'Message' and 'Data' sections. The last response comes with 'Finished' = true.
$VAR1 = {
'answer' => {
'Error' => bless( do{\(my $o = 0)}, 'JSON::XS::Boolean' ),
'Id' => 12345,
'Finished' => $VAR1->{'answer'}{'Error'},
'Groups' => [
{
'Code' => 'ABC',
'RegNum' => 123,
'Name' => 'John Doe'
},
{
...
}
],
'Message' => undef,
'Data' => [
{
'Column1' => 'c1',
'Column2' => 'c2'
},
{
...
}
],
}
}
You can merge hashes by Hash::Merge
This has absolutely nothing to do with JSON. You want to merge two data structures. From the little you said, there are three arrays to merge. You didn't specify how, so maybe you simply want to append the elements of the new response to the elements of the original response.
for (qw( Groups Message Data )) {
push #{ $orig->{answer}{$_} }, #{ $new->{answer}{$_} }
if $new->{answer}{$_};
}
Related
This is my data table image
my blade file
#table([
'id' => 'Persons.index',
'xhr' => route('api.manage-dup-api'),
'ns' => 'PersonsIndex',
'columns' => $columns ?? [],
'filters' => $filterTable ?? [],
'params' => [
'filters_live' => false,
'selectable' => true,
'toolbar_style' => 'fixed'
]
])
this is a query which passes data to a data table [API]
$q->with('user')
->with('user.roles')
->select(
'persons.*',
'birth->date as birthdate'
)->`enter code here`whereIn('id', $id)->orWhereIn('old_id_CONINET', $coninet_ids);
return $this->outputList($q, $request);
as shown in the picture I want to remove ["] from the CONINET_ID table
you are storing an array of strings in the DB.
you can convert the array values to int:
array_map('intval', $array);
you can also create an accessor on your eloquent model
public function getOldIdConinetAttribute($value)
{
return array_map('intval', $value);
}
It would better if you give some detailed info. As of now details mentioned above can not explain your code. As of my understanding, I suggest you to check Yajra datatable plugin which will help you solving your issue.
or you can cast coninet_id to array by adding below code in your model.
protected $casts = [
'coninet_id' => 'array'
];
Is it possible to loop through this array in mysql and execute a delete statement where the category_id column is equal to the current value been looped in that array below.
$row = [
'type' => '3',
'name' => 'Warez',
'category_id' => 'IAB26-2',
'parent_category_id' => 'IAB26'
],
[
'type' => '3',
'name' => 'Spyware/Malware',
'category_id' => 'IAB26-3',
'parent_category_id' => 'IAB26'
],
[
'type' => '3',
'name' => 'Copyright Infringement',
'category_id' => 'IAB26-4',
'parent_category_id' => 'IAB26'
],
[
'type' => '3',
'name' => 'Uncategorized',
'category_id' => 'IAB24'
]
I have tried this
foreach($row as $value) {
$this->execute('DELETE from categories WHERE category_id = '.$value['category_id'].'');
}
doesn't seem to work as it should. Is there is better Sql command for this kind of operation?
Your code is insecure because it's possible to inject SQL. So an attacker might execute whatever he wants in your SQL query.
If this is really CakePHP code, why aren't you using the ORM? You cleary should read https://book.cakephp.org/3.0/en/orm.html the Table Objects and Deleting Data section. If not don't use wrong tags.
Assuming this is done in a table object, the most simple way to do this is:
$ids = Hash::extract($data, '{n}.category_id');
if (!empty($ids)) {
$this->deleteAll([
'category_id IN' => $ids
]);
}
You probably just need to wrap the value you concatenate with quotes (because it's not numeric).
Something like this:
$this->execute('DELETE from categories WHERE category_id = "'.$value['category_id'].'"');
However, doing DELETE ... WHERE as suggested in one of the comments would yield better performance.
Also, note that if the data comes from the user then it may be susceptible to SQL injection, so you should read about and use parameterized queries rather than concatenation.
Using an IN clause
$list = array(); foreach ($row as $item) {
$list[] = "'{$item['category_id']}'";
}
$sql = 'DELETE from categories WHERE category_id IN ('.implode(',',$list).')';
$this->execute( $sql );
I'm sending a post request in a test case, and I want to assert that a specific element, let's say with key 'x' exists in the response. In this case, I can't say seeJson(['x' => whatever]); because the value is unknown to me. and for sure, I can't do it with seeJson(['x']);.
Is there a way to solve this?
If it matters:
Laravel: v5.2.31
PHPUnit: 5.3.4
May it will be helpful for anyone else. You can write this test for your check response json structure
$this->post('/api/login/', [
'email' => 'customer3#example.com',
'password' => '123123123',
])->assertJsonStructure([
'status',
'result' => [
'id',
'email',
'full_name',
],
]);
Although it's not optimal at all, I chose to use this code to test the situation:
$this->post(URL, PARAMS)->see('x');
X is a hypothetical name, and the actual element key has a slim chance of popping up in the rest of the data. otherwise this nasty workaround wouldn't be practical.
UPDATE:
Here's the solution to do it properly:
public function testCaseName()
{
$this->post(route('route.name'), [
'param1' => 1,
'param2' => 10,
], [
'headers_if_any' => 'value'
]);
$res_array = (array)json_decode($this->response->content());
$this->assertArrayHasKey('x', $res_array);
}
I am working on an automated form submit script. It is logging in to a vendor's website and populating the fields of a form. When trying to submit, the desired result would be a ticket number displayed, which is acknowledging the form is submitted and the request is processed by their helpdesk.
However the form is not submitted correctly (no acknowledgement is displayed) and I suspect that it is caused by one of the inputs which is a SELECT.
Here is the code I use to set this field:
$forms[3]->value('ProductList','-2');
This has no effect on the the prepared form unfortunately, dumping $forms[3], i see this:
[...]
bless({
'onchange' => ' checkKC(document.all.ProductList, \'~0\'); prodExpand();',
'current' => 1,
'menu' => [
{
'seen' => 1,
'value' => '~0',
'name' => '<Please select>'
},
{
'seen' => 1,
'value' => '-2',
'name' => 'Product not found.... Search more'
},
{
'value' => '-1',
'name' => '------------------------------------'
},
{
'value' => 'Product1',
'name' => 'Product 1 Name'
}
],
'name' => 'ProductList',
'id' => 'ProductList',
'idx' => 1,
'type' => 'option'
}, 'HTML::Form::ListInput' ),
[...]
Am I using the right method of $forms[3]? (it was created by HTML::Form->parse($pageresult) btw) Or is there any other method I should try? I can't find any documentation for HTML::Form::ListInput
Thanks for any advice
Consider using WWW::Mechanize for form processing that takes more than one step. That way you can include the login process in your script along with going to the form and of course getting the result.
Or if you need to work with JavaScript, then use WWW::Mechanize::Firefox.
I'm pulling data from several remote DataSources, restructuring to fit my models schema and finally passing the array to MyModel::saveAll();
I'd like to avoid importing duplicate records (ie, don't import if MyModel.external_id = 120 & MyModel.external_type = 'basecamp.comment' already exists in db).
What's the most efficient way of going about this?
Sample data:
$data['MyModel'] = [
[
'title' => 'foo',
'created' => '2013-12-18 11:29:06',
'external_id' => 120,
'external_type' => 'github.commit'
],
[
'title' => 'bar',
'created' => '2013-12-18 13:22:06',
'external_id' => 120,
'external_type' => 'basecamp.comment'
]
];
NB: Notice that MyModel.external_id isn't unique on it's own.
This is where validation comes into play. In your MyModel class, add the following:
public $validate = array(
'external_type' => array(
'rule' => 'idAndTypeUnique',
'message' => "Type and ID already exist"
)
);
public function idAndTypeUnique()
{
$existing = $this->find('first', array(
'conditions' => array(
'external_id' => $this->data[$this->name]['external_id'],
'external_type' => $this->data[$this->name]['external_type']
)
));
return (count($existing) == 0);
}
Your saveAll() call would look like:
$this->MyModel->saveAll($data, array('validate' => true));
The easiest way is to make a unique index on those two fields.
alter table my_model add unique index(external_id, external_type);
This forces the constraint in the database level.
If you want to force this constraint in the cake layer, then check this out:
cakephp isUnique for 2 fields?