Need help with PHP homework - friend matching algorithm - php

I'm totally new to php and have started learning it. I have two homework assignments in php and html.
Assignment 1:
I have to store some people's names and all of their friends names. I have to list only people who have common friends. My problem is that if a person has no friends in common with someone else I get a message "Rana has 0 friends in common with Roni. I do I prevent this:
Assignment 2:
I have a html form to search for a person from the last php file
When I will search for Rana the PHP form will open and and print:
Rana have 4 friends and he has a common friend with Nandini and Mamun.
When I search for Tanmoy the page will be open and print:
Tanmoy is Rana’s friend who has 4 friends and common friends with Nandini and Mamun.
For this I have to used the function “post/get/request”
Here is my code so far:
<?php
# Function: finfCommon
function findCommon($current, $arr) {
$cUser = $arr[$current];
unset($arr[$current]);
foreach ($arr As $user => $friends) {
$common = array();
$total = array();
foreach ($friends As $friend) {
if (in_array($friend, $cUser)) {
$common[] = $friend;
}
}
$total = count($common);
$add = ($total != 1) ? 's' : '';
$final[] = "<i>{$current} has {$total} friend{$add} in common with {$user}.</i>";
}
return implode('<br />', $final);
}
# Array of users and friends
$Friends = array(
"Rana" => array("Pothik", "Zaman", "Tanmoy", "Ishita"),
"Nandini" => array("Bonna", "Shakib", "Kamal", "Minhaj", "Ishita"),
"Roni" => array("Akbar", "Anwar", "Khakan", "Pavel"),
"Liton" => array("Mahadi", "Pavel"),
"Mamun" => array("Meheli", "Tarek", "Zaman")
);
# Creating the output value
$output = "<ul>";
foreach ($Friends As $user => $friends) {
$total = count($friends);
$common = findCommon($user, $Friends);
$output .= "<li><u>{$user} has {$total} friends.</u><br /><strong>Friends:</strong>";
if (is_array($friends) && !empty($friends[0])) {
$output .= "<ul>";
foreach ($friends As $friend) {
$output .= "<li>{$friend}</li>";
}
$output .= "</ul>";
}
$output .= "{$common}<br /><br /></li>";
}
$output .= "</ul>";
# Printing the output value
print $output;
?>

