I have dynamic where conditions. They consist of the following array:
array:2 [
"brand_name" => array:2 [
0 => "a"
1 => "b"
]
"category_type" => array:1 [
0 => "AA"
]
]
I need to apply where conditions to my query.
$em = $this->getEntityManager();
$sql = " select * from products as p";
$i = 0;
foreach ($wheres as $key => $value) {
if ($i === 0) {
$sql .= " WHERE";
} else {
$sql .= " AND";
}
$sql.= " te.$key IN (:$key)";
$i +=1;
}
I am not sure how to assign the value to the query. If I had single where condition, I did something like this:
$params = array(
$ids,
);
$query = $em->getConnection()->executeQuery(
$sql,
$params,
array(
\Doctrine\DBAL\Connection::PARAM_STR_ARRAY,
\PDO::PARAM_INT,
)
);
$records = $query->fetchAll();
But I don't know how to fix where where conditions are in dynamic.
This is very easy using the query builder. It's the kind of thing it was designed for.
Something like this would take you there:
$qb = $this->createQueryBuilder('p');
$suffix = 0;
foreach ($conditions as $key => $value) {
$parameter = 'query_' . $suffix++;
$qb->andWhere("p.$key IN :$parameter")
->setParamter($parameter, $value);
}
$records = $qb->getQuery()->getResult()
You'll need to make adjustments to suit your data model. In your question you are selecting products as p, but then you are trying to select from te, so I guess some pieces are missing from the puzzle.
But you should be able to finish it from here.
Related
I am writing a function in which I can do a couple of database actions, in this case an insert data based on a simple array
"insert" => array (
"1" => array (
"tnt_role" => array (
"rolename" => array (
"value" => "administrator",
"notation" => "string"
)
)
),
"2" => array (
"tnt_role" => array (
"rolename" => array (
"value" => "user",
"notation" => "string"
)
)
),
"3" => array (
"tnt_users" => array (
"username" => array (
"value" => "administrator",
"notation" => "string"
),
"userpassword" => array (
"value" => md5('admin', FALSE),
"notation" => "string"
),
"email" => array (
"value" => "someone#something.com",
"notation" => "string"
),
"roleid" => array (
"value" => "1",
"notation" => "int"
)
)
)
)
and here is the specific part of the function
case "insert":
foreach ($tables as $instance => $inserttables) {
foreach ($inserttables as $table => $fields) {
// create a count on the number of fields that are being parsed
$countfields = count($fields);
$sql = "INSERT INTO ". $table ." (" ;
$i = 0;
// set up the columns for the insert statement
foreach ($fields as $field => $value) {
$i++;
$sql .= $field;
if ($countfields != $i ) {
$sql .= ", ";
}
}
// close the column statement, open the value statement, since this is prepared, we will add question marks and add later the values
$sql .= ") ";
$sql .= "VALUES (";
$i = 0;
$parameters = "";
$notation = "";
foreach ($fields as $field => $value) {
$i++;
$sql .= "?";
// set up the notation in the bind parameters
switch($value['notation']) {
case "int":
$notation .= "i";
break;
case "string":
$notation .= "s" ;
break;
}
// need to escape the email and username values
$parameters .= "'".$value['value']."'" ;
if ($countfields != $i ) {
$sql .= ", ";
$parameters .= ", ";
}
}
$sql .= ")";
$stmt = mysqli_prepare($con, $sql);
mysqli_stmt_bind_param($stmt, $notation, $parameters);
if(mysqli_stmt_execute($stmt)) {
echo "data entered";
} else {
echo "error in following query:". $sql;
}
}
}
break;
This works all fine except for 1 tiny thing and that is when I enter more than 1 item in the database. It gives me the following error
mysqli_stmt_bind_param(): Number of elements in type definition string
doesn't match number of bind variables in .... line 647
I realized after a while that it is the parameter variable that is the case. The bind parameter here is only 1 variable in which I separate it all nicely with a comma (in order to mimic the list). Viewing this optical would say this looks fine, however I think the bind parameter statement really requires separate variables. At this point it sees actually just one variable, rather than the 4 in my test case.
I tried looping it this way:
mysqli_stmt_bind_param($stmt, $notation,
foreach ($fields as $field => $value) {
echo $value['value'];
if ($countfields != $i ) {
echo ",";
}
}
);
But to no avail, since it will spit out the following.
Parse error: syntax error, unexpected 'foreach' (T_FOREACH) in
Does anybody have an idea how to solve this issue?
== edit ==
table structure as requested, although I doubt it is that problem, since I get a bind parameter error, not an error in executing the statement.
== edit 2 ==
also tried the following, which didn't help, since it didn't stack (I saw this in PDO)
foreach ($fields as $field => $value) {
switch($value['notation']) {
case "int":
$notation = "i";
break;
case "string":
$notation = "s" ;
break;
}
mysqli_stmt_bind_param($stmt, $notation, $value['value']);
}
You need to pass each variable individually to mysqli_stmt_bind_param, so $parameters needs to be an array, not a string. Change the following lines of code:
$parameters = "";
to:
$parameters = array();
and
$parameters .= "'".$value['value']."'" ;
to:
$parameters[] = $value['value'];
(note there is no need to escape values when you are using prepared statements)
remove this line:
$parameters .= ", ";
and finally, change
mysqli_stmt_bind_param($stmt, $notation, $parameters);
to:
mysqli_stmt_bind_param($stmt, $notation, ...$parameters);
and it should work fine.
I have country list in array with multiple array, like:
public static function listCountries()
{
$this->country = array(
array(1, 'SAD', 'sad.png'),
array(2, 'Argentina', 'argentina.png'),
array(3, 'Australija', 'australija.png'),
array(4, 'Novi Zenland', 'noviz.png'),
array(5, 'Belgija', 'belg.png'),
array(6, 'Nizozemska', 'nizozemska.png')
);
}
But when i do foreach for array, i'm getting this:
//From DB
$item->country = "1,4";
$item->country = explode(",", $item->country);
for($i=0; $i < count($item->country); $i++) {
$index = $item->country[$i];
if( !empty($this->country[$index]) ) {
$item->country[$i] = $this->country[$index];
}
}
$item->country = implode(",", $item->country);
echo $item->country;
But i'm getting something like this:
array:2 [▼
0 => array:3 [▼
0 => 5
1 => "Belgija"
2 => "belg.png"
]
1 => array:3 [▼
0 => 2
1 => "Argentina"
2 => "argentina.png"
]
]
1 = SAD, 4 = Novi Zenland, not Belgija and Argentina
There is no good country, also no data what i want. How to fix this?
You can use this foreach loop to go through the other array and swap the string if the number matches:
$item->country = "1,4";
$item->country = explode(",", $item->country);
for($i=0; $i < count($item->country); $i++) {
$index = $item->country[$i];
foreach($this->country as $c) {
if($c[0] == $index) {
$item->country[$i] = $c[1]; // or $item->country[$i] = $c; if you want all three items
break;
}
}
}
$item->country = implode(",", $item->country);
echo $item->country;
// Should output: SAD,Novi Zenland
The indexes in arrays are 0-based, which means that:
$index = $item->country[$i];
Has to become
$index = $item->country[$i - 1];
To correlate with the country ids. Otherwise, it is always one off. This is assuming that the ids are always ordered from least to greatest, and all ids are a continuous range.
Edit :
i Want a structure like this
'categories' => [
[
'name' => "science" ,
'questions' => [
[
'question' => 'C1_Q2',
'answer' => 'C1_A2',
],
[
'question' => 'C1_Q3',
'answer' => 'C1_A3',
]
]
]
but with help of loop
I am trying to create a questionnaire in which 3 steps need to be done
Create 3 arrays
1.categories - 2d -- like category["science"]["questions"]
2.questions
3.answers
step 1. add 10 questions in question array and add 10 answers in answer arrays
step 2.first 5 question of question array should be inserted to categories["science"]["questions"] and 5 answers to categories["science"]
["answers"]
I created Question and answer array and added 10 , 10 elements in it . but didnt succeed to add its elements as per step2 . I tried few logic
$Category=array();
$Q=array();
$A=array();
for($i=1;$i<=10;$i++)
{
$Q[] = "Question post".$i;
$A[] = "Answer post".$i;
//if($i==5)
//{
// array_push($Category,$Q[i]);
// break;
//} ---logic not working
}
//array first 5 Questions to category array
/*
for($i=1;$i<=5;$i++)
{
//$Category[]=$Q[i];
array_push($Category,$Q[i]);
}
*/ -- not working
print_r($Category);
Any suggestion or help would be appreciated
Try this:
$questions = [];
$answers = [];
for($i=1; $i <= 10; $i++) {
$questions[] = 'Question post' . $i;
$answers[] = 'Answer post' . $i;
}
$categories = ['science', 'something', 'else'];
$result = [];
foreach ($questions as $index => $question) {
if ($index % 5 != 0 || $index == 0) {
$category = current($categories);
} else {
$category = next($categories);
}
$result[$category][] = ['question' => $question, 'answer' => $answers[$index]];
}
var_dump($result);
I have the following code which works perfectly for producing a two tier navigation system, the problem is I have a requirement where one section has a third level of pages below it.
Edit: The code produces a two tier side navigation item that lists the pages in this section along with the parent item detailed at the top like so:
Page Title
Sub Page 1
Sub Page 2
Another Sub Page 1
Further Sub Page 1
Another Sub Page 1
Sub Page 3
There isn't any abnormal behaviour or error messages, it fails to display the further sub page 1 items in the list.
function insection_make_ul($tree, $level=0) {
$indent = str_repeat(" ", $level);
$result = "\n".$indent."<ul>\n";
foreach($tree as $id => $item) {
$result .= $indent."<li><a href=\"".$item['permalink']."\" class=\""
.($item['selected'] == true ? 'selected' : '')
.($level == 0 ? ' root' : '')."\" >" . $item['title']."</a>";
if(count(#$item['items'])) {
$result .= insection_make_ul($item['items'], ($level+1));
$result .= $indent."</li>\n";
}else{
$result .= "</li>\n";
}
}
$result .= $indent."</ul>\n";
return $result;
}
function insection($structure_id,$custom_selected=false){
$tree = insection_array($structure_id,$custom_selected);
return insection_make_ul($tree);
}
and the code to build the array
function insection_array($data,$custom_selected=false){
global $link;
if(is_numeric($data))
$data = fetch_row('SELECT * FROM content_structure WHERE id = '.$data);
$selected_id = $data['id'];
if($custom_selected) // dynamic item of 'real' parent
$selected_id .= '_'.$custom_selected;
$insection = array();
if($data['parent_id'] > 0){
if(HIDE_EMPTY_STRUCTURE){
$sql = 'SELECT * FROM content_structure WHERE parent_id = '.$data['id'].' AND visible = 1 AND in_menu = 1
AND (item_id > 0 OR redirect <> "")';
}else{
$sql = 'SELECT * FROM content_structure WHERE parent_id = '.$data['id'].' AND visible = 1 AND in_menu = 1';
}
$result = mysqli_query($link, $sql);
if(mysqli_num_rows($result) > 0 || $data['children_php'] != ''){
$parent_id = $data['id'];
}else{
$parent_id = $data['parent_id'];
}
}else{
$parent_id = $data['id'];
}
while($parent_id > 0){
$data = fetch_row('SELECT * FROM content_structure WHERE id = '.$parent_id);
$insection[$parent_id] = array('id' => $data['id'],
'title' => $data['menu_title'],
'permalink' => navlink($data),
'selected' => ($data['id'] == $selected_id ? true : false) );
if(HIDE_EMPTY_STRUCTURE){
$sql = 'SELECT * FROM content_structure WHERE parent_id = '.$parent_id.' AND visible = 1 AND in_menu = 1
AND (item_id > 0 OR redirect <> "") ORDER BY '
.($data['sort_auto'] == 1 ? 'menu_title' : 'sort_order');
}else{
$sql = 'SELECT * FROM content_structure WHERE parent_id = '.$parent_id.' AND visible = 1 AND in_menu = 1 ORDER BY '
.($data['sort_auto'] == 1 ? 'menu_title' : 'sort_order');
}
$result = mysqli_query($link, $sql);
if(!$result){ die('error: '.mysqli_error($link)); }
while($row = mysqli_fetch_assoc($result)){
$insection[$parent_id]['items'][$row['id']] = array('id' => $row['id'],
'title' => $row['menu_title'],
'permalink' => navlink($row),
'selected' => ($row['id'] == $selected_id ? true : false) );
}
// custom start
if($data['children_php'] != ''){ // custom sub items?
$sub_item_result = custom_navigation_array($data['children_php']);
foreach($sub_item_result as $sub_item){
$id = $data['id'].'_'.$sub_item['id']; // realparent_customid
$insection[$parent_id]['items'][$id] = array('id' => $id,
'title' => $sub_item['menu_title'],
'permalink' => $sub_item['href'],
'selected' => ($id == $selected_id ? true : false) );
}
}
//custom end
$parent_id = $data['parent_id'];
}
$insection = array_reverse($insection,true);
$temp = current($insection);
$root_id = #$temp['id'];
$insection_tree[$root_id] = current($insection);
$found_selected = false;
if(is_array(#$insection_tree[$root_id]['items'])){
foreach($insection_tree[$root_id]['items'] as $id => $item){
if(!empty($insection[$id])){
if($insection_tree[$root_id]['items'][$id]['selected'] == true)
$found_selected = true;
$insection_tree[$root_id]['items'][$id] = $insection[$id];
}
}
}
//if(!$found_selected){
// while(!$found_selected){
//
// }
//}
return $insection_tree;
}
Any pointers where I might get this working.
thanks
Personally I'd advise re-looking at your code. There is a lot of code there doing the same thing. Repetition is bad. As a helping hand, here's something to get you going.
Take this menu structure as an example but It's really upto you to produce this array yourself the main thing to notice is the function which will build the array into a <ul><li> string.
$menuItems = array(
array(// Top level items
"name" => "item1",
"subs" => array(// Second Level items
array(
"name" => "1a",
"href" => "something"
),
array(
"name" => "1b",
"subs" => array(// Third Level Items
array("name" => "1ba", "href" => "something"),
array("name" => "1bb", array(
array("name" => "1cca", "href" => "something"),
)
)
)
)
)
),
array(// Top level items
"name" => "item2",
"subs" => array(// Second Level items
array(
"name" => "2a",
"href" => "something"
),
array(
"name" => "2b",
"subs" => array(// Third Level Items
array("name" => "2ba", "href" => "something"),
array("name" => "2bb", array(
array("name" => "2cca", "href" => "something"),
)
)
)
)
)
)
);
$this->menuIterator($menuItems);
die();
The following logic is the important bit, it'll mean your menu could be any levels deep you want and it'll still produce the same result:
public function menuIterator($items) {
print "<ul>";
foreach ($items as $item) {
print "<li>";
print "<a>{$item['name']}</a>";
if (isset($item['subs'])) {
$this->menuIterator($item['subs']);
}
print "</li>";
}
print "</ul>";
return;
}
And the result is:
<ul><li><a>item1</a><ul><li><a>1a</a></li><li><a>1b</a><ul><li><a>1ba</a></li><li><a>1bb</a></li></ul></li></ul></li><li><a>item2</a><ul><li><a>2a</a></li><li><a>2b</a><ul><li><a>2ba</a></li><li><a>2bb</a></li></ul></li></ul></li></ul>
In my database i have column like id,product_id,company_name,service,qty,delivery_cost,delivery_date,order_status etc.
I view i used Jquery and Html and jquery dynamically add more input fields of product_id,service,delivery_cost,qty,delivery_date,order_status on clicking ADD more button.On submiting form i got this in controller on doing dd($allData);
My question is how can i save this data in database
array:8 [▼
"_token" => "gSddIeA11OBV60xU9YiDXn8fmsfkwxlQ85QmDdkQ"
"service" => array:3 [▼
0 => "cement"
1 => "iron"
2 => "steel"
]
"qty" => array:3 [▼
0 => "5"
1 => "44"
2 => "5"
]
"delivery_cost" => array:3 [▼
0 => "5465"
1 => "553"
2 => "554"
]
"delivery_date" => array:3 [▼
0 => "2016-12-16"
1 => "2016-12-08"
2 => "2016-12-17"
]
"order_status" => "Confirm"
"delivery_vehicle" => array:1 [▼
0 => "Self_elivery"
1 => "Self_elivery"
2 => "Self_elivery"
]
]
public function store(Request $request)
{
$allData= $request->all();
dd($allData);
$product = new Order;
}
i try this
public function store(Request $request)
{
$date = $request->get('delivery_date');
$cost = $request->get('delivery_cost');
$service = $request->get('service');//add quotes next to service
foreach($date as $deliveryDate)
{
foreach($cost as $proAmount){
$db = new Order;
$db->delivery_date = $deliveryDate;
$db->amount = $proAmount;
$db->save();
}
}
return"ok";
}
I tried this way but it store same data multiple times may be because of loop inside of loop.I need your help to store this data in database
Using for() should work for you:
$data = $request->all();
for ($i = 0; $i < count($data['delivery_date']); $i++) {
$db = new Order;
$db->delivery_date = $data['delivery_date'][$i];
$db->delivery_cost = $data['delivery_cost'][$i];
....
$db->save();
}
You can try this If you want to use foreach $key will give you the index.
$date = $request->get('delivery_date');
$cost = $request->get('delivery_cost');
$service = $request->get('service');
foreach($date as $key=>$deliveryDate)
{
$db = new Order;
$db->delivery_date = $deliveryDate;
$db->amount = $cost[$key];
$db->save();
}
return"ok";
Hope this help you. Ask if any query
Do bulk insert instead of running new sql query for every insert(if all the request params exist in single table).
$data = [];
foreach ($request->all() as $param => $val) {
if( is_array($val) ) // Ignore string params. i.e. _token, order_status
{
foreach ($val as $key => $value) {
$data[$index][$param] = $value;
$data[$index]['created_at'] = \Carbon\Carbon::now();
$data[$index]['updated_at'] = \Carbon\Carbon::now();
$index++;
}
$index = 0;
}
}
Model::insert($data);
Using foreach() should work for you very easy:
$inputdata = $request->all();
foreach ($inputdata as $key=>$val) {
$dbdata = new Order;
$dbdata ->delivery_date = $data['delivery_date'][$key];
$dbdata ->delivery_cost = $data['delivery_cost'][$key];
....
$dbdata ->save();
}