post an array and iterate throught it in PHP codeigniter - php

This is the first time i create my own webservice (someone always did it for me before), so please bear with me.
I post this array :
$data = array(
'user_id' => $this->post('user_id'),
'group_id' => $this->post('group_id'),
'child_id' => $this->post('child_id'), //will be nested array
'custom' => $this->post('custom'),
'time' => $this->post('time'),
'date' => $this->post('date')
);
I tried to create a nested array with this : $this->post('child_id'), because user can post multiple child_id at once.
Then i tried to iterate through the child_id, because i need to insert them to the mysql :
for($i = 0; $i < sizeof($data['child_id']); $i++)
{
$result2 = $this->schedule_m->add_trans('transaction_schedule', $data, $result_id[0]['id']);
}
What should i do, so i can have an array of child_id in my $data array? (nested array)
And how to iterate through it?
UPDATE :
I have updated the codes above.
I use advanced rest client for testing, and i tried to post something like this in the form content type :
child_id=1&user_id=1&group_id=1&custom=&time=17%3A17%3A00&date=&child_id=2
Notice that theres two child_id (left most and right most), but only the last one (right most) is inserted.
And this is the add_trans in the model :
function add_trans($table, $data, $schedule_id) {
$query = $this->db->insert($table, array('child_id' => $data['child_id'], 'schedule_id' => $schedule_id));
return $query;
}
Thanks a lot for your time.

Even thought you set the name attribute as child[] on the markup,
You still need to call it as:
'child_id' => $this->post('child_id')
It will still return an array.
for($i = 0; $i < sizeof($data['child_id']); $i++) {
$result2 = $this->schedule_m->add_trans('transaction_schedule', $data, $result_id[0]['id']);
}
EDIT:
Looking upon you query string, that seems to be the culprit:
child_id=1&user_id=1&group_id=1&custom=&time=17%3A17%3A00&date=&child_id=2
^ same index , same index, same index, it will overwrite and you will get only `2`
If you want to get them all into an array format, you need to set them like this
child_id[]=1&user_id=1&group_id=1&custom=&time=17%3A17%3A00&date=&child_id[]=2
^ it needs to be set like this
UPDATE:
And in your model, if you want each id per row, well you can also loop in this case:
function add_trans($table, $data, $schedule_id) {
foreach($data['child_id'] as $child_id) {
$query = $this->db->insert($table, array('child_id' => $child_id, 'schedule_id' => $schedule_id));
}
// return $this->db->insert_id();
return $query;
}

ofcourse that won't work, it has to be
for($i = 0; $i < sizeof($data['child_id']); $i++)
{
$result2 = $this->schedule_m->add_trans('transaction_schedule', $data['child_id'][$i], $result_id[0]['id']);
}
because you've not set $data['child_id[]'] so it doesn't exist, the key is just a string or number, it does not validate or parse anything

you don't need to give child[] in post method. just give only child, it will get complete array what are you sending from views
replace
'child_id' => $this->post('child_id[]')
with
'child_id' => $this->post('child_id')

Related

How to increment MySQL field by one if one or more items are checked in form?