For the assignment 1.1: You have just to filter out the unwantend responses with an
if ($total>0) {
$output .= "<li><u>{$user} has {$ ...
}
clause.
For the second assignment:
You have to create a page that expects a parameter to be read via $_GET or $_POST or $_REQUEST (call it name, for example). They are not functions, are arrays and you can access them from every scope in you program (they are superglobals and you don't need to declare them with gobals).
I would just print a select with the known people if the name (eg. $_REQUEST['name'] )is missing just print the form, otherwise find the person indicated by the input and print the result of the search.
EDIT:
For the second assignment, you will have to figure how to get the input data.
Probably I will use an approach a bit different
Provided that you have a form similar to this
<form action="homework.php" method="get">
Person: <select name="searchperson" />
<option> </option>
...
<option> </option>
</select>
</form>
you will have to get the list of all the known peoples in a manner similar to this:
$friends = array(
"Rana" => array("Pothik", "Zaman", "Tanmoy", "Ishita"),
"Nandini" => array("Bonna", "Shakib", "Kamal", "Minhaj", "Ishita"),
"Roni" => array("Akbar", "Anwar", "Khakan", "Pavel"),
"Liton" => array("Mahadi", "Pavel"),
"Mamun" => array("Meheli", "Tarek", "Zaman")
);
// create a flat array with all the known peoples
$knownPeople = array_reduce(
$friends,
function($current, $result) {
return array_merge($result, $current);
},
array_keys($friends)
);
$knownPeople = array_flip(array_flip($knownPeople)); //get rid of duplicates
asort(knownPeople); // sort the names
$knownPeople = array_values($knownPeople); // normalize the array indexes
and then get the form you need with a function like this:
function theForm($people) {
$options = '<option>'.join("</option>\n<option>",$people). '</option>';
echo "
<form action=\"homework.php\" method=\"get\">
<h2>Chose the people you want investigate on:</h2>
Person: <select name=\"person\" />
$options
</select>
</form>";
}
Whenever you get a grasp on the previous code or not, you have to evaluate the input and take the opportune actions:
Let say that your script is called homework.php (you will see the name into the action of the form) and it is located ad http://example.com. His URI will be http://example.com/homework.php
There are several possible scenarios:
the user call the script for the first time
the user choose a person from the select
the user invoke your script manually with a known person as parameter
the user invoke your script manually with a person you don't have in your list
Let's review the different cases:
the user call the script for the first time
What appened: the user go to http://example.com/homework.php crossing a link or writing the URI into the browser address bar.
How you detect this scenario: Given the form above you can check $_GET['person']. if it is not isset or empty or not array_key_exists you can state you are into the first scenario.
To do: Just output the form and exit.
the user choose a person from the select
What appened: the user get the form (first scenario) and choose a name from the select.
How you detect this scenario: The detection of the first scenario fails and you can find the name contained into $_GET['person'] into the knownPeople array.
To do:
sanitize the input (remove any spurious character)
find the name into the knownPeople array to be sure you are not serving a forged request
apply your functions to the person in input in order to get the desired output
output the result you got
the form for a new query or a link to http://example.com/homework.php
the user invoke your script manually with a known person as parameter
What appened: the user use a URI like http://example.com/homework.php?person=Rana to reach the script
How you detect this scenario: If the method you use in the form is get you can't (at least not using this simple scenarion) and you won't bother to as it can be considered a legal request as this is an homework and you don't have requirements about it. If you used the method post you have the chance to detect the forgeries as the parameter passed with that method are usually stored into the $_POST array. You can still find the name contained into $_GET['person'] into the knownPeople array.
To do: Same as second scenario
sanitize the input (remove any spurious character)
find the name into the knownPeople array to be sure you are not serving a forged request
apply your functions to the person in input in order to get the desired output
output the result you got
the form for a new query or a link to http://example.com/homework.php
the user invoke your script manually with a person you don't have in your list
How you detect this scenario: The detection of the first scenario fails and you can not find the name contained into $_GET['person'] into the knownPeople array.
To do:
sanitize the input (remove any spurious character)
find the name into the knownPeople array to be sure you are not serving a forged request
as the check fails output an error messages stating the user is unknown and let the user go to the correct uri with a link to http://example.com/homework.php.
Not all forgeries are bad. Consider an user that make a legal search and bookmark the result. If the list of friends change and then he returns to the page using the bookmark. He will fall straight into the fourth scenario
Hope this will help you to comprehend how the php scripting works.

change findCommon function from
function findCommon($current, $arr) {
$cUser = $arr[$current];
unset($arr[$current]);
foreach ($arr As $user => $friends) {
$common = array();
$total = array();
foreach ($friends As $friend) {
if (in_array($friend, $cUser)) {
$common[] = $friend;
}
}
$total = count($common);
$add = ($total != 1) ? 's' : '';
$final[] = "<i>{$current} has {$total} friend{$add} in common with {$user}.</i>";
}
return implode('<br />', $final);
}
to
function findCommon($current, $arr) {
$cUser = $arr[$current];
unset($arr[$current]);
foreach ($arr As $user => $friends) {
$common = array();
$total = array();
foreach ($friends As $friend) {
if (in_array($friend, $cUser)) {
$common[] = $friend;
}
}
$total = count($common);
$add = ($total != 1) ? 's' : '';
if ( $total > 0 ) $final[] = "<i>{$current} has {$total} friend{$add} in common with {$user}.</i>";
}
return implode('<br />', $final);
}
The change is i added a if ( $total > 0 ) before $final[] = ..
for the second one.
<?php
function searchPerson($person, $friends){
$direct = false;
$found = false;
if ( in_array ($person, array_keys($friends) ) ){
list($total, $common_friends) = commonFriend ($person, $friends);
$direct = true;
$found = true;
}
else{
foreach ( $friends as $friend => $his_friends ){
if ( in_array ( $person, $his_friends ) ){
list($total, $common_friends) = commonFriend ($friend, $friends);
$direct = false;
$found = true;
$friend_person = $friend;
break;
}
}
}
if ( !$found ) return false;
$output = $person . " ";
if ( $direct ){
$output .= " has " . $total . " friends";
}
else{
$output .= " is " . $friend_person . "'s friend who has " . $total . " friends";
}
if ( isset($common_friends[0]) ) $output .= " and common friends with " . $common_friends;
return $output;
}
function commonFriend ($person, $friends){
$my_friends = $friends[$person];
unset($friends[$person]);
$total_friends = count($my_friends);
$common_with = array();
foreach ( $friends as $friend => $his_friends ){
foreach ( $my_friends as $my_friend ){
if ( in_array ($my_friend, $his_friends) ){
$common_with[] = $friend;
}
}
}
$common_with = array_unique ($common_with);
$common_friends = "";
if ( count($common_with) > 0 ){
$common_friends = join (", ", $common_with );
}
return array ( $total_friends, $common_friends );
}
$friends = array(
"Rana" => array("Pothik", "Zaman", "Tanmoy", "Ishita"),
"Nandini" => array("Bonna", "Shakib", "Kamal", "Minhaj", "Ishita"),
"Roni" => array("Akbar", "Anwar", "Khakan", "Pavel"),
"Liton" => array("Mahadi", "Pavel"),
"Mamun" => array("Meheli", "Tarek", "Zaman")
);
$person = $_GET['person'];
$output = searchPerson($person, $friends);
if ( $output === false ) print $person . " is not on the list";
else print $output;
?>
What you have to do with the second assignment is you need a form.
lets say the above code was named searchPerson.php
then add a html page like
<html>
<head>
<title>Search for friend</title>
</head>
<body>
<form action="searchPerson.php" method="get">
Person: <input type="text" name="person" /><input type="submit" value="search" />
</form>
</body>
</html>
or run directly like
searchPerson.php?person=Rana
And why you get a message like that is because $person = $_GET['person']; gets the person name from the url, and u must have run it like searchPerson.php, so their is no value for $person to check.
-- EDIT
Chaged the code to work with people not in the list

Related

How to extract PHP array values and remove data

I have seen a bunch of ways, but none that seem to work. My array data is coming back like this.
Array
(
[0] => RESULT=0
[1] => RESPMSG=Approved
[2] => SECURETOKEN=8cpcwfZhaH02qNlIoFEGZ1wO4
[3] => SECURETOKENID=253cad735251571cebcea28e877f4fd7
I use this:
<?php echo $response[2];?>
too get each out, that works. But I need to remove “SECURETOKEN=” so im left with just the number strings. I have been trying something like this with out success.
function test($response){
$secure_token = $response[1];
$secure_token = substr($secure_token, -25);
return $secure_token;
}
Also Im putting end number into a form input “Value” field. Not that that matters, unless it does?
Thanks
This is what I would do:
$keyResponse = [];
foreach ($response as $item) {
list($k, $v) = explode('=', $item, 2);
$keyResponse[$k] = $v;
}
Now you can easily access just the value part of each item based on the name:
echo $keyResponse['SECURETOKEN']; // output: 8cpcwfZhaH02qNlIoFEGZ1wO4
The advantage to this method is the code still works if the order of the items in $response changes
I get your secure token like this (tested):
<?php
$arr = array(
'RESULT=0',
'RESPMSG=Approved',
'SECURETOKEN=8cpcwfZhaH02qNlIoFEGZ1wO4',
'SECURETOKENID=253cad735251571cebcea28e877f4fd7'
);
$el = $arr[2];
$parts = explode('=', $el);
echo '#1 SECURETOKEN is ' . $parts[1];
// This break just for testing
echo '<br />';
// If you wanted to, you could revise the whole array
$new = array();
foreach( $arr as $el ){
$parts = explode('=', $el);
$new[$parts[0]] = $parts[1];
}
// Which would mean you could then get your securetoken like this:
echo '#2 SECURETOKEN is ' . $new['SECURETOKEN'];

get csv values from two coloumns mysql csv using php

enter image description here
Refer Image
I have values like this in mysql.
I need wholesaletl name based on wholesaletlcontact.
Example: when I have value ajin3 then i need the value 1234587452
Get the field values from db.
Explode them to an array.
$myString = "ajin1,ajin3,ajin2";
$myArray = explode(',', $myString);
print_r($myArray);
Do the same for the other field values.
Output will be: Array ( [0] => ajin1 [1] => ajin3 [2] => ajin2 )
Then get the id for a specific value:
$key = array_search('ajin3', $myArray);
And that Id will correspond to the required value in the other array.
Here could be the solution for you
$wholesaletl=explode(",",$record->wholesaletl);
$wholesaletlcontact=explode(",",$record->wholesaletlcontact);
$wholesaletlcontact_arr=array();
if(count($wholesaletl) > 0){
foreach($wholesaletl as $key => $value){
$wholesaletlcontact_arr[$value]=$wholesaletlcontact[$key];
}
echo $wholesaletlcontact_arr["ajin3"];
If you don't have a choice about using the csv files or if you don't feel that the drawbacks matter, the following code should help you with accessing the information:
function get_contact_from_name($name, &$name_array, &$contact_array) {
$name_index = array_search($name, $name_array);
// Name is not in csv list
if ($name_index === false) {
echo "Name does not exist: $name<br />";
return null;
}
// There is no contact in the corresponding postion
if (!isset($contact_array[$name_index])) {
echo "Contact does not exist at position: $name_index<br />";
return null;
}
return $contact_array[$name_index];
}
$names = 'bill,george,sophia,marge';
$wholesaleltnames = str_getcsv("bill,george,sophia", ",");
$wholesaleltcontacts = str_getcsv("123,456", ",");
foreach (explode(',', $names) as $name) {
$c = get_contact_from_name($name, $wholesaleltnames, $wholesaleltcontacts);
if ($c) {
echo "Contact: $name, $c<br />";
}
}
You will need to modify it to fit your needs. For example, it would need to be updated to use the row returned from mysql and to handle errors properly.

php pdo category level access

i want category level access to users, i will give from admin side which categories users should access and which are not. Here i have trouble please help me, here is my code
In my database permission table there, in that userid and catids fields there so user if click on category function will see in permission table if user has permission are not then it will dipplay.
public function Grants($username)
{
$q = $this->db->prepare("select * from permissions where user = ?");
$q->bindParam(1, $username);
$q->execute();
$results = $q->fetchAll();
return $results;
}
category page
$check = new Access;
$data = $check->Grants($user);
foreach($data as $v)
{
if($v['catid'] == $_GET['p'])
{
foreach($nav as $list)
{
echo '' . '<li style="display:inline; padding:10px;">' . $list['catname'] . '</li>' . '';
}
}
else{
echo 'Access Denied'; }
}
if i had only one category in permission table it is working fine, if user had two or more catids not working.
Permission table example:
User>1 catid>1,2,3 array model giving problem how do i solve please help, if i place only one category it is working.
If your data is stored as I think it is from what you posted, it would look like this:
------------------------
| User | catid |
------------------------
1 1,2,3
Am I right? If that is the case. Then when you call this:
$check = new Access;
$data = $check->Grants($user);
Your $data variable would contain something like this:
1,2,3
and NOT an array as you think it would.
What you should do is use explode() to create that url:
$check = new Access;
$data = explode(',', $check->Grants($user));
Which, in turn; should give you an array like this:
Array (
[0] => 1,
[1] => 2,
[2] => 3,
)
Allowing you to iterate as you require.
EDIT
As per your comment, you need to access the catid array element. Provided you have the right php version, you could simple do this:
$check = new Access;
$data = explode(',', $check->Grants($user)[0]['catid']);
Or if that throws error, try this:
$check = new Access;
$cats = $check->Grants($user);
$data = explode(',', $cats[0]['catid']);
I have found simple solution for this.
$check = new Access;
$data = $check->Grants($user);
foreach($data as $result)
{
$str = $result['catid'];
$string = explode(',' , $str);
}
if(in_array($_GET['p'], $string))
{
foreach($nav as $list)
{
echo '' . '<li style="display:inline; padding:10px;">' . $list['catname'] . '</li>' . '';
}
}
else { echo "You dont have permission"; }

php foreach supplied argument not valid

I am getting results from a mysql table and putting each cell into an array as follows:
$sqlArray = mysql_query("SELECT id,firstName FROM members WHERE id='$id'");
while ($arrayRow = mysql_fetch_array($sqlArray)) {
$friendArray[] = array(
'id' => $arrayRow['id'],
'firstName' => $arrayRow['firstName'],
);
}
Then I do a search for a specific friend. For example if I want to search for a friend name Osman, i would type and o and it will return to me all the results that start with the letter o. Here is my code for that:
function array_multi_search($array, $index, $pattern, $invert = FALSE) {
$output = array();
if (is_array($array)) {
foreach($array as $i => $arr) {
// The index must exist and match the pattern
if (isset($arr[$index]) && (bool) $invert !== (bool) preg_match($pattern, $arr[$index])) {
$output[$i] = $arr;
}
}
}
return $output;
}
$filtered = array_multi_search($friendArray, 'firstName', '/^o/i');
and then it will print out all the results. My problem is that it returned an error saying "Invalid argument supplied to foreach()" and that is why I added the if(is_array)) condition. It is working fine if I leave this code in the index.php page, but I moved it to a subfolder named phpScripts and it doesn't work there. Any Help?
$output is not returning any value because apparently $friendArray is not an array. But I verified that it is by using print_r($friendArray) and it returns all the member's id and firstName.
P.S. I use JavaScript to the the call using AJAX.
If your array structure is such:
$friendArray[] = array(
'id' => $arrayRow['id'],
'firstName' => $arrayRow['firstName'],
);
This means your array is indexed and two levels.
So the correct way to walk through it is:
foreach($array as $cur_element) {
$id = $cur_element['id'];
$firstName = $cur_element['firstName'];
}
Change this:
foreach($array as $i => $arr) {
To this:
foreach((array)$array as $i => $arr) {
Are you sure that $array is not empty?

Merging data structures

I have a set of structured data, that I'm trying to merge together, based on a set of conditions.
There is a set of rows, returned from the db. Each row has a course id, and a discipline id. There's an equal amount of disciplines in each course, but some disciplines are repeated in both courses.
I want to build a data structure where if the discipline is in both courses, then it only appears once on a line in a new data structure, and nothing else, but if there are two unmatched disciplines, then they are both included in a new course.
The code I'm using so far, is filtering and removing the keys that are duplicated, and adding them to a new array. This works fine.
However, because I can't control the order in which the data comes (don't ask) I'm having troubles making sure that each line has either a discipline that appears in both courses, or one of each.
I think I need some techniques to help deal with this, and was wondering if anyone had come across this before. I want to avoid making many consecutive loops, if possible.
Thanks.
edit: messy and horrible code below:
function buildDisciplineMap(){
$sql = "SELECT [idcurso]
,[idversao]
,[ordem]
,[bloco]
,[obsbloco]
,[iddisciplina] as idd
,cast([iddisciplina] as TEXT) as iddisciplina
,[descdisciplina]
,[iddepartamento]
,[descdepartamento]
,[ects]
,[horas]
,[idregente]
,[regente]
,[idregente1]
,[regente1]
,[idregente2]
,[regente2]
,[idregente3]
,[regente3]
,cast([objectivos] as TEXT) as objectivos
,cast([programa] as TEXT) as programa
,[descdisciplina_en]
,cast([objectivos_en] as TEXT) as objectivos_en
,cast([programa_en] as TEXT) as programa_en
FROM [proffile2].[dbo].[vw_site_CursosDisciplinas_FEG]
where idcurso = '3512 GE' or idcurso = '3513 ECON' order by idcurso desc ";
$discs = $this->returnObject($sql);
$map = new stdClass();
// find blocos, and titles
foreach ($discs as $key => $value) {
if (isset($map->bloco[$value->bloco])) {
// block already exists
} else {
#echo "making new block";
$map->bloco[$value->bloco] = new stdClass();
}
if (strlen($value->obsbloco)>1) {
$map->bloco[$value->bloco]->title = $value->obsbloco;
}
}
foreach ($map->bloco as $keybloco => $value) {
$map->bloco[$keybloco]->lines = array();
$processed_ids = array();
foreach ($discs as $kd => $vd) {
if ($vd->bloco == $keybloco) {
// check if this discipline occurs more than once in this block
foreach ($discs as $kdd => $vdd) {
if ($vdd->iddisciplina == $vd->iddisciplina && $kdd != $kd && !in_array($kd,$processed_ids) && !in_array($kdd,$processed_ids)) {
// this discipline is for both courses
$details = array();
$details['both'] = $vd;
$map->bloco[$keybloco]->lines[] = $details;
array_push($processed_ids, $kd, $kdd);
unset($discs[$kdd]);
unset($discs[$kd]);
break;
}
}
}
}
}
$processed_ids = array();
foreach ($discs as $key => $value) {
echo $value->idcurso."\n";
}
foreach ($discs as $kd => $vd) {
$bloco = $vd->bloco;
$lastidx =sizeof($map->bloco[$bloco]->lines)-1;
$line = $map->bloco[$bloco]->lines[$lastidx];
echo sizeof($map->bloco[$bloco]->lines);
#pr($line);
if (isset($line['both'])) {
echo "omog - \n ";
$map->bloco[$bloco]->lines[][$vd->idcurso] = $vd;
unset($discs[$kd]);
continue;
}
#pr($line['both']->idcurso);
foreach ($map->bloco[$bloco]->lines as $k => $v) {
echo $k."-";
#echo $v['3513 ECON']->idcurso;
}
if ($line[$vd->idcurso]) {
echo 'add';
$map->bloco[$bloco]->lines[][$vd->idcurso] = $vd;
} else {
echo 'fill';
$map->bloco[$bloco]->lines[sizeof($map->bloco[$bloco]->lines)-1][$vd->idcurso] = $vd;
}
}
echo sizeof($discs);
return $map;
}
You said "don't ask", but I've got to: why can't you control the order of the rows? Aren't you the one writing the database query?
If you think fixing the order of the rows will help you parse and build a new data structure better, why not make sorting the rows the first step in your process? Or, is the data set too large?
You might find some of PHP's array set manipulations to be of use. i.e. array_diff, array_intersect_key etc.

Categories