I'm coding an iTunes search app using the iTunes Search API. So far I have everything working properly but here is the problem I am running into. If you want to search all media types by a particular keyword it returns the results in no particular order. You may have movies, podcasts, songs, etc mixed in randomly in the results. The API, as far as I know only allows you to sort by most recent release date.
I would like to sort the results by the "kind":key to group them by media type. I don't care what particular order they are in as long as they are grouped together by media type.
This is part of a typical return in JSON format with simple key value pairs. I have it set to return the maximum results so I may have up to 200 results with 10 different media types with the key of "kind":
{"wrapperType":"track",
"kind":"song",
"artistId":909253,
"collectionId":120954021,
"trackId":120954025,
"artistName":"Jack Johnson",
Here is part of my results array:
$iTunes = array();
for($i=0; $i<count($data['results']); $i++) {
$kind = $data['results'][$i]['kind'];
$artistId = $data['results'][$i]['artistId'];
$collectionId = $data['results'][$i]['collectionId'];
$trackId = $data['results'][$i]['trackId'];
$artistName = $data['results'][$i]['artistName'];
$trackName = $data['results'][$i]['trackName'];
$collectionName = $data['results'][$i]['collectionName'];
$artistViewUrl = $data['results'][$i]['artistViewUrl'];
$trackViewUrl = $data['results'][$i]['trackViewUrl'];
$collectionViewUrl = $data['results'][$i]['collectionViewUrl'];
$image100 = $data['results'][$i]['artworkUrl100'];
$collectionPrice = $data['results'][$i]['collectionPrice'];
$previewUrl = $data['results'][$i]['previewUrl'];
I'm trying to wrap my head around grouping by values of keys. Do I create another array and iterate over the $kind = $data['results']?
It would seem that you would need to build an array with 'kind' as a dimension. So something like this:
$data_array = array();
for ($i = 0; $i <count($data['results']); $i++) {
$kind = $data['results'][$i]['kind'];
$data_array[$kind][] = $data['results'][$i];
}
You could then work with the array like this:
foreach ($data_array as $kind => $kind_array) {
// echo out any category headers based on $kind
foreach($kind_array as $item) {
// echo out each individual item within this kind group
}
}
Related
I have a function that calls an API but want to create batches and call these every x second.
My form contains a textarea (Titles) where a list is added and are formatted SKU|Title on each line.
Within my code take each line and split where pipe is, i use the SKU part to know where the search terms belongs to and the Title part is used on the API search.
What i need to do now is split the 1000 (or however amount) inputted search lines into smaller batches, like 10 searches every 5 seconds and work through the titles.
Current Setup
<?php
function search_items($title, $filetype, $resultamount) {
foreach(explode("\r\n", $title) as $line) {
$strip = explode("|",$line);
// This is where the API Runs
// I use $strip[1] to get the Title to search in the API request
}
}
?>
I think the below could work but kept getting errors like array to string error
$batches_of = 10;
$search_array = explode("\r\n", $title);
$batch = array_chunk($search_array, $batches_of);
foreach($batch as $b) {
foreach ($b as $key => $value) {
print $key;
}
sleep (5);
}
Update
Ok so i have been trying this for a while and seem to have got something working and looks to do as intended, no errors and take a while but its as expected (note this is not a production model), any feedback on the below?
// Title = Multiple Lines from Textarea, Example Title 32306|Samsung Galaxy S20 256GB Black
// Filetype = I have a custom If / Else statement, if form has one selection display it differently (File Type 1 or 2)
// ResultAmount = How many results do i want to retrieve for each searched title, Example 1 - 10
function search_items($title, $filetype, $resultamount) {
// Set the amount of Batches to create from the Total Submitted amount in form
$batch_of = 10;
// Create array for each line item
$my_array = explode("\r\n", $title);
// Create array Batches
$batch = array_chunk($my_array, $batch_of);
foreach($batch as $line) {
foreach ($line as $key => $value) {
// Seperate the line items to Get SKU ($strip[0]) and get Title ($strip[1])
$strip = explode("|",$value);
// API request variables using CURL
$endpoint = 'http://web.com/services/search';
// The Query, now i will use the Product Name and appende $query to my search URL
$query = ''.str_replace(str_split('\\/:*?"<>|()[]-'), '%20', $strip[1]).'';
// My API Data and responses will be below
}
// Wait 2 Seconds before the next batch
sleep (2);
}
}
I have this code
private function hashtagName($string){
$name = $string;
$name = ltrim($name, '#');
$name = trim($name);
return $name;
}
private function hashtags($article){
$htag = '#';
$arr = explode(" ", $article->description);
$arrc = count($arr);
$i = 0;
$arr_id = [];
while($i < $arrc){
if(substr($arr[$i], 0, 1) === $htag ){
$hash = Hashtag::firstOrCreate(
['name' => $this->hashtagName($arr[$i]), 'slug' => str_slug(ltrim($arr[$i], '#'))]
);
if (! $article->hashtags->contains('hashtag_id', $this->hashtagName($arr[$i]))) {
$article->hashtags()->save($hash);
}
}
$i++;
}
}
This code store tags into db correctly. I have a problem if I try use a few hashtags in WYSCIWYG editor. Very often WYSCIWYG editor add it's own html tags and this code save it. For example it stored in DB helloworld
Since an Article can have many hashtags and a hashtag can belong to many articles, it's a ManyToMany relationship....
You can synchronize the hashtags using the sync method, any old hashtags that aren't in the new associations array will be automatically removed...
$article->hashtags()->sync($arrayOfHashtagsIds);
From the Docs
Syncing Associations
You may also use the sync method to construct many-to-many associations. The sync method accepts an array of IDs to place on the intermediate table. Any IDs that are not in the given array will be removed from the intermediate table. So, after this operation is complete, only the IDs in the given array will exist in the intermediate table.
I am trying to create either a list or table of fixtures for sports teams in a Wordpress website using data that comes in from a json api and I am running into issues figuring out exactly how to do this. As some of the fixtures have the same dates, I thought to group the data into a new array by doing the following:
$matchLists = json_decode(json_encode($fixture_data), True);
$newlist = array();
foreach ($matchLists as $key => $matchitem) {
if (array_key_exists('matchDate', $matchitem)) {
$newlist[$matchitem['matchDate']][$key] = ($matchitem);
}
}
But this seems to have the effect of creating a further level to the array please see picture attached to see what the $newlist looks like: newlist array example
I am struggling to use the tutorials/examples I have seen so far on dealing with multi dimensional arrays to split this information out correctly. I can get the fixture date headings using:
foreach($newlist as $key => $value)
{
$fixtureDate = date('D j M Y ga', strtotime($key));
$return .= '<li><h4>' . $fixtureDate . $test . '</h4></li>';
}
but this doesn't then offer me a route to pull out the rest of the data that I need.
This is how I got the information before realizing that I would need to group the fixtures into the correct dates/times
$fixtureHome = json_decode(json_encode($fixtureitem->homeTeam), true);
$fixtureAway = json_decode(json_encode($fixtureitem->awayTeam), true);
$fixtureHomeName = $fixtureHome['name'];
$fixtureAwayName = $fixtureAway['name'];
$fixtureHomeID = $fixtureHome['id'];
$fixtureAwayID = $fixtureAway['id'];
$fixtureID = $fixtureitem->id;
$matchDate = $fixtureitem->matchDate;
$fixtureDate = date('D j M Y ga', strtotime($matchDate));
$homeColour = $fixtureHome['color'];
$awayColour = $fixtureHome['color'];
$fixtureStatus = json_decode(json_encode($fixtureitem->matchStatus), true);
$scoreHome = $fixtureStatus['homeTeamScore'];
$scoreAway = $fixtureStatus['awayTeamScore'];
but I don't understand how to achieve the same results now with the $newlist?
It turned out I was just having problems figuring out how to access the correct levels...
$fixtureHome = $fixtureitem['homeTeam']['name'];
$fixtureAway = $fixtureitem['awayTeam']['name'];
Just having a mental block,thanks for looking :-)
This is driving me nuts.
I'm attempting to reada CSV file (done) and then work through the permutations of each row.
Each row contains several bits of data (name, price etc.).
Some of them contain slash separated lists (a/b/c/c3/c65).
What I need to do is generate all the possible variations of each row.
Example:
Row 12 =
Name = name,
Price = price,
Models = x12/x14/x56,
Codes = LP1/LP12/LP899/XP90/XP92,
From that I should be able to generate 15 variations, each with the same Name and Price, but with different Codes and varied Models;
Name Price X12 LP1
Name Price X12 LP12
Name Price X12 LP899
~
Name Price X56 XP90
Name Price X56 XP92
Yet I'm either overwriting pre-existing versions, or generating individual versions, but only getting 1 set of values changing (so I may get the 15 versions, but only Model changes, everything else stays the same).
Any help/thoughts or pointers would be appreciated!
So you have one row containing that much items,
say
$row = array('Name'=>'name', 'price'=>'price','models'=>'x12/x14/x56','codes'=>'LP1/LP12/LP899/XP90/XP92')
and you want to split models and codes with "/" then have each item as a new row in the array with all the columns those having the same value for price and name field, here is how you can do this,
$line = 0;
$result_array = array();
$result_array[$line]['name'] = $row['name'];
$result_array[$line]['price'] = $row['price'];
//split the models using explode
$tmpModels = explode("/",$row['models']);
foreach($tmpModels as $mod){
if($line > 0){
$result_array[$line]['name'] = $row['name'];
$result_array[$line]['price'] = $row['price'];
}
$result_array[$line]['model'] = $mod;
$line++;
}
$line = 0;
//now split the codes using explode
$tmpCodes = explode("/",$row['models']);
foreach($tmpCodes as $cod){
$result_array[$line]['code'] = $cod;
$line++;
}
if(count($tmpCodes) > count($tmpModels)){ // then few more rows should be added to include all from codes
foreach($tmpCodes as $cod){
$result_array[$line]['name'] = $row['name'];
$result_array[$line]['price'] = $row['price]'
$result_array[$line]['model'] = '';
$result_array[$line]['code'] = $cod;
$line++;
}
}
$result_array will have what you want.
This code is not tested, so there can be some errors, btw i hope this will surely give you an idea on how to achieve that.
Let's say you have array that looks like this:
$variant=Array();
$list[0]=array('Name'=>'Item name', 'Price'=>'$400','Models'=>'x12/x14/x56','Codes'=>'LP1/LP12/LP899/XP90/XP92');
$list[1]=array('Name'=>'Item name', 'Price'=>'$400','Models'=>'x12/x14/x56','Codes'=>'LP1/LP12/LP899/XP90/XP92'); // and more array.......
for($i=0;$i<count($list);$i++){
$Names=$list[$i]["Name"];
$Prices=$list[$i]["Price"];
$Models=explode("/",$list[$i]["Models"]);
$Codes=explode("/",$list[$i]["Codes"]);
for($i2=0;$i2<count($Codes);$i2++){
$variant[]=Array("name"=>$Names,"price"=>$Prices,"model"=>$Models[0],"code"=>$Codes[$i2]);
$variant[]=Array("name"=>$Names,"price"=>$Prices,"model"=>$Models[1],"code"=>$Codes[$i2]);
$variant[]=Array("name"=>$Names,"price"=>$Prices,"model"=>$Models[2],"code"=>$Codes[$i2]);
// You can add more models by copy paste it and change $Models[2] with next available $Models array index
}
}
var_dump($variant);
?>
The results will produce 30 array, because we have 2 rows, so that's not wrong ... okay
Reason for looping the codes
Because codes is more greater than models. So, we can catch all values.
Good luck, btw i have test it and that's worked
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.