I'm not sure if the title of this question is necessarily the accurate description of what I need to do, but I'll go ahead and ask my question and see what everyone thinks...
Basically, I am receiving data from a source that I have no control over, and I need to transpose it into a suitable format for inserting into my database using CakePHP. So, here's how I'm doing it:
public function submitApp($data) {
$array = array(
'Student' => array(
'name' => $data['name'],
'email' => $data['email'],
'phone' => $data['phone'],
'address' => $data['address'],
'dob' => $data['dob'],
'gender' => $data['gender']
),
'Application' => array(
'course_id' => $data['course_id'],
'question1' => $data['question1'],
'question2' => $data['question2'],
'question3' => $data['question3'],
'question4' => $data['question4'],
),
'ApplicationQualification' => $data['Qualifications']
);
// Logic to save $array goes here
}
The problem is that sometimes not all of the keys in $data will be submitted to my app but I still want my app to work with what it gets.
I know that I can wrap each key in a conditional like this:
if (!isset($data['name'])) { $data['name'] = null; }
...and then building the array, but this seems like a pretty clumsy way of doing it. Is there a more efficient way to do this?
You could use a simple ternary statement
'name' => array_key_exists('name', $data) ? $data['name'] : null
Alternatively, you can set up a default array and then merge the given values in
$defaults = [
'name' => null,
'email' => null,
// etc
];
$data = array_merge($defaults, $data);
Related
I have the following array
$array['projects'] = [
'name1' => [
'task' => [
'tags' => ['value1', 'value2'],
'email' => 'email2',
'description' => 'mpla'
],
'email' => 'email1',
'tags' => ['value1', 'value3'],
'title' => 'mpla'
]
];
Is there anyway I could use the Hash class of CakePHP 3 or maybe another class of CakePHP framework to achieve the following result:
$array['projects'] = [
'name1' => [
'email' => 'email2',
'tags' => ['value1', 'value2'],
'title' => 'mpla'
'desciption' => 'mpla'
]
];
If you also know anyother package that it can handle arrays and get my job done it will do.
Not sure that this can be easily achieved using Cake's Hash utility. You can easily extract the array items indexed by task using combine(), but not sure how you would then go about extracting the title values and combining those with the other array elements using Hash:-
Hash::combine($array, 'projects.{s}', 'projects.{s}.task');
Perhaps the simplest solution is to use a foreach loop like this:-
$data = [];
foreach ($array['projects'] as $value) {
$data['projects'] = $value['task'] + ['title' => $value['title']];
}
I created this array of objects:
$ad_1 = new AdUnit(array('id' => '1', 'name' => 'Ad_1', 'description' => 'great ad', 'code' => 'alpha', 'widget_id' => '123'));
$ad_2 = new AdUnit(array('id' => '2', 'name' => 'Ad_2', 'description' => 'good ad', 'code' => 'delta', 'widget_id' => '456'));
$ad_3 = new AdUnit(array('id' => '3', 'name' => 'Ad_3', 'description' => 'bad ad', 'code' => 'sigma', 'widget_id' => '789'));
$adUnitArr = array($ad_1, $ad_2, $ad_3);
and i want to check that a random ad i got from a function exists in the array. the code to get the ad looks like this:
$fixture = new AdGroup();
$fixture->setAds($adUnitArr);
$randad = $fixture->getRandomAd();
now i want to check if the array contains the random ad i received, what i was able to do like this:
$this->assertEquals(in_array($randad, $adUnitArr), 1); //check if ad in array
but my question is, is there an assert or some other way to check this thing better than the way i did it?? i tried using assertArrayHasKey but i got the following error:
PHPUnit_Framework_Exception: Argument #1 (No Value) of PHPUnit_Framework_Assert::assertArrayHasKey() must be a integer or string
any idea please? thx
Try the assertContains method:
$this->assertContains( $randad, $adUnitArr );
In my example code I am using the php client library, but it should be understood by anyone familiar with elasticsearch.
I'm using elasticsearch to create an index where each document contains an array of nGram indexed authors. Initially, the document will have a single author, but as time progresses, more authors will be appended to the array. Ideally, a search could be executed by an author's name, and if any of the authors in the array get matched, the document will be found.
I have been trying to use the documentation here for appending to the array and here for using the array type - but I have not had success getting this working.
First, I want to create an index for documents, with a title, array of authors, and an array of comments.
$client = new Client();
$params = [
'index' => 'document',
'body' => [
'settings' => [
// Simple settings for now, single shard
'number_of_shards' => 1,
'number_of_replicas' => 0,
'analysis' => [
'filter' => [
'shingle' => [
'type' => 'shingle'
]
],
'analyzer' => [
'my_ngram_analyzer' => [
'tokenizer' => 'my_ngram_tokenizer',
'filter' => 'lowercase',
]
],
// Allow searching for partial names with nGram
'tokenizer' => [
'my_ngram_tokenizer' => [
'type' => 'nGram',
'min_gram' => 1,
'max_gram' => 15,
'token_chars' => ['letter', 'digit']
]
]
]
],
'mappings' => [
'_default_' => [
'properties' => [
'document_id' => [
'type' => 'string',
'index' => 'not_analyzed',
],
// The name, email, or other info related to the person
'title' => [
'type' => 'string',
'analyzer' => 'my_ngram_analyzer',
'term_vector' => 'yes',
'copy_to' => 'combined'
],
'authors' => [
'type' => 'list',
'analyzer' => 'my_ngram_analyzer',
'term_vector' => 'yes',
'copy_to' => 'combined'
],
'comments' => [
'type' => 'list',
'analyzer' => 'my_ngram_analyzer',
'term_vector' => 'yes',
'copy_to' => 'combined'
],
]
],
]
]
];
// Create index `person` with ngram indexing
$client->indices()->create($params);
Off the get go, I can't even create the index due to this error:
{"error":"MapperParsingException[mapping [_default_]]; nested: MapperParsingException[No handler for type [list] declared on field [authors]]; ","status":400}
HAD this gone successfully though, I would plan to create an index, starting with empty arrays for authors and title, something like this:
$client = new Client();
$params = array();
$params['body'] = array('document_id' => 'id_here', 'title' => 'my_title', 'authors' => [], 'comments' => []);
$params['index'] = 'document';
$params['type'] = 'example_type';
$params['id'] = 'id_here';
$ret = $client->index($params);
return $ret;
This seems like it should work if I had the desired index to add this structure of information to, but what concerns me would be appending something to the array using update. For example,
$client = new Client();
$params = array();
//$params['body'] = array('person_id' => $person_id, 'emails' => [$email]);
$params['index'] = 'document';
$params['type'] = 'example_type';
$params['id'] = 'id_here';
$params['script'] = 'NO IDEA WHAT THIS SCRIPT SHOULD BE TO APPEND TO THE ARRAY';
$ret = $client->update($params);
return $ret;
}
I am not sure how I would go about actually appending a thing to the array and making sure it's indexed.
Finally, another thing that confuses me is how I could search based on any author in the array. Ideally I could do something like this:
But I'm not 100% whether it will work. Maybe there is something fundemental about elasticsearch that I am not understanding. I am completely new to so any resources that will get me to a point where these little details don't hang me up would be appreciated.
Also, any direct advice on how to use elasticsearch to solve these problems would be appreciated.
Sorry for the big wall of text, to recap, I am looking for advice on how to
Create an index that supports nGram analysis on all elements of an array
Updating that index to append to the array
Searching for the now-updated index.
Thanks for any help
EDIT: thanks to #astax, I am now able to create the index and append to the value as a string. HOWEVER, there are two problems with this:
the array is stored as a string value, so a script like
$params['script'] = 'ctx._source.authors += [\'hello\']';
actually appends a STRING with [] rather than an array containing a value.
the value inputted does not appear to be ngram analyzed, so a search like this:
$client = new Client();
$searchParams['index'] = 'document';
$searchParams['type'] = 'example_type';
$searchParams['body']['query']['match']['_all'] = 'hello';
$queryResponse = $client->search($searchParams);
print_r($queryResponse); // SUCCESS
will find the new value but a search like this:
$client = new Client();
$searchParams['index'] = 'document';
$searchParams['type'] = 'example_type';
$searchParams['body']['query']['match']['_all'] = 'hel';
$queryResponse = $client->search($searchParams);
print_r($queryResponse); // NO RESULTS
does not
There is no type "list" in elasticsearch. But you can use "string" field type and store array of values.
....
'comments' => [
'type' => 'string',
'analyzer' => 'my_ngram_analyzer',
'term_vector' => 'yes',
'copy_to' => 'combined'
],
....
And index a document this way:
....
$params['body'] = array(
'document_id' => 'id_here',
'title' => 'my_title',
'authors' => [],
'comments' => ['comment1', 'comment2']);
....
As for the script for apending an element to array, this answer may help you - Elasticsearch upserting and appending to array
However, do you really need to update the document? It might be easier to just reindex it as this is exactly what Elasticsearch does internally. It reads the "_source" property, does the required modification and reindexes it. BTW, this means that "_source" must be enabled and all properties of the document should be included into it.
You also may consider storing comments and authors (as I understand these are authors of comments, not the document authors) as child document in ES and using "has_child" filter.
I can't really give you specific solution, but strongly recommend installing Marvel plugin for ElasticSearch and use its "sense" tool to check how your overall process works step by step.
So check if your tokenizer is properly configured by running tests as described at http://www.elastic.co/guide/en/elasticsearch/reference/1.4/indices-analyze.html.
Then check if your update script is doing what you expect by retrieving the document by running GET /document/example_type/some_existing_id
The authors and comments should be arrays, but not strings.
Finally perform the search:
GET /document/_search
{
'query' : {
'match': { '_all': 'hel' }
}
}
If you're building the query yourself rather than getting it from the user, you may use query_string with placeholders:
GET /document/_search
{
'query' : {
'query_string': {
'fields': '_all',
'query': 'hel*'
}
}
}
Anyone know how to insert data from a single form to multi tables in codeigniter
i tried below method but it is not working
Model
function add_models(){
$data1 = array(
'companykeyid' => $this->input->post('ckeyid'),
'name' => $this->input->post('name'),
'age' => $this->input->post('age'),
);
$data2 = array(
'companykeyid' => $this->input->post('ckeyid'),
'phrase' => $this->input->post('phrase'),
'medialength' => $this->input->post('medialength'),
);
$data3 = array(
'companykeyid' => $this->input->post('ckeyid'),
'phrase' => $this->input->post('phrase')
'medialength' => $this->input->post('medialength'),
);
$this->db->insert('girls', $data1);
$this->db->insert('movies',$data2);
$this->db->insert('keywords',$data3);
}
Method you made is, actually working, i think that your problem is syntax error you have (missing comma in data3 array).
So, this should work:
function add_models(){
$data1 = array(
'companykeyid' => $this->input->post('ckeyid'),
'name' => $this->input->post('name'),
'age' => $this->input->post('age')
);
$data2 = array(
'companykeyid' => $this->input->post('ckeyid'),
'phrase' => $this->input->post('phrase'),
'medialength' => $this->input->post('medialength')
);
$data3 = array(
'companykeyid' => $this->input->post('ckeyid'),
'phrase' => $this->input->post('phrase'),
'medialength' => $this->input->post('medialength')
);
$this->db->insert('girls', $data1);
$this->db->insert('movies',$data2);
$this->db->insert('keywords',$data3);
}
Important - you have to be sure that field names in tables are right... If this doesn't work, your problem is somewhere else in code (check your controller, view...)
In the array, you call the last value don't have "," get read of it and your model working correctly.
$data1 = array(
'companykeyid' => $this->input->post('ckeyid'),
'name' => $this->input->post('name'),
'age' => $this->input->post('age') <-----
);
In sinisake's answer shouldn't:
function add_models()
be chaged to:
function add_models($data)
Seems like there will be data to pass from the controller.
I had asked a question here a while back about setting up database populated dropdowns for SugarCRM. I received a really good answer and, after more php studies and a dev instance running, I decided to give it a shot. The instructions I followed can be found here. After I run the repair and rebuild, I would expect to see the custom field in my Fields list under the module in studio, but have not been able to find it. The module is named Makers (a1_makers as a database table). For good orders sake, there were no errors when I repaired/rebuilt after saving the files. Per the instructions, I first created a php file with a custom function to query the database (custom/Extension/application/Ext/Utils/getMakers.php):
<?php
function getMakers() {
static $makers = null;
if (!$makers){
global $db;
$query = "SELECT id, name FROM a1_maker";
$result = $db->query($query, false);
$accounts = array();
$accounts[''] = '';
while (($row = $db->fetchByAssoc($result)) !=null) {
$accounts[$row['id']] = $row['name'];
}
}
return $makers;
}
?>
Then, I set 'function' field in Vardefs to point to the function (custom/Extension/modules/Maker/Ext/Vardefs/makers_template.php):
<?php
$dictionary['Maker']['fields']['list_of_makers'] = array (
'name' => 'list_of_makers',
'vname' => 'LBL_MKRLST'
'function' => 'getMakers',
'type' => 'enum',
'len' => '100',
'comment' => 'List of makers populated from the database',
);
?>
Unfortunately, there are no errors and the repair/rebuild runs fine. I am just unable to see the custom field when I go into studio. Can anyone please help point out what I may be doing wrong?
I would recommend checking existence of newly created field 'list_of_makers' in cache/modules/Maker/Makervardefs.php file. If new field definition exists in that file, try add 'studio' => 'visible' to custom/Extension/modules/Maker/Ext/Vardefs/makers_template.php to get something like this:
<?php
$dictionary['Maker']['fields']['list_of_makers'] = array (
'name' => 'list_of_makers',
'vname' => 'LBL_MKRLST'
'function' => 'getMakers',
'type' => 'enum',
'studio' => 'visible'
'len' => '100',
'comment' => 'List of makers populated from the database',
);
Try to edit your custom/modules/Maker/metadata/editviewdefs.php manually and insert field definition by hand in proper place if everything above won't work.
$dictionary['Maker']['fields']['list_of_makers'] = array (
'name' => 'list_of_makers',
'vname' => 'LBL_MKRLST'
'function' => 'getMakers',
'type' => 'enum',
'studio' => 'visible'
'len' => '100',
'comment' => 'List of makers populated from the database',
'studio' => array(
'listview' => true,
'detailview' => true,
'editview' => true
),
);