I have a question regarding php and sql. In the database I have a shop table 'x' in which there is a tags column containing mixed tags from which to filter the collection for the product using the operator 'like'. I have to compare the filtered collection with the collections in column 1 of the store '. If these two collections are equal, then from the store's table in column 2 I can retrieve the appropriate value and enter it into the csv file.
In php I have downloaded the column with tags from the 'x' store, but I have no idea how to add to the category that I searched for by query and compare it with the data from the store 's' column. I tried to explode the resulting strings from the foreach loop with explode () to get an array from each cell in the column, but got the primitive array that was fetched from the database. I also tried a regular for loop but it also failed.
How can you get this one value from the tags column and compare it with the data from another column ?
public static function findEmpikCategory()
{
$empik_lilante_categories = MysqlProvider::getEmpikCategory(); // empik and lilante categories from empik_categories in which the 'collection' is included
// get a specific category (lilante_category) from empik_categories
foreach($empik_lilante_categories as $categories)
{
$lilante_category_from_empik[] = $categories['lilante_category'];
}
return $lilante_category_from_empik;
}
//$lilante_category = explode(",", $lilante_category_for_offers_products, 0);
// searching lilante categories from the shopifyProductsLilante array
public static function findLilanteCategory()
{
$empik_cateries_equals_lilante_categories = MysqlProvider::getEmpikCategoryEqualLilanteCategory(); // empik categories corresponding to lilante categories
$lilante_category_to_check = CSVFileGenerator::findEmpikCategory();
$lilante_category_for_offers_products = MysqlProvider::getLilanteCategoryByOffersEmpik(); // lilante categories for all empik products
//print_r($lilante_category_to_check);
foreach($lilante_category_for_offers_products as $lilanteCategories)
{
foreach($lilanteCategories as $lilanteCategory)
{
echo "<br/>";
//print_r($lilanteCategory);
echo "<br/>";
print_r(explode(",", $lilanteCategory, 0));
//echo "<br/>";
// echo gettype($lilanteCategory) . "<br>"; // each element is a string
// print_r($lilanteCategory);
}
}
foreach($lilante_category_to_check as $lilanteCategoryFromEmpik)
{
echo "<br/>";
print_r($lilanteCategoryFromEmpik);
echo "<br/>";
}
//fclose($file_open);
return ;
}
Related
I've a problem that confuses me and can not get solved...
I have 1 for each loop which runs through all products and then inside I have another for each loop for some specific product parameters that I need to combine into one string (string, array or serialized data) and save info in data base.
foreach ($products as $product) {
$parameter1 = $product_parameter1;
foreach ($products_extra_parameters as $product_extra_parameter) {
$parameter2 .= $product_extra_parameter . '|';
}
$insert_data = "INSERT INTO table (parameter1,parameter2) values ('$parameter1','$parameter1')";
if (!mysqli_query($conn, $insert_data)):
fwrite($fh, "Error: " . $insert_data . "\n" . mysqli_error($conn). "\n");
endif;
}
The problem is that with '.=' it adds previous results to the next product (first product have: 'product1_parameter2_value1|product1_parameter2_value' and next one: 'product1_parameter2_value1|product1_parameter2_value|'product2_parameter2_value1|product2_parameter2_value' and so on and on...
I just need to save combined product attributes in 1 table column (using just string combining or can be serialize) for appropriate product and just this product parameters! And I'll have several such parameters that I need to combine in 1 parameter and save in 1 column...
What I'm missing here/doing wrong?
In this DataObject there is a user supplied field Title which has to be converted to a unique URL slug.
Desired Result: Duplicate URL's should get a suffix to its value. So saving 2 records with Title Foo should result in one record with foo as its value for column URL and the second record should have value foo-2 for the same column.
public function onBeforeWrite() {
parent::onBeforeWrite();
// Sanitize Title field to use for URL
$filter = URLSegmentFilter::create();
$this->URL = $filter->filter($this->Title);
// If URL is not unique, add suffix
$i = 1;
while($this->uniqueURL($this->URL)) {
$i++;
$this->URL = $this->URL . "-" . $i;
}
}
method: uniqueURL (within same class)
public function uniqueURL($URL) {
// Check if there is a record with the same URL
$existingURL = DataObject::get('NewsArticle', "URL = '$URL'");
if ($existingURL) {
// this is a duplicate URL
return false;
} else {
// this is a unique url
return true;
}
}
Saving Foo twice would result in foo and foo-2.
When saving two records with the same Title Foo results in two URL fields with foo
Why do you have two foo urls?
If you check your DB before inserting all records, this means that the check will not work on your record batch.
Don't use a loop to count unique urls
You don't need to loop and check every time and increment the count ($i). Performance wise youre far better off doing a COUNT() in a query and just use that value for your next insert.
// The following does exactly the same with just 1 query. No loop needed.
$count = DB::query("SELECT COUNT(*) FROM Table WHERE Title LIKE '{$filteredTitle}'")->value();
if ($count > 1) {
$filteredTitle .= "-" . $count;
}
$this->URL = $filteredTitle
Solutions
To do it onBeforeWrite() the only possibility is to Query your data AND check your records before they are saved.
Or a simpler solution with the same results is that you can change the url in an onAfterWrite() , and check use the amount of same titles as number.
public function onAfterWrite() {
parent::onAfterWrite();
// Sanitize Title field to use for URL
$filter = URLSegmentFilter::create();
$filteredTitle= $filter->filter($this->Title);
$count = DB::query("SELECT COUNT(*) FROM Table WHERE Title LIKE '{$filteredTitle}'")->value();
if ($count > 1) {
$filteredTitle .= "-" . $count;
}
$this->URL = $filteredTitle
}
I need to use where operator to check some ids in my table as the following
$subScIDs = SubjectSchedule::where('subject_start_id',Input::get('substID'))
->whereNull('deleted_at')
->select('id')->get();
$subScIDsArray = array() ;
foreach ($subScIDs as $id)
{
$subScIDsArray [] = $id->id ;
}
// here my issue
$subScInStudAttends = StudentAttendees::whereIn('subject_schedule_id',$subScIDsArray)
->select('subject_schedule_id')->get();
if ($subScInStudAttends)
{
return " true " . $subScInStudAttends;
}else{
return "false";
}
My issue in this code
$subScInStudAttends = StudentAttendees::whereIn('subject_schedule_id',$subScIDsArray)
->select('subject_schedule_id')->get();
whereIn working well it fetch any id in $subScIDsArray, but i need to check each id of ids if one id in $subScIDsArray not equal subject_schedule_id' return false ;
How I Can do it ?
Any Suggestions ?
You can check the length of the array that contains the ids against the length of the records returned.
if( count($subScIDsArray) == count($subScInStudAttends) ){
// all IDs in the array have a corresponding record in the database
}
Or better, if your application logic permits it, simply get the count of the records and then compare with the length of the ids array.
$subScInStudAttendsCount = StudentAttendees::whereIn('subject_schedule_id', $subScIDsArray)->count('subject_schedule_id');
if( count($subScIDsArray) == $subScInStudAttendsCount ){
// all IDs in the array have a corresponding record in the database
}
This code assumes the ids in your database are all unique.
if(count($search)==0) {
for($i=0;$i<count($about);$i++) {
$bd->insert("search","page_title,page_description,page_url,image_id","'About','{$about[$i]['image_title']}','http://religiousbrands.in/demo/about.php?search=".$about[$i]['id']."','{$about[$i]['uniq_id']}'");
}
} else {
for($i=0;$i<count($about);$i++) {
for($k=0,$j=0;$k<=$i,$j<count($search);$j++,$k++) {
if($search[$j]['image_id']==$about[$i]['uniq_id']) {
echo "update".$i.'and'.$k.'and'.$j;
echo"<br>";
$bd->update("search",
"page_title='About',page_description='{$about[$i]['image_title']}',page_url='http://religiousbrands.in/demo/about.php?search=".$about[$i]['id']."' ","image_id='{$about[$i]['uniq_id']}' limit 1");
}
}
}
}
$search is an array which I am getting from my database . first I m checking if the search table is empty or not . if empty then insert the values in the search table .
$about is also an array which i am getting from my database . if $search is not empty Then I am updating the value but checking first that $search[$j]['image_id']===$about[$i][uniq_id] and HERE IS MY PROBLEM START :
Suppose in my table about there are 3 entries ie :
uniq_id=1
uniq_id=2
uniq_id=3
and In my table search there are 2 entries ie:
image_id=1
image_id=2
So the search table is not empty So it will follow the 2nd condition. So i was trying that table $about[1]['uniq_id'] should check for $search[1]['image_id'] and $search[2]['image_id'] and etc $search[$i]['image_id'] if the table has any values
but I my for loop is not working like I want So anybody can help me in this
You'll need to know which rows in the "search" table need adding (INSERT) and which ones need updating.
Perhaps try looping through the "search" array first and find which "image_id" values you have.
$image_ids = array();
foreach ($search as $item) {
$image_ids[] = $item['image_id'];
}
Next, loop through the "about" array. Use the ID's in the "$image_ids" array to determine whether you need to UPDATE or INSERT an item.
foreach ($about as $item) {
if (in_array($item['image_id'], $image_ids)) {
// Item already exists. Update it.
} else {
// Item doesn't exist. Add it.
}
}
This is also much faster than putting loops inside loops.
The goal of this code, is to get all brands for all stores into one array, and output this to the screen. If a brand exists in multiple stores, it will only be added once.
But I feel I have too many for loops, and that it might choke the CPU on heavy traffic.
Is there a better solution to this?
function getBrands($stores, $bl)
{
$html = "";
//Loop through all the stores and get the brands
foreach ($stores as $store)
{
//Get all associated brands for store
$result = $bl->getBrandsByStore($store['id']);
//Add all brands to array $brands[]
while ($row = mysql_fetch_array($result))
{
//If this is the first run, we do not need to check if it already exists in array
if(sizeof($brands) == 0)
{
$brands[] = array("id" => $row['id'], "name" => $row['name']);
}
else
{
// Check tosee if brand has already been added.
if(!isValueInArray($brands, $row['id']))
$brands[] = array("id" => $row['id'], "name" => $row['name']);
}
}
}
//Create the HTML output
foreach($brands as $brand)
{
$url = get_bloginfo('url').'/search?brandID='.$brand['id'].'&brand='.urlSanitize($brand['name']);
$html.= ''.$brand['name'].', ';
}
return $html;
}
//Check to see if an ID already exists in the array
function isValueInArray($values, $val2)
{
foreach($values as $val1)
{
if($val1['id'] == $val2)
return true;
}
return false;
}
From your comment, you mention "Guide table has X stores and each store has Y brands". Presumably there's a "stores" table, a "brands" table, and a "linkage" table, that pairs store_id to brand_id, in a one-store-to-many-brands relationship, right?
If so, a single SQL query could do your task:
SELECT b.`id`, b.`name`
FROM `stores` s
LEFT JOIN `linkage` l
ON l.`store`=s.`id`
LEFT JOIN `brands` b
ON b.`id`=l.`brand`
GROUP BY b.`id`;
That final GROUP BY clause will only show each brand once. If you remove it, you could add in the store ID and output the full list of store-to-brand associations.
No need to loop through two sets of arrays (one to build up the array of brands, and then one to make the HTML). Especially since your helper function does a loop through -- use the array_key_exists function and use the ID as a key. Plus you can use the implode function to join the links with ', ' so you don't have to do it manually (in your existing code you'd have a comma on the end you'd have to trim off). You can do this without two sets of for loops:
function getBrands($stores, $bl)
{
$brands = array();
//Loop through all the stores and get the brands
foreach ($stores as $store)
{
//Get all associated brands for store
$result = $bl->getBrandsByStore($store['id']);
//Add all brands to array $brands[]
while ($row = mysql_fetch_array($result))
{
if (!array_key_exists($row['id'])
{
$url = get_bloginfo('url') . '/searchbrandID=' .
$brand['id'] . '&brand=' . urlSanitize($brand['name']);
$brands[$row['id']] .= '<a href="' . $url . '" id="' .
$brand['id'] . '" target="_self">' .
$brand['name'] . '</a>';
}
}
}
return implode(', ', $html);
}
That will get you the same effect a little faster. It's going to be faster because you used to loop through to get the brands, and then loop through and build up the HTML. Don't need to do that as two separate loops so it all at once and just store the HTML as you go along. Plus since it's switched to use array_key_exists, instead of the helper you wrote that checks by looping through yet again to see if a brand is in there, you'll see more speed improvements. Hashmaps are nice like that because each element in the hashmap has a key and there are native functions to see if a key exists.
You could further optimize things by writing a better SQL statement with a distinct filter to make it so you don't have to do a while inside a foreach.
How are your tables designed? If you had a store table, a brand table, and a link table that had the relationship between stores and brands, you could just pull in the list of brands from the brand table in one query and not have to do any other logic.
Design your tables so they easily answer the questions you need to ask.
If you need to get all the brands for a certain set of stores then you should consider using a query crafted to do that instead of iterating through all the stores and getting the separate pieces of information.