I have problems with arrays - php

So, I want to have table with users name, grades and subjects. Table will display only his grades. So I'm generating subject in foreach loop and reading grades depending on his id.
For subject I want to have an array which will contain infos about subject (teacher, classroom, etc.)
For now I have this array:
$subjects = array();
$getSubjects = mysqli_query($con, "SELECT * FROM predmeti");
while ($subject = mysqli_fetch_array($getSubjects)) {
$subjects[]= array(
$subject['subject_name'] => array(
'id' => $subject['id'],
'name' => $subject['name'],
'teacher' => $subject['teacher'],
'short_name' => $subject['short_name'],
'classroom' => $subject['classroom']
)
);
I know this isn't right. I can't get data for each subject.
Could you please help me?

You're accessing the columns by name while mysqli_fetch_array() returns only an integer indexed array. Have you tried mysqli_fetch_assoc()?

Related

PHP get Array with sub Array from SQL

I am new with coding and I just can't seem to get my head around this. A little help or tip is much appreciated.
Basically I want an array with Questionnaires, which consist of id, name and a sub array of questions. Questions also consist of id and name.(1 Questionnaire can have multiple questions)
Something like this is what I am looking for:
[{Questionnaires{id:x, name:x, questions:{id:x, name:x},{id:x2, name:x2}}]
This is my query
SELECT questionnaires.id QuestionnaireId, questionnaires.title QuestionnaireTitle, questions.id QuestionId, questions.text Question
FROM questionnaires INNER JOIN questionnaireshasquestions qa ON qa.idQuestionnaire = questionnaires.id
INNER JOIN questions ON questions.id = qa.idQuestion
And my PHP Code:
while ($row = $conn->fetch()) {
if (!isset($data['questionnaires'][$row['QuestionnaireId']])) {
$data['questionnaires'][] = array(
'id' => $row['QuestionnaireId'],
'title' => $row['QuestionnaireTitle'],
'questions' => array(
'id' => $row['QuestionId'],
'text' => $row['Question']
)
);
} else {
$data['questionnaires'][$row['QuestionnaireId']][] = array(
'questions' => array(
'id' => $row['QuestionId'],
'text' => $row['Question']
)
);
}
The JSON array I get with this is in a wrong/incorrect format:
{"questionnaires":[{"id":"1","title":"Are you hungry?","questions":{"id":"1","text":"How is your passion? "}},{"id":"1","title":"Are you hungry?","questions":{"id":"2","text":"Do you drink?"}},{"id":"2","title":"How are you feeling?","questions":{"id":"1","text":"How is your passion? "},"0":{"questions":{"id":"3","text":"Do you like fish?"}}},{"id":"5","title":"Is testing working?","questions":{"id":"4","text":"How is the testing?"}}]
As you can see, it repeats the same Questionnaire for each Question within...
I hope I explained well what I am trying to do here :)
Your collection method was a bit "broken".
This should work:
while ($row = $conn->fetch()) {
$id = $row['QuestionnaireId'];
if (!isset($data['questionnaires'][$id])) {
// First time we get this "QuestionnaireId" -
// define "container" that collects the related questions.
$data['questionnaires'][$id] = [
'id' => $row['QuestionnaireId'],
'title' => $row['QuestionnaireTitle'],
'questions' => [],
];
} else {
// Already got this "container" -
// put the question into the collection.
$data['questionnaires'][$id]['questions'][] = [
'id' => $row['QuestionId'],
'text' => $row['Question']
];
}
}

Efficient solution to generating an array in PHP, which extracts unique data from one array, based on data from another

Writing in PHP, I have 2 arrays, each created from SQL queries.
The first query runs through a table that has multiple pieces of data that correspond to various quiz attempts. The table has a column for the user's Email, the activity ID (which represents a quiz attempt) and another 2 columns for data relating to the attempt (for example 'percentage achieved' or 'quiz ID'):
UserEmail ActID ActKey ActMeta
joB#gm.com 2354 Percentage 98
joB#gm.com 2354 Quiz ID 4
boM#hm.com 4567 Percentage 65
boM#hm.com 4567 Quiz ID 7
Once queried, this first array ($student_quiz_list) stores the selected data in the form of
[[UserEmail, ActID, ActKey, ActMeta], [UserEmail, ActID, ActKey, ActMeta], [UserEmail, ActID, ActKey, ActMeta]...]
where each pair of sub-arrays corresponds to a single quiz attempt.
The second table that is queried has two columns that relate to the quizzes themselves. The first column is the Quiz ID and the second is the Quiz name.
Quiz ID Quiz Name
4 Hardware
7 Logic
Once queried, this second array ($quiz_list) stores the selected data in the form of
[[ID, Name], [ID, Name]...]
What I need to do is create a 3rd array (from the 2 above) which holds the user's email and percentage score
[email, percentage], [email, percentage]...]
but with each sub-array corresponding to a unique actID (so basically the user's percentage in each quiz they attempted without duplicates) and (this is the challenging bit) only for quizzes with certain ID values, in this case, let's say quiz ID 4.
In PHP, what would be the most efficient solution to this? I continually create arrays with duplicates and cannot find a neat solution which provides the outcome desired.
Any help would be greatly received.
Try this code as the example and let me know.
$student_quiz_list=array(
array(
'UserEmail'=>'joB#gm.com','ActID'=>'2354','ActKey'=>'Percentage','ActMeta'=>'90',
),
array(
'UserEmail'=>'joB#gm.com','ActID'=>'2354','ActKey'=>'QuizID','ActMeta'=>'4',
),
array(
'UserEmail'=>'boM#hm.com','ActID'=>'4567','ActKey'=>'Percentage','ActMeta'=>'98',
),
array(
'UserEmail'=>'boM#hm.com','ActID'=>'4567','ActKey'=>'QuizID','ActMeta'=>'7',
),
);
$final_array=array();
foreach( $student_quiz_list as $row){
if($row['ActKey']=='Percentage'){
$final_array[]=array('UserEmail'=>$row['UserEmail'],
'ActMeta'=>$row['ActMeta']
) ;
}
}
echo"<pre>"; print_r($final_array); echo"</pre>";
As commenter #Nico Haase suggested, you can do most of the logic in SQL. You didn't respond to my comment, so I suppose a user can have multiple attempts per quiz ID:
SELECT
UserEmail,
ActMeta
FROM
your_table # replace with your table name
WHERE
ActKey = 'Percentage'
AND ActID IN (
# subselection with table alias
SELECT
t2.ActID
FROM
your_table t2 # replace with your table name
WHERE
t2.ActKey = 'Quiz ID'
AND t2.ActMeta = 2 # insert your desired quiz ID here
AND t2.ActID = ActID
)
(Query tested with MySQL/MariaDB)
For the case that you cannot change the SQL part, here is how you can process your data in PHP. But consider that a large dataset could exceed your server capabilities, so I would definitely recommend the solution above:
// Your sample data
$raw = [
['UserEmail' => 'joB#gm.com', 'ActID' => 2354, 'ActKey' => 'Percentage' , 'ActMeta' => 98],
['UserEmail' => 'joB#gm.com', 'ActID' => 2354, 'ActKey' => 'Quiz ID', 'ActMeta' => 4],
['UserEmail' => 'joB#gm.com', 'ActID' => 4567, 'ActKey' => 'Percentage' , 'ActMeta' => 65],
['UserEmail' => 'joB#gm.com', 'ActID' => 4567, 'ActKey' => 'Quiz ID', 'ActMeta' => 7],
];
// Extract the corresponding ActIDs for a QuizID
$quiz_id = 4;
$act_ids = array_column(
array_filter(
$raw,
function($item) use ($quiz_id) {
return $item['ActMeta'] == $quiz_id;
}
),
'ActID'
);
// Get the entries with ActKey 'Percentage' and an ActID present in the previously extracted set
$percentage_entries = array_filter(
$raw,
function($item) use ($act_ids) {
return $item['ActKey'] === 'Percentage' && in_array($item['ActID'], $act_ids);
}
);
// Map over the previous set to get the array into the final form
$final = array_map(
function($item) {
return [$item['UserEmail'], $item['ActMeta']];
},
$percentage_entries
);

PHP & sqlsrv - create array from results, without knowing column names?

Using the below, I echo a JSON array of the results. But this requires that I identify the column names which I'd like to return from the SQL query:
$new_sql = "SELECT TOP 200 * FROM STracker ORDER BY [ID] DESC";
$check_statement = sqlsrv_query($conn, $new_sql);
$data = array();
while($row = sqlsrv_fetch_array($check_statement, SQLSRV_FETCH_ASSOC)) {
$data['data'][] = array(
'id' => $row['ID'],
's_reference' => $row['s_reference'],
'reference' => $row['reference'],
'customer_name' => $row['customer_name']
);
}
Is there any way to create that array information, but return all of the columns returned by the query dynamically? So by using SELECT * FROM, all of the column data is returned in the array but without me needing to write out all of these individually? (the below)
'id' => $row['ID'],
's_reference' => $row['s_reference'],
'reference' => $row['reference'],
'customer_name' => $row['customer_name']
Ok I forgot to add that I'd tried this:
$data['data'][] = array($row);
Which is clearly wrong, and after using the following, it works perfectly!
$data['data'][] = $row;

fetch values in listbox from two table using joins

User Table -
column name - location_id
values = 4,5
Location table
column name - id , location_name
values = 4 nagpur
5, Akola
i want to display location names in listbox by joining location_id of user table,
Suppose in location_id column of user table 4,5 values are present then in my select box this only displays nagpur, Akola from location table.
i cannot understand how to explode values of location_id table before select and display only those values which are available in location_id column from location table.
public function getUserLocations() {
$this->loadModel('User');
$getlocations = $this->User->find('list', array(
'fields' => array('Location.id','Location.location_name'),
'joins' => array(
array(
'table' => 'locations',
'alias' => 'Location',
'type' => 'LEFT',
'conditions' => array('FIND_IN_SET(User.location_id,Location.id)')
)
),
));
$this->set('getlocations', $getlocations);
}
below is my code ..
Explode the variable like this :
$getlocations = $this->User->find('list', array(
'fields' => array('Location.id'));
$location_ids[] = explode (',', $getlocations);
Now you will get the data in array format. Modify it according to your needs

How do I combine two arrays in PHP based on a common key?

I'm trying to join two associative arrays together based on an entry_id key. Both arrays come from individual database resources, the first stores entry titles, the second stores entry authors, the key=>value pairs are as follows:
array (
'entry_id' => 1,
'title' => 'Test Entry'
)
array (
'entry_id' => 1,
'author_id' => 2
I'm trying to achieve an array structure like:
array (
'entry_id' => 1,
'author_id' => 2,
'title' => 'Test Entry'
)
Currently, I've solved the problem by looping through each array and formatting the array the way I want, but I think this is a bit of a memory hog.
$entriesArray = array();
foreach ($entryNames as $names) {
foreach ($entryAuthors as $authors) {
if ($names['entry_id'] === $authors['entry_id']) {
$entriesArray[] = array(
'id' => $names['entry_id'],
'title' => $names['title'],
'author_id' => $authors['author_id']
);
}
}
}
I'd like to know is there an easier, less memory intensive method of doing this?
Is it possible you can do a JOIN in the SQL used to retrieve the information from the database rather than fetching the data in multiple queries? It would be much faster and neater to do it at the database level.
Depending on your database structure you may want to use something similar to
SELECT entry_id, title, author_id
FROM exp_weblog_data
INNER JOIN exp_weblog_titles
ON exp_weblog_data.entry_id = exp_weblog_titles.entry_id
WHERE field_id_53 = "%s" AND WHERE entry_id IN ("%s")
Wikipedia has a bit on each type of join
Otherwise the best option may be to restructure the first array so that it is a map of the entry_id to the title
So:
array(
array(
'entry_id' => 1,
'title' => 'Test Entry 1',
),
array(
'entry_id' => 3,
'title' => 'Test Entry 2',
),
)
Would become:
array(
1 => 'Test Entry 1',
3 => 'Test Entry 2',
)
Which would mean the code required to merge the arrays is simplified to this:
$entriesArray = array();
foreach ($entryAuthors as $authors) {
$entriesArray[] = array(
'id' => $authors['entry_id'],
'title' => $entryNames[$authors['entry_id']],
'author_id' => $authors['author_id']
);
}
I've rearranged some of my code to allow for a single SQL query, which looks like:
$sql = sprintf('SELECT DISTINCT wd.field_id_5, wd.entry_id, mb.email, mb.screen_name
FROM `exp_weblog_data` wd
INNER JOIN `exp_weblog_titles` wt
ON wt.entry_id=wd.entry_id
INNER JOIN `exp_members` mb
ON mb.member_id=wt.author_id
WHERE mb.member_id IN ("%s")
AND wd.entry_id IN ("%s")',
join('","', array_unique($authors)),
join('","', array_unique($ids))
);
This solves my problem quite nicely, even though I'm making another SQL call. Thanks for trying.
In response to your comment on Yacoby's post, will this SQL not give the output you are after?
SELECT exp_weblog_data.entry_id, exp_weblog_data.field_id_5 AS title_ie, exp_weblog_titles.author_id
FROM exp_weblog_data LEFT JOIN exp_weblog_titles
ON exp_weblog_data.entry_id = exp_weblog_titles.entry_id
WHERE exp_weblog_data.field_id_53 = "%S"
Every entry in exp_weblog_data where field_id_53 = "%S" will be joined with any matching authors in exp_weblog_titles, if a an entry has more than one author, two or more rows will be returned.
see http://php.net/manual/en/function.array-merge.php

Categories