I have a table options and I have an array of strings ["value1", "value2", "value3"].
What I'd like to do is check if all of the values within the array are present in the table.
I've tried whereIn but I think it checks if any values exist in the table.
This is what I have done currently:
$v = ["value1", "value2", "value3"];
$options = Options::whereIn('value', $v)->get();
if ($options->count() != count($v)) {
//something must be missing
}
This works, but I wonder if there is a better way? The table has millions of records so I'd like to do only 1 query if possible.
Thanks!
The answer in the comments by justcarty is technically correct, but you can reduce the load by not pulling in the options if you don't intend to use them.
if (Option::whereIn('value', [...])->count() != count([...])) {
//perform action
}
Also note, as justcarty mentioned, this won't work if you have multiple occurrences of a value in your database, but you can get around this by adding DISTINCT clause to your query.
if (Option::distinct(['value'])->whereIn('value', [...])->count() != count([...])) {
//perform action
}
whereIn check specifically for that one value in the arrays.
You can try this:
$search_values = ['value1', 'value2', 'value3'];
$found = true;
foreach ($search_values as $search) {
if (!Search::where('column', $search)->first()) {
$found = false;
}
}
if (!$found) {
// Something must be missing
}
Related
I run a script under xampp with a mysqlDB.
I check if a domainname has an ip.
The problem is, that I have to check over 100000 domain names from a MySQL_DB.
The function "gethostbyname" works great, but my solution is too slow.
while($row = mysqli_fetch_array($db_res)) { // get the DB domainnames entrys
if (empty($row['status'])) {
$items[] = $row['domainnames'];
}
foreach ($items AS $domain) {
if ( gethostbyname($domain) != $domain ) {
do somthing.....
}
}
}
How do I get it faster?
Your foreach() loop inside of your while() loop is simply a bad idea. Think about it.
As you iterate the result set, $items swells and swells -- this means that the foreach() will have to work longer and longer and longer.
Ultimately, if you need to process the gethostbyname() value for the next task in your script, you should be storing that value at the same time that you INSERT the entry into your table the first time -- perhaps the new column can be host.
The smart money is not to call gethostbyname() 100000 times; have the value ready when you SELECT it.
Beyond the above logic, I don't see the need to declare an array with a single element/string, then iterate it.
In fact, your query should contain a WHERE clause that excludes rows that have a null/0/blank status value AND includes rows that have a host (new column) value that matches $domain so that php doesn't have to bother any qualifying/disqualifying conditions.
foreach ($db_res as $row) { // yes, you can simply iterate the result object
// do whatever with the associative string elements (e.g. $row['domainnames'])
// ...you know this is a string and not an array, right? -^^^^^^^^^^^^^^^^^^^
}
thanks for the answers.
With your assistance i was able to reduce the procedure to:
while($row = mysqli_fetch_array($db_res))
{
$domain = $row['domainnames'];
if ( gethostbyname($domain) != $domain ) {
do somthing.....;
}
else{
do somthing.....;
}
}
it feels a little bit faster but not enough.
#mickmackusa i catch now only the empty "status" fields:
$db_res = mysqli_query ($db_link, "select domainnames FROM domaintable WHERE status = ''")
Looks like when your while loop iterates, it uses the $items from the last iteration - which will waste time - so please try this version (putting the foreach into the if:
while($row = mysqli_fetch_array($db_res)) { // get the DB domainnames entrys
if (empty($row['status'])) {
$items[] = $row['domainnames'];
foreach ($items AS $domain) {
if ( gethostbyname($domain) != $domain ) {
do somthing.....
}
}
}
}
I am building a web scraper in PHP and I am not so experimented with all this stuff. What I am trying to achieve is as following:
Split an array of values into strings using foreach
Search any value in a predefined MYSQL table. If value is identical with one of the defined ones, it should be replaced. Otherwise it should remain the same
Put the new values back into an array
Below is my snippet. Basic structure of database is "ID, Marime, Inlocuire". "Marime" is the column to search on, and "Inlocuire" is the column to replace value with.
foreach ($marimi as $marime) {
$sizes[]=trim(strtok($marime->innertext, '-'));
$newArray = array_filter($sizes, 'myFilter');
foreach ($newArray as $marimeFixa) {
$marimeDefinita = $conn->query("SELECT * FROM oc_1_tabelmarimi WHERE Marime = '$marimeFixa'");
if($marimeDefinita->num_rows == 0) {
$marimeFixa = $marimeFixa;
} else {
$marimeFixa = $marimeDefinita['Inlocuire'];
}
$arrayMarimi[] = $marimeFixa;
}
print_r($arrayMarimi);
}
However this doesn't seem to work. Any help is greatly appreciated. Thanks!
try:
$marimeDefinita = $marimeDefinita->fetch_assoc();
before if($marimeDefinita->num_rows == 0) {
or
$marimeFixa = $marimeDefinita->Inlocuire;
I'm having trouble trying to remove null values from an array using values from the database. These null values are usually found within the 'answers'.. Code below:
$getQuestions = mysql_logging_query("SELECT fq.`question_id`, fq.`ques_form_id`, fq.`question_body`, fq.`type`, fq.`answer1`, fq.`answer2`, fq.`answer3`, fq.`answer4`, fq.`answer5`, fq.`answer6`, fq.`min_validation`, fq.`max_validation`
FROM QuestionnaireFormQuestions fq
LEFT JOIN QuestionnaireForms f
ON f.`form_id` = fq.`ques_form_id`
WHERE f.`active` = 1
AND f.`form_id` = '".mysql_real_escape_string($form_id,$this->dbcon)."'
",$this->dbcon);
if($getQuestions && mysql_num_rows($getQuestions)>0 && mysql_error($this->dbcon)=="")
{
$get_questions_array = array();
while($getQuestions && $getQuestions_rec=mysql_fetch_assoc($getQuestions))
{
$get_questions_array[] = array('question_id' => $getQuestions_rec['question_id'],
'related_form_id' => $getQuestions_rec['ques_form_id'],
'question_body' => $getQuestions_rec['question_body'],
'question_type' => $getQuestions_rec['type'],
'possible_answer1' => $getQuestions_rec['answer1'],
'possible_answer2' => $getQuestions_rec['answer2'],
'possible_answer3' => $getQuestions_rec['answer3'],
'possible_answer4' => $getQuestions_rec['answer4'],
'possible_answer5' => $getQuestions_rec['answer5'],
'possible_answer6' => $getQuestions_rec['answer6'],
'min_validation' => $getQuestions_rec['min_validation'],
'max_validation' => $getQuestions_rec['max_validation']
);
}
if(is_array($get_questions_array) && count($get_questions_array)>0)
{
foreach($get_questions_array as $key=>$array)
{
if($array === null) {
unset($get_questions_array[$key]);
}
$return['data']['questions'][] = $array;
}
}
}
else
//error
A return for example; would look like this:
"question_id":"3",
"related_form_id":"4",
"question_body":"Do you like this content?",
"question_type":"radio",
"possible_answer1":"Disagree",
"possible_answer2":"Neutral",
"possible_answer3":"Agree",
"possible_answer4":null,
"possible_answer5":null,
"possible_answer6":null,
"min_validation":"1",
"max_validation":"1"
I've tried unsetting the key using empty and isnull but to no avail. Any help would be appreciated.
You are not testing the values inside the array, you need to:
foreach($get_questions_array as $array){
foreach($array as $key=>$element){
if($element===null)
unset($array[$key]);
}
$return['data']['questions'][] = $array;
}
I think it's possible you're looping through your nested data structure at the wrong level.
You have this $get_questions_array, each element of which is an associative array that came from one row in your MySQL result set. But your php code loops over the rows of the result set, not over the columns.
I think you want something more like this, with another nested foreach.
if(is_array($get_questions_array) && count($get_questions_array)>0)
{
foreach($get_questions_array as $row)
{
foreach ($row AS $colname=>$colvalue)
{
if ($colvalue === null || $colvalue =='')
{
unset($row[$colname]);
}
}
}
}
See what's going on? Your code was throwing away whole rows that were null, but there weren't any of those, so it wasn't doing anything.
why don't you query the data that does not contain nulls, instead of removing the nulls by yourself ? let the database do this for you something like:
select * from table where possible_answer IS NOT NULL
Try this loop through the array and set them to null with the key's if the value is empty
foreach($getQuestions_rec as $key => $value){
if($value == ''){
$getQuestions_rec[$key] = null;
}
}
Use the IFNULL(ColumnName,"") to replace the null values to empty string in SQL query.
Example: IFNULL(answer6,"")
refer this this How to remove null values from an array? or you ca alter the query to select the null values from table.
I've got the following code which is something like a form search engine with multiple inputs where the results are kinda absolute concerning the number of characters etc(perfect match)
.
// build array of field names=============================================================================
$fields=array('user','customer','vessel','country',
'port','eta','service_station','type_of_service',
'case_reference','status');
// initialize empty array for WHERE clauses
$wheres=array();
// loop through field names, get POSTed values,
// and build array of WHERE clauses, excluding false values
foreach ($fields as $field) {
// get existing field value from POST, mark missing or empty value as FALSE
${$field} = isset($_POST[$field]) && trim($_POST[$field])!=''
? trim($_POST[$field]) : false;
// add to array of WHERE clauses only if value is not FALSE
if (${$field}) { $wheres[]="$field='".${$field}."'"; }
}
// build SELECT statement from WHERE clauses
$sql="SELECT * FROM jobs WHERE ".
(!empty($wheres) ? implode(" AND ",$wheres) : '1=1').
";";
What i want to do is add an input in the form
<label for="special">Special Search</label>
<input type="text" name="special" id="special_search">
where the user would be able to search in the case_reference field and get the results that match the first four characters. Also i would like this new input to work the same as the others as far as the AND or OR and TRUE or FALSE statements are concerned.
All help appreciated thank you in advance:)
UPDATE : Instead of rewriting the whole thing i came up with the following code at the begining of my previous :
$joker = $_POST['special'];
$joker1 = substr($joker1, 0, 4);
if(isset($_POST['case_reference']) && !empty($_POST['case_reference'])
&& empty($_POST['special'])) {
} else { $_POST['case_reference'] = $joker1; }
It is working for now but anyone can confirm that it would be okay in future??
From the SQL:
$sql="SELECT * FROM jobs WHERE ". (!empty($wheres) ? implode(" AND ",$wheres) : '1=1').";";
Just simply add a variable for special:
$special = $_POST['special']; // this will get the data from the textbox
then add it to the sql statement
$sql="SELECT * FROM jobs WHERE LIKE $special 'aaaa%' AND ". (!empty($wheres) ? implode(" AND ",$wheres) : '1=1').";";
Rewritten avoiding variable variable names, and using mysql_real_escape_string (although you should use mysqli or pdo):-
<?php
// build array of field names=============================================================================
$fields=array('user','customer','vessel','country',
'port','eta','service_station','type_of_service',
'case_reference','status');
// initialize empty array for WHERE clauses
$wheres = array('1=1');
// loop through field names, get POSTed values,
// and build array of WHERE clauses, excluding false values
foreach ($fields as $field)
{
// get existing field value from POST, mark missing or empty value as FALSE
if (isset($_POST[$field]) && trim($_POST[$field])!='')
{
$wheres[]="`$field`='".mysql_real_escape_string(trim($_POST[$field]))."'";
}
}
if (isset($_POST['special']) && trim($_POST['special'])!='')
{
$wheres[] = " case_reference' LIKE '".mysql_real_escape_string(trim($_POST['special']))."%'";
)
// build SELECT statement from WHERE clauses
$sql="SELECT * FROM jobs WHERE (".implode(" AND ",$wheres).") ;";
?>
Example: my current result set:
array(7) {[0]=>array(2)
{ ["class_id"]=>string(1) "1"["class"]=>string(3)"1st"}
{ ["class_id"]=>string(1) "2"["class"]=>string(3)"2nd"}
{ ["class_id"]=>string(1) "3"["class"]=>string(3)"3rd"}
I want a new result set as :
array(7) {[0]=>array(2)
{ ["new_id"]=>string(1) "1"["new_class"]=>string(3)"1st"}
{ ["new_id"]=>string(1) "2"["new_class"]=>string(3)"2nd"}
{ ["new_id"]=>string(1) "3"["new_class"]=>string(3)"3rd"}
I dont want this to affect the column names in my database. only the result set.
Show us your query.. If you're doing, for example, the following query:
SELECT class_id, class FROM table;
Change it to this:
SELECT class_id AS new_id, class AS new_class FROM table;
Changing it in the query is hands-down the best way to do it, as you're not having to do any extra work within PHP, however you could also amend them in PHP, of course.
// where $resultset is your original results..
foreach ($resultset as &$result) {
$result_ = array('new_id' => $result['class_id'], 'new_class' => $result['class']);
$result = $result_;
}
Note that neither of these methods would affect your database columns. The only way to do that would be via an ALTER|MODIFY TABLE statement.
try this
function rename_key(&$array, $oldkey, $newkey) {
// remember here we send value by reference using `&`
if(array_key_exists($oldkey,$array))
{
$array[$newkey] = &$array[$oldkey];
unset($array[$oldkey]);
}
return $array;
}
foreach($input as $k)
{
rename_key($k, 'class_id', 'new_id');
rename_key($k, 'class', 'new_class');
$output[]=$k;
}
echo "<pre>";
print_r ($output);
In foreach cycle. Create a new array with needed to you colums from existing result set.