php: how can i change Stored value into user friendly values ! - php

the problem in short,
Field:ProfileItems = "action,Search,Work,Flow,pictures";
Mysql query = "SELECT ProfileItems FROM addUsers";
then I explode with , making array e.g.: array('action','search',...etc)
and create fields for ,
Result:
<form>
action : <input type=text name=action>
search : <input type=text name=search>
...etc
<input type=submit>
</form>
My problem is how can I replace names in the database with more user friendly ones (add description) to fields without using an IF statement??
//created asoc array with Key = search item and value = user friendly value
$prase = array("ABS" => "ABS (Anti lock braking System)"
,"DriverAirBag" => "Air bags");
$string= "ABS,DriverAirbag,GOGO,abs";
foreach($prase as $db=>$eu){
echo "if $db will be $eu<br>";
echo str_ireplace($eu,$db,$string);
}
echo $string;
Tried above but was an epic fail :D !.. can you please help me out ?

Having a map inside PHP is not an unreasonable approach, but you're doing the str_ireplace() backwards: it's search, replace, subject, so in your case str_ireplace($db, $eu, $string);
But just doing a str_ireplace() on a comma-separated list of strings is not ideal anyway. For one thing, imagine if after you did the substitution for ABS you then encountered another profile item that matched lock (which just so happens to appear in "Anti-lock braking system"). Oops. Now you've overwritten your earlier replacement!
How about something like this:
$prase = array("ABS" => "ABS (Anti lock braking System)"
,"DriverAirBag" => "Air bags");
$string= "ABS,DriverAirbag,GOGO,abs";
$fields = explode(',', $string);
foreach($fields as $field) {
$friendly = $field;
if (isset($phrase[$field]))
$friendly = $phrase[$field];
echo htmlspecialchars($friendly) . ': <input type="text" name="' . htmlspecialchars($field) . '" />
}
The key here is that you're handling each field separately. And you're never just doing a replacement; you're looking specifically for the keywords "ABS" or "DriverAirbag". If there's not an exact match, you don't have a human-friendly name for that item, and there's no point doing any replacement.
All this can be improved even further if you have the ability to change the database schema. Storing a comma-separated list is never desirable. You should have a table with a schema something like:
field_id (e.g., "ABS")
name (e.g., "Anti-lock Braking System")
And another table like:
user_id (I'm inferring a little here from the name addUsers — whatever field/s you have in addUser now identifying the person)
field_id (i.e., foreign key to the above field table)
Note that you may end up with many rows in this table for each person (1, 'ABS'), (1, 'DriverAirbag')
But then your query can become
SELECT field, name
FROM user_field
INNER JOIN field USING (field_id)
Now you get back one row for each field (no explode required!) and each row includes both the computer-friendly and human-friendly name.

Related

String from an array from an array from the database

Okay so, first of all, I searched through the www for this question, and I found some question related to arrays but not exactly to mine.
Okay so as you may know, paypal only allows one custom variable to be $POST but I need to gather the product id AND the quantity of the item bought. So to do this I made my custom variable into something that would get the post like (25-1,12-3,13-4) it means, the user bought 3 items(separated by commas), where the first number is the product id (then the separator '-' comes in) and the second one is the quantity. (so they're all in the same row and column)
Now my problem is displaying it from the database. I need to get the product name and details that's why I need to separate the numbers from each array as a string and fetch the data from the database for the information of the product. (I'm using an older version of php anyway, 5.2, I guess.)Now the problem is:
1.) It returns the word 'Array' (literally) so it would say like ArrayArrayArray
2.) How do I explode/separate those data so I can get it because I need the product ID to fetch some other data... I tried exploding it into array, then exploding it again but doesn't work (most likely my code is wrong?)
Here is my code: (I've already connected to the database)
$data = mysql_query("SELECT * from transactions") or die(mysql_error());
/* My table tag and headers goes here */
while($info = mysql_fetch_array( $data )) {
echo "<tr>";
echo '<td>' . $info['id'] . '</td>';
echo "<td>";
$array = $info['product_id_array'];
$explode_array = explode(",", $array);
foreach($explode_array as $explode_more){
$explode_more = explode("-", $explode_array);
$prod_id = $explode_more[0];
$quantity = $explode_more[1];
print_r($prod_id); //should echo the 25 in the array (25-1), right?
print_r($quantity);
}
echo"</td>";
echo"<tr>";
}
If only paypal would allow multiple custom variables T_T Thank you guys. Forgive me if I can't express my question very well or my language is not good, as english is not my first language :), Good day!
Your variable names are mixed up. Inside the foreach-loop, you should do something like this
foreach($explode_array as $explode_more){
$explode_even_more = explode("-", $explode_more);
$prod_id = $explode_even_more[0];
$quantity = $explode_even_more[1];
print_r($prod_id); //should echo the 25 in the array (25-1), right?
print_r($quantity);
}
Note, that $explode_more is used inside the loop and $explore_array is left as is.
Separate this in multiple tables, never store non-atomic values in 1 column.
Certainly not when they have relation with another table.
Suppose you want to know the sales from a certain product in some period.

comparing variables in PHP with different language files

I have a select menu for users.
It is populated by PHP variables, which are all language variables. For example:
$word = $lang['word'];
$select = array($word);
Therefore, the select menu options will change based on the language the user has chosen. I need to be able to compare users' selections to each other. For example:
if($user1word == $user2word) ...
But because of the language files, this doesn't work. Obviously "one" != "Uno" even though they're the same.
My first fix was to change everything to a numeric value before posting it to the database. Example:
if($_POST['word'] == $lang['word']) { $userWord = 1 }
This worked perfectly for all words except those that contained special characters (å, æ, é...) and nothing I did could resolve this (I tried normalizer; language-specific accept-char onchange events for the form; utf8_encode. It was hopeless.
Currently everything saves to the database as text, dependent on the language the user is in. So if "Language" is an option, but you're in Norwegian, it saves as "Språk".
I need a simple solution that doesn't crush my mind - I am new to PHP.
Currently everything saves to the database as text, dependent on the language the user is in.
This is a design flaw in my opinion. Ideally your data would be as agnostic as possible to language and translations would be performed just for the UI with tools like gettext. Typically items like select values would be stored with keys or IDs.
Use a map that is based on a common index, this index can be english, spanish or numeric. i'd suggest numeric. Store the numeric index in your database.
A step in the right direction:
$lang['en'][0] = 'Hello';
$lang['de'][0] = 'Hallo';
$lang['es'][0] = 'Hola';
$lang['en'][1] = 'Sup?';
$lang['de'][1] = 'Wie gehts?';
$lang['es'][1] = 'Que pasa?';
$userLang = 'en';
// show the select
echo '<select name="word">';
foreach ( $lang[$userLang] as $index => $word {
echo '<option value="'.$index.'">'.$word.'</option>';
}
echo '</select>';
// show the selected word:
echo 'You chose to say "'.$lang[$userLang][$_POST['word']].'".';
// compare the word to what is in the db
if ( $_POST['word'] === $dbRow['word'] ) {
// expression matches!
// assume a column in the db "language" describes the language the user chose, e.g. 'en', 'de', or 'es'
echo 'You previously chose "'.$lang[$dbRow['language']][$dbRow['word']].'" in the language "'.$dbRow['language'].'".;
}
Depending on how you want to organize it, you may favor grouping by phrase instead of grouping by language, i.e.:
$lang[0]['en'] = 'Hello';
$lang[0]['de'] = 'Hallo';
$lang[0]['es'] = 'Hola';

Is this the right way to use Sphinx from PHP?

I am just starting with Sphinx. So far I got it installed successfully, got a table called profiles on my MySQL database indexed and am able to get the correct results back using the PHP API. I am using CodeIgniter so I wrapped the default PHP API as a CodeIgniter library.
Anyway this is how my code looks like:
$query = $_GET['q'];
$this->load->library('sphinxclient');
$this->sphinxclient->setMatchMode(SPH_MATCH_ANY);
$result = $this->sphinxclient->query($query);
$to_fetch = array();
foreach($result['matches'] as $key => $match) {
array_push($to_fetch, $key);
}
The array $to_fetch contains the ids of the matched table rows. Now I can use a typical MySQL query to get all the relevant users to display on the search page like so:
$query = 'SELECT * FROM profiles WHERE id IN('. join(',', $to_fetch) . ')';
My question are:
is this the right way to go about it? or is there a default "Sphinx way of doing it" that would be better for performance .
secondly, all I get back at the moment is the id of the matched table rows. I also want the part of the text in the column that matched. For example if a someone searches for the keyword dog and a user on the profiles table had in their about column the following text:
I like dogs. I also like ice cream.
I would like Sphinx to return:
I like <strong>dogs</strong>. I also like ice cream.
How can I do that? I tried to play around with the buildExcerpts() function but can't get it to work.
EDIT
This is how I am getting excerpts now:
// get matched user ids
$to_fetch = array();
foreach($result['matches'] as $key => $match) {
array_push($to_fetch, $key);
}
// get user details of matched ids
$members = $this->search_m->get_users_by_id($to_fetch);
// build excerpts
$excerpts = array();
foreach($members as $member) {
$fields = array(
$member['about'],
$member['likes'],
$member['dislikes'],
$member['occupation']
);
$options = array(
'before_match' => '<strong class="match">',
'after_match' => '</strong>',
'chunk_separator' => ' ... ',
'limit' => 60,
'around' => 3,
);
$excerpt_result = $this->sphinxclient->BuildExcerpts($fields, 'profiles', $query, $options);
$excerpts[$member['user_id']] = $excerpt_result;
}
$excerpts_to_return = array();
foreach($excerpts as $key => $excerpt) {
foreach($excerpt as $v) {
if(strpos($v, '<strong class="match">') !== false) {
$excerpts_to_return[$key] = $v;
}
}
}
As you can see I am searching each query across 4 different mysql columns:
about
likes
dislikes
occupation
Because of this I don't know which of the 4 columns contains the matched keyword. It could be any of them or even more than one. So I have no choice but to run the contents of all 4 columns through the BuildExcerpts() function.
Even then I don't know which one the BuildExcerpts() returned with the <strong class="match"> tags. So I run a stpos check on all values returned by BuildExcerpts() to finally get the proper excerpt and map it to the user whose profile it belongs to.
Do you see a better way than this given my situation where I need to match against the contents of 4 different columns?
Yes that looks good way. One thing to remember the rows coming back from Mysql probably won't be in the order from sphinx.
See the FAQ on sphinx site for how to use FIELD() but personally I like to put the rows from sphinx into associative array, then just loop though the sphinx I'd list and get the row from the array. Avoids a sorting phase altogether at the expense of memory!
As for highlighting, yes do persevere with buildExcerpts - that's is the way to do it.
edit to add, this demo
http://nearby.org.uk/sphinx/search-example5-withcomments.phps
demonstrates both getting rows from mysql and "sorting" in the app. And buildExcerpts.

Remove values in comma separated list from database

I have a table in my MySQL database called 'children'. In that table is a row called 'wishes' (a comma separated list of the child's wishlist items). I need to be able to update that list so that it only removes one value. i.e. the list = Size 12 regular jeans, Surfboard, Red Sox Baseball Cap; I want to remove Surfboard.
My query right now looks like this
$select = mysql_query('SELECT * FROM children WHERE caseNumber="'.$caseNum.'" LIMIT 1 ');
$row = mysql_fetch_array($select);
foreach ($wish as $w) {
$allWishes = $row['wishes'];
$newWishes = str_replace($w, '', $allWishes);
$update = mysql_query("UPDATE children SET wishes='$newWishes' WHERE caseNum='".$caseNum."'");
}
But the UPDATE query isn't removing anything. How can I do what I need?
Using these user-defined REGEXP_REPLACE() functions, you may be able to replace it with an empty string:
UPDATE children SET wishes = REGEXP_REPLACE(wishes, '(,(\s)?)?Surfboard', '') WHERE caseNum='whatever';
Unfortunately, you cannot just use plain old REPLACE() because you don't know where in the string 'Surfboard' appears. In fact, the regex above would probably need additional tweaking if 'Surfboard' occurs at the beginning or end.
Perhaps you could trim off leading and trailing commas left over like this:
UPDATE children SET wishes = TRIM(BOTH ',' FROM REGEXP_REPLACE(wishes, '(,(\s)?)?Surfboard', '')) WHERE caseNum='whatever';
So what's going on here? The regex removes 'Surfboard' plus an optional comma & space before it. Then the surrounding TRIM() function eliminates a possible leading comma in case 'Surfboard' occurred at the beginning of the string. That could probably be handled by the regex as well, but frankly, I'm too tired to puzzle it out.
Note, I've never used these myself and cannot vouch for their effectiveness or robustness, but it is a place to start. And, as others are mentioning in the comments, you really should have these in a normalized wishlist table, rather than as a comma-separated string.
Update
Thinking about this more, I'm more partial to just forcing the use of built-in REPLACE() and then cleaning out the extra comma where you may get two commas in a row. This is looking for two commas side by side, as though there had been no spaces separating your original list items. If the items had been separated by commas and spaces, change ',,' to ', ,' in the outer REPLACE() call.
UPDATE children SET wishes = TRIM(BOTH ',' FROM REPLACE(REPLACE(wishes, 'Surfboard', ''), ',,', ',')) WHERE caseNum='whatever';
Not exactly a direct answer to your question, but like Daren says it's be better having wishes as its own table. Maybe you could change your database schema so you have 3 tables, for instance:
children
-> caseNum
-> childName
wishes
-> caseNum
-> wishId
-> wishName
childrensWishes
-> caseNum
-> wishId
Then to add or delete a wish for a child, you just add or delete the relevant row from childrensWishes. Your current design makes it difficult to manipulate (as you're finding), plus leaves you at risk for inconsistent data.
As a more direct answer, you could fix your current way by getting the list of wishes, explode() 'ing them, removing the one you don't want from the array and implode() 'ing it back to a string to update the database.
Make wishes table have this format:
caseNumber,wish
Then you get all of a child's wishes like this:
SELECT * FROM children c left join wishes w on c.caseNumber = w.caseNumber WHERE c.caseNumber= ?
Removing a wish becomes:
DELETE from wishes where caseNumber = ?
Adding a wish becomes:
INSERT into wishes (caseNumber,wish) values (?,?)
Returning one wish becomes:
SELECT * FROM children c left join wishes w on c.caseNumber = w.caseNumber WHERE c.caseNumber= ? LIMIT 1
Having the wishes indexed in an array which is thereafter serialized could be an idea, otherwise you would need to retrieve the string, slice it, remove the part you don't want, then concatenate the remains. This can be done by using the explode() function.
If you were to use an array, you would retrieve the array and then sort through it with a loop like this:
// Wishes array:
// Array (
// [0] Regular Jeans
// [1] Surfboard
// [2] Red Sox Baseball Cap
// )
$wishes = $row['wishes']; // This is a serialized array taken from the database
$wishes = unserialize($wishes);
foreach ($wishes as $key => $value) {
if ($value == 'Surfboard') {
unset($wishes[$key]);
break;
}
}
$wishes = serialize($wishes);
// Update database
Keep in mind that index [1] now won't exist in the array, so if you wish to have a clean array you should loop through the array and make it create a new array by itself:
foreach ($wishes as $wishes) {
$newArray[] = $wishes;
}
I think the best answer to such issue is here
The best way to remove value from SET field?
query should be like this which covers the ,value or value, or only value in the comma separated column
UPDATE yourtable
SET
categories =
TRIM(BOTH ',' FROM
REPLACE(
REPLACE(CONCAT(',',REPLACE(col, ',', ',,'), ','),',2,', ''), ',,', ',')
)
WHERE
FIND_IN_SET('2', categories)
Here you can have your condition in where clause. for more details refer above link.
You can create function like this:
CREATE FUNCTION `remove_from_set`(v int,lst longtext) RETURNS longtext CHARSET utf8
BEGIN
set #lst=REPLACE(#lst, ',,', ',');
set #lng=LENGTH(#lst) - LENGTH(REPLACE(#lst, ',', ''))+1;
set #p=find_in_set(#v,#lst);
set #l=SUBSTRING_INDEX( #lst, ',', #p-1);
set #r=SUBSTRING_INDEX( #lst, ',', #p-#lng);
IF #l!='' AND #r!='' THEN
return CONCAT(#l,',',#r);
ELSE
RETURN CONCAT(#l,'',#r);
END IF;
END
Using:
SELECT remove_from_set('1,,2,3,4,5,6',1)

How to remove only entirely duplicate values from an array?

I have a website where my database is set up with different artists and song titles within the same row, where it might look this:
artist: The Monkees, title: I'm A Believer
artist: The Monkees, title: Daydream Believer
artist: The Hollies, title: The Air That I Breathe
artist: The Hollies, title: Bus Stop
artist: The Beatles, title: Hello, Goodbye
artist: The Beatles, title: Yellow Submarine
And I have an autocomplete widget set up with my site's search form that is fed a json_encoded array filled with 'artist' values.
The first problem is that if a user were to begin typing "the" into the search form, values would come up like this:
The Monkees
The Monkees
The Hollies
The Hollies
The Beatles
The Beatles
So I used the array_unique function to remove duplicate values, but it seems that even if a value has one duplicate word (this case being "the"), it is removed entirely, so only the first value is returned:
The Monkees
Where the output I would like to have would be:
The Monkees
The Hollies
The Beatles
So, what might be another way I can remove these duplicate values and display them the way I would like?
EDIT:
Here is my source code:
<?php
include 'includes/config.php';
$return_arr = array();
$term = ($_GET['term']);
if ($con)
{
$artist = mysql_query("SELECT * FROM songs WHERE artist LIKE '%$term%' LIMIT 0, 5");
while ($row = mysql_fetch_array($artist, MYSQL_ASSOC)) {
$row_array['value'] = strtolower($row['artist']);
array_push($return_arr,$row_array);
}
}
mysql_close($con);
echo json_encode(array_unique($return_arr));
?>
array_unique uses a strict comparison. So differences in case and whitespace are taken into consideration. Since all of those values seem to be strings, it's likely the reason why array_unique is not working the way you would expect.
Your database structure makes it pretty difficult to weed out duplicates. I would suggest refactoring it into a table of artists and a table of songs, where songs simply reference the id of artist. This will give you a better chance of being able to keep your artist list unique.
Also, one thing I would do for your autocomplete is set it up to ignore certain strings. ('a', 'an', 'the') These are known as stopwords, and help search results be more relevant by not performing a search on common words.

Categories