I have questions model in laravel that has a database structure like this:
question_id | is_active
------------+-----------
1 | Y
2 | Y
3 | N
... | ...
I have an input in form of an array that i want to validate with questions model, this array will contain key that act as the question_id and the value as the question answer, that looks like this:
$QnAs = [
'1' => '3',
'2' => '5',
'4' => '1',
'6' => '4',
'7' => '2',
'8' => '0',
]
The validation system will required all the Active (is_active == 'Y') questions that present in the array as question_id as the key of array to represent it and the value of each array is 1, 2, 3, or 4.
I can achieve that by looping through every question that active like this:
$collections = Questions::where('is_active','Y')->get();
foreach($collections as $collection){
if(!array_key_exists($collection->question_id,$QnAs)){
return false; // doesn't find the question id in array key input
} elseif(!in_array($QnAs[$collection->$question_id],['1','2','3','4'])){
return false; // input value for this array does not match with required value
}
}
the problem with this code is , when i process 15k++ data it will take a long time too process because it has to loop through every model collection , is there any other approach that can simplify the code and the process ?
Your code wont work . Beacause return will immediately end the execution of current function. So the checking will be done only with the first value in collections and it will return the result based on the first element in the array $collections.
you can change the code as following :
$collections = Questions::where('is_active','Y')->get();
$result = true;
foreach($collections as $collection)
{
if(!array_key_exists($collection->question_id,$QnAs))
{
$result = false; // doesn't find the question id in array key input
}
}
return $result;
The above code will work
You can research more for greater performance
The problem is you are getting all of the active questions,
so the point is to limit the datas,
Firstly, add composite index on question_id and is_active
$table->index(['question_id', 'is_active']);
And try this code:
$QnAs = [
'1' => '3',
'2' => '5',
'4' => '1',
'6' => '4',
'7' => '2',
'8' => '0',
];
// filter elements allowed:
$valid_QnAs = array();
foreach($QnAs as $k => $v) {
if (in_array($v, [1,2,3,4])) {
$valid_QnAs[$k] = $v;
}
}
$not_in_active = Questions::where('is_active','Y')
->whereNotIn('question_id', array_keys($valid_QnAs))
->exists();
if ($not_in_active) return false;
Related
How can I get data by grouping user_id for a foreach loop in a controller's function in Laravel. For example, user_id = 2, 5 rows available, user_id = 1, 10 rows available. Then show 2 arrays.
$lists = lists::wherestatus(1)->groupby('user_id')->get();
foreach($lists as $list){
$list = functionHere;
}
What function can I create for this on the controller for grouping?
I need more information, but based on what you shared, you should be able to do this (removing the foreach):
$lists = Lists::whereStatus(1)->get()->groupBy('user_id');
The difference is that if you use groupBy before get, you are grouping your query by user_id, so instead of getting 5 rows for user_id = 2 and 10 for user_id = 1, you are going to get 2 rows and just the latest data, so you need to use Collection's groupBy.
What you want to do is group all the information by user_id but have each row, a schema like this:
[
'1' => [ // user_id
['user_id' => '1', 'column1' => 'random value'],
['user_id' => '1', 'column1' => 'other value'],
// 8 remaining rows
],
'2' => [ // user_id
['user_id' => '2', 'column1' => 'other nice value'],
// 4 remaining rows
],
]
you should first in List model set:
public function scopeStatus(){
return $this->where('status','1');
}
and in your controller:
$products = List::status()->groupby('user_id')->get();
how can i get something randomly from a array for example i have this array I want to grab one of those lines randomly how can I do that using PHP?
$quizes = array(
'3-1' => '2',
'4+4' => '8',
'7-5' => '2',
'4+2' => '6',
'9-3' => '6',
'1+2' => '3',
'9+9' => '18',
'3+2' => '5',
'2*3' => '6',
'5*3' => '15',
'6+6' => '12',
'3+4' => '7',
'7-4' => '3',
'6+2' => '8',
'3*2' => '6',
'7+6' => '13',
'1+1' => '2',
'4*4' => '16',
'10-3' => '7'
);
What i have tried
$rand_keys = array_rand($quizes, 2);
echo $quizes[$rand_keys[0]] . "\n";
echo $quizes[$rand_keys[1]] . "\n";
but this only returns results such as 2 7, 15 2, 3 2 and more
Please help thank you
You can randomize the array order and take the first element. The code would look like this:
shuffle($quizes);
Well, you are getting exactly what you are asking for - value that belongs to randomly chosen key.
To get key => value pair execute:
echo $rand_keys[0] . " => " . $quizes[$rand_keys[0]] . "\n";
Of course you can format output however you'd like to.
Each of the "rows" in your code is actually two parts: a key and its corresponding value. For example, in the first row '3-1' is the key and '2' is its value. The => operator indicates this relationship.
The array_rand function you used will return a random key (or set of keys, if you specify the second parameter) from your array.
$key = array_rand($quizes); // returns a random key e.g. '3-1'
Then you can use that key to get the corresponding value,
$value = $quizes[$key]; // returns the value that matches $key
There are various ways to output them from that point. If you want it to look kind of like it does in the code, you can use
echo "$key => $value";
So basically I have an array mutator which works perfectly, but the field its pulling is only a char 1 and only 1 entry so it works fine
However I want to do the exact same thing with a field that contains multiple entries by a comma separator. below is what i have that works and and example of what I want.
The field interests contains a number from 1 to 3,
protected $userTypes = array(
'1' => 'Owner',
'2' => 'Admin',
'3' => 'Standard User'
);
public function getUserTypeAttribute($value)
{
return $this->userTypes[$value];
}
now I have another field lets call it, InterestList but it has multiple entries separated by commas like so 3,4,5,6,7
How would I get the code like above to work for something like that?
Try this --
<?php
// lets define the interest list
protected $interestList = array(
'1' => 'Play',
'2' => 'Sing',
'3' => 'Hobby'
);
// function for getting the interesttype strings
public function getIntestetTypeString($intStr=''){
// $intStr = '1,3' ; may be something like
$interestList = '';
if(!empty($intStr)){
$attrToIterate = explode(", ",$intStr) ;
foreach($attrToIterate as $value){
if($interestList){
$interestList .= ','. $this->interestList[$value] ;
}else{
$interestList .= $this->interestList[$value] ;
}
}
}
return $interestList ;
}
Hey so I ended up with an answer, Below is the code
public function getInterestsAttribute($value)
{
$InterestList = array(
'1' => 'Books',
'2' => 'Cars',
'3' => 'Cats'
);
$strExplode = explode(",",$value);
foreach ($strExplode as $i=>$ANUMBER){
echo $InterestList[$ANUMBER];
}
}
Then in the blade you just go about your way as normal. eg.
{{ $UserProfile->Interests }}
In CodeIgniter I'm trying to create a function. Need create array who will delete rows in db like:
$selected_items_by_id = array('1','2','3','4',); // --<<<Need Create This
$this->db->where_in('id', $selected_items_by_id);
$this->db->delete('mytable');
mytabe DB Structure of:
ID | NAME | PARENT_ID
1 Item1 0 // First Root item
2 Item2 1 // First Root sub item
3 Item3 2 // First Root sub sub item
4 Item4 3 // First Root sub sub sub item
5 Item5 0 // Second Root item
Items layout:
Item1
+Item2
++Item3
+++Item4
Item5
Here I'm getting the needed item id (from select box):
$id = $this->input->post('delete_menu_item');
Logic:
If item parent_id == 0, then item is root.
If Item is root item, in array will be only root item id
In array need $id and all $id subs (if they exist)
UPDATE
I try to make recursive function outside from CI.
Search function - to separate the necessary subaray:
function search($array, $key, $value)
{
$results = array();
if (is_array($array))
{
if (isset($array[$key]) && $array[$key] == $value)
$results[] = $array;
foreach ($array as $subarray)
$results = array_merge($results, search($subarray, $key, $value));
}
return $results;
}
I'm using this array, based on DB entries:
$array = array(
array('id' => '1', 'name' => 'Item1', 'parent_id' => '0'),
array('id' => '2', 'name' => 'Item2', 'parent_id' => '1'),
array('id' => '3', 'name' => 'Item3', 'parent_id' => '2'),
array('id' => '4', 'name' => 'Item4', 'parent_id' => '3'),
array('id' => '5', 'name' => 'Item5', 'parent_id' => '0'),
);
Recursive function:
function build_array($array,$id, $final = NULL){
$data = search($array, 'id', $id);
foreach ($data as $item):
if ($item['parent_id'] == 0){
$final[] = $item['id'];
}
else {
$parent_id = $item['parent_id'];
$final[] = $item['id'];
$final[] = $parent_id;
build_array($array, $parent_id, $final);
// Here go recursive
}
endforeach;
return $final;
}
$result = build_array($array,1);
var_dump($result);
What should be the function recursively?
If I understand what you are asking, you'll need to handle each item iteratively (in a loop).
So first you get an item, then you see if it has a parent - if so, get it's parent and start again, etc. This is one of the few cases where recursive functions can really come in handy.
You just build your final arrays as you go, until you run out of items - being aware that if you aren't careful you will get an infinite loop as you pull the same items over and over again.
Without more information on what you have to input and what you want to get as output, this is about as helpful as anyone can be. For more help you'll need to clarify what you want as output, code you've tried so far and what it's doing that you don't want, etc.
Ok. I will use the sample array you put together, only slightly different: Since ids are unique, there's no reason why they shouldn't serve as keys. Like so:
$array = array(
'1'=>array('name' => 'Item1', 'parent_id' => '0'),
'2'=>array('name' => 'Item2', 'parent_id' => '1'),
'3'=>array('name' => 'Item3', 'parent_id' => '2'),
'4'=>array('name' => 'Item4', 'parent_id' => '3'),
'5'=>array('name' => 'Item5', 'parent_id' => '0'),
);
Add the following methods to your controller/model/lib/whatever:
function children_of($arr,$id)
{
$r=array();
foreach($arr as $key=>$entry)
if($entry['parent_id']==$id) $r[]=$key;
return $r;
}
function subtree_array($arr,$id)
{
if(isset($arr[$id]))
{
$r=array($id);
foreach($this->children_of($arr,$id) as $child)
$r=array_merge($r,$this->subtree_array($arr,$child));
return $r;
}
else
return array(0); // (0) comes handy in SQL IN operations
}
children_of() returns the immediate children of $id in $arr.
subtree_array() returns an array including $id and all of its descendants in $arr. If $id is not a key of $arr, it returns array(0). That's because you say you want to use it in an SQL query, and a where clause like where xyz in () would be bogus, while where xyz in (0) wouldn't, and also would always return false since no item has a zero id (it seems to be reserved to denote root nodes).
So, the usage might be something like:
$id=$this->input->post('delete_menu_item');
$selected_items_by_id=subtree_array($aray,$id);
I tried to approach the task from the other side.
Using cascade delete, and everything is going sql side:
CREATE TABLE `navigation` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL COLLATE 'utf8_general_ci',
`url` VARCHAR(50) NOT NULL COLLATE 'utf8_unicode_ci',
`position` MEDIUMINT(8) NOT NULL DEFAULT '100',
`parent_id` INT(11) NOT NULL,
PRIMARY KEY (`id`),
INDEX `parent_id` (`parent_id`),
CONSTRAINT `FK1` FOREIGN KEY (`parent_id`) REFERENCES `navigation` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB;
Thank you for your suggestions.
Please I have a table with three columns :
id (this is the id of my table)
parent (this is the parent)
position (and this is the position)
And I have this array $_arr['menu'] :
array (size=3)
13 =>
array (size=1)
'parent' => string '0' (length=1)
14 =>
array (size=1)
'parent' => string '13' (length=2)
25 =>
array (size=1)
'parent' => string '0' (length=1)
I want to update may table with those values in the array $_arr['menu'].
I imagine to do something like but in one query (perhaps using case in) :
UPDATE table SET position = 1, parent = 0 WHERE id = 13;
UPDATE table SET position = 2, parent = 13 WHERE id = 14;
UPDATE table SET position = 3, parent = 0 WHERE id = 25;
Please masters, how to get those values from that array and how to do the update !
Thanks a lot
I'm not sure I got your question, but I'll write my snippet. (I don't remember php syntax well and it's not tested, but I think it shows what I want to say)
try {
$db->beginTransaction();
$increment = 0;
foreach ($arr as $id => $innerArray) {
$db->query("UPDATE table SET position = ".(++$increment).", parent = ".$innerArray['parent']." WHERE id =".$id);
}
$db->commit();
} catch (Exception $e) {
$db->rollback();
}