I have a page where user can vote which gaming platform (for example) is the best. In MySQL I have a table of these items. I want to update 'count' field and set it to +1 every time when specified item is checked.
After form is submitted I get an array of selected items:
array [
0 => "XBOX"
1 => "PS4"
2 => "PC"
]
Now, I want to check and compare this array with MySQL fields and increase their count values by 1.
I am trying to compare array with MySQL with this, but unsuccessfully.
$value = Input::get('platform'); //this produces presented array
$test = Platform::where('name', 'LIKE', implode(" ", $value))->get();
I think you should use whereIn instead of where
$test = Platform::whereIn('name', $value)->get();
Update:
You can do this by DB::raw():
DB::table('Platforms')
->whereIn('name', $value)
->update([
'count' => DB::raw('count + 1')
]);
I'm not familiar with your query builder, but in SQL you would just do something like this:
UPDATE table_name SET counter=(counter+1) WHERE name IN ('XBOX', 'PS4', PC');
Where table_name is your table name and counter is the name of the field that keeps track of the counts.
This will increment each matched platform by 1.
Now it works. If someone needs code example, here it is. Thank you guys.
public function vote()
{
$value= Input::get('platform');
$test = Platform::whereIn('name', $value)->get();
for ($i = 0; $i < count($test); $i++) {
$test[$i]->count += 1;
$test[$i]->save();
}
}

MongoDB/PHP - MapReduce Max value

I used to group on mongoDB via PHP to get the max date of my items.
As i have too many items (more than 10 000), i read i must use MapReduce.
Here's my past group function :
$keys = array('ItemDate'=> true);
$initial = array('myLastDate' => 0);
$reduce = "function(obj, prev) {
if (myLastDate < obj.ItemDate) {
myLastDate = ItemDate;
}
}";
$conds = array( 'ItemID' => (int) $id );
$results = $db->items->group($keys, $initial, $reduce,
array('condition'=> $conds ) );
I've tried something but seems not to work ...
$map = new MongoCode("function() {
emit(this.ItemID,this.ItemDate);
}");
$reduce = new MongoCode("function(obj, prev) {
if(prev.myLastDate < obj.ItemDate) {
prev.myLastDate = obj.ItemDate;
}
}");
$items = $db->command(array(
"mapreduce" => "items",
"map" => $map,
"reduce" => $reduce,
"query" => array("ItemID" => $id);
$results = $db->selectCollection($items['result'])->find();
Can you please help ?
Solution
You don't need to use map/reduce for that. Provided your date field contains an ISODate, a simple query does the trick:
db.yourColl.find({},{_id:0,ItemDate:1}).sort({ItemDate:-1}).limit(1)
In order to have this query done efficiently, you need to set an index on ItemDate
db.yourColl.createIndex({ItemDate:-1})
Explanation
The query
Let us dissect the query. db.yourColl...
.find({} The default query
,{_id:0,ItemDate:1} We want only ItemDate to be returned. This is called a projection.
.sort({ItemDate:-1}) The documents returned should be sorted in descending order on ItemDate, making the document with the newest date the first to be returned.
.limit(1) And since we only want the newest, we limit the result set to it.
The index
We create the index in descending order, since this is the way you are going to use it. However, if you need to change the default query to something else, the index you create should include all fields you inspect in the query, in the exact order.

Laravel "Trying to get property of non-object" Setting Array with Database Values

I'm Trying to solve this error i'm having with PHP, i'm not completely familiar with the Language, so it would be nice if you would help me out, I can't figure out this error.
I have this Code Here:
public function index() {
$counterino = ClientsJobs::all()->count();
$MasterArray = array();
/* Go Through All of the Records in the Client-Jobs Table and Resolve their columns to Desired Names */
for ($i = 1; $i <= $counterino; $i++ ) {
//Temporary Array for one Name-Resolved-Row of the Table.
$tempArray = array(
'id' => ClientsJobs::find( $i )->id, // id
'client_name' => ClientsJobs::find( $i )->clients->fname , // get the first name ( based on fk )
'job_name' => ClientsJobs::find( $i )->jobs->name, // get the name of the job ( based on fk )
'wage' => ClientsJobs::find( $i )->wage, // wage for the job
'productivity'=> ClientsJobs::find( $i )->producivity // productivity level for the job
);
$MasterArray[] = $tempArray; //add the row
}
return $MasterArray;
}
This code changes the names of the of the Columns in the ClientsJobs Junction Table.
public function up()
{
Schema::create('clients-jobs', function(Blueprint $table)
{
$table->increments('id')->unsigned();
$table->integer('client_id')->unsigned();
$table->foreign('client_id')->references('id')->on('clients');
$table->integer('job_id')->unsigned();
$table->foreign('job_id')->references('id')->on('jobs');
$table->decimal('wage', 4, 2);
$table->decimal('productivity', 5, 2); // 0.00 - 100.00 (PERCENT)
$table->timestamps();
});
}
The Jobs and Clients Table are very simple.
I am having the Error in the index() function I posted above, it says
'Trying to get property of non-object'
Starting on the Line
'client_name' => ClientsJobs::find( $i )->clients->fname,
It's also mad at me for the other parts of setting the array.
I have tested the individual functions I am using to set the array and they all work, fname should also return a string, I used dd() to get the value.
I have tried:
-Using FindorFail
-Setting the Array without the for loop and setting each element manually
-Dumping out multiple parts of the function to make sure it works( counterino, all of the functions for the array, .. )
My guess is that it has to do with the type-deduction of PHP, I actually only need a string array, but would still like to use the name mappings because I am going to be passing this a View I am using for some of my other stuff. The Code was actually working earlier, but I broke it somehow (adding a new record or running a composer update?) anyway, there's some serious voodoo going on.
Thanks in Advance for the help, I am working on this project for a Non-Profit Organization for free.
P.S. I am using Laravel 4.2, and Platform 2.0
First off, this is a horrible practice:
$tempArray = array(
'id' => ClientsJobs::find( $i )->id, // id
'client_name' => ClientsJobs::find( $i )->clients->fname , // get the first name ( based on fk )
'job_name' => ClientsJobs::find( $i )->jobs->name, // get the name of the job ( based on fk )
'wage' => ClientsJobs::find( $i )->wage, // wage for the job
'productivity'=> ClientsJobs::find( $i )->producivity // productivity level for the job
);
By calling ClientJobs::find($i) multiple times, you are doing multiple times the same lookup - either to your DB, or to your cache layer if you have one configured.
Secondly, the answer to your question depends on your ClientJobs model. For your example to work, it needs:
A valid clients relations, defined as follows:
public function clients()
{
return $this->hasOne(...);
}
clients also needs to be a valid 1:1 always existing relation. i.e. there must always be one client. If there isn't, you are susceptible to the error you just got (as the `clients̀ magic would end up being null)
The same applies to jobs.
In every case, it is better to make sure everything is set first. Check using the following:
$clientJob = ClientJobs::find($i);
if (!$clientJob->clients || $clientJob->jobs) throw new \RangeException("No client or job defined for ClientJob $i");
And then catch the exception at whichever level you prefer.
Best approach
public function index() {
$masterArray = array();
ClientsJobs::with('clients', 'jobs')->chunk(200, function($records) use (&$masterArray) {
foreach ($records as $record) {
$masterArray[] = array(
'id' => $record->id, // id
'client_name' => !empty($record->clients) ? $record->clients->fname : null,
'job_name' => !empty($record->jobs) ? $record->jobs->name : null,
'wage' => $record->wage,
'productivity'=> $record->productivity,
);
}
});
return $MasterArray;
}
Your Approach is very wrong
If you want to return an array you can do like this
$counterino = ClientsJobs::all()->toArray();
This will fetch all rows from the table and the toArray will convert the object into an array

Match specific words in a string and categorize them

I'm pretty new to PHP so bear with me here. I'm trying to iterate through the words in a string of text, look for specific words, categorize them, and then count the number of times each word category was hit. I was able to do the easy part but I'm having problems counting the number of times each category is matched. Here's the main function that accepts my string:
public function matchThemeTest($query){
$marriageNum = 0;
$criminalNum = 0;
$contactNum = 0;
$keywords = array(
'background'=> array('category'=>'criminal'),
'marriage' => array('category'=>'marriage'),
'criminal' => array('category'=>'criminal'),
'arrest' => array('category'=>'criminal'),
'divorce' => array('category'=>'marriage'),
'person' => array('category'=>'contact'),
'contact' => array('category'=>'contact')
);
foreach (preg_split("/\s/", $query) as $word)
{
if (isset($keywords[$word]))
{
echo $keywords[$word]['category'];
if ($keywords[$word]['category'] == 'marriage') {
$marriageNum++;
}
echo $marriageNum;
}
}
//return reset($matches);
}
I've got a php fiddle setup here: http://phpfiddle.org/main/code/i4g-mdu that I've been playing around with. In it's current form, I can get the words into categories but I'm not sure how to count how many times each category gets matched. I feel like I need an additional loop or something simple to count but I'm not exactly sure where. Any advice is greatly appreciated. Thanks in advance.
You may need another array of data, to store the counts. Use an array like this:
$counts = array(
'criminal' => 0,
'marriage' => 0,
'contact' => 0
);
Then when you iterate through your foreach loop, you can use the $keywords[$word]['category'] as the key in $counts and increment it:
if(isset($keywords[$word]) {
$counts[$keywords[$word]['category']]++;
}
Then you can return the $counts array so the caller can use it to find out what the counts of each theme were:
return $counts;

PHP MySQL building a 3 Tier multi dimensional array

So I have my query, its returning results as expect all is swell, except today my designer through in a wrench. Which seems to be throwing me off my game a bit, maybe its cause Im to tired who knows, anyway..
I am to create a 3 tier array
primary category, sub category (which can have multiples per primary), and the item list per sub category which could be 1 to 100 items.
I've tried foreach, while, for loops. All typically starting with $final = array(); then the loop below that.
trying to build arrays like:
$final[$row['primary]][$row['sub']][] = $row['item]
$final[$row['primary]][$row['sub']] = $row['item]
I've tried defining them each as there own array to use array_push() on. And various other tactics and I am failing horribly. I need a fresh minded person to help me out here. From what type of loop would best suit my need to how I can construct my array(s) to build out according to plan.
The Desired outcome would be
array(
primary = array
(
sub = array
(
itemA,
itemB,
itemC
),
sub = array
(
itemA,
itemB,
itemC
),
),
primary = array
(
sub = array
(
itemA,
itemB,
itemC
),
sub = array
(
itemA,
itemB,
itemC
),
),
)
Something like this during treatment of your request :
if (!array_key_exists($row['primary'], $final)) {
$final[$row['primary']] = array();
}
if (!array_key_exists($row['sub'], $final[$row['primary']])) {
$final[$row['primary']][$row['sub']] = array();
}
$final[$row['primary']][$row['sub']][] = $row['item'];
Something like this....
$final =
array(
'Primary1'=>array(
'Sub1'=>array("Item1", "Item2"),
'Sub2'=>array("Item3", "Item4")
),
'Primary2'=>array(
'Sub3'=>array("Item5", "Item6"),
'Sub4'=>array("Item7", "Item8")
),
);
You can do it using array_push but it's not that easy since you really want an associative array and array_push doesn't work well with keys. You could certainly use it to add items to your sub-elements
array_push($final['Primary1']['Sub1'], "Some New Item");
If I understand you correctly, you want to fetch a couple of db relations into an PHP Array.
This is some example code how you can resolve that:
<?php
$output = array();
$i = 0;
// DB Query
while($categories) { // $categories is an db result
$output[$i] = $categories;
$ii = 0;
// DB Query
while($subcategories) { // $subcategories is an db result
$output[$i]['subcategories'][$ii] = $subcategories;
$iii = 0;
// DB Query
while($items) { // $items is an db result
$output[$i]['subcategories'][$ii]['items'][$iii] = $items;
$iii++;
}
$ii++;
}
$i++;
}
print_r($output);
?>

Categories