Unique Slug Issue Auto Increment - php

I have slugs formatted like my-cool-slug however I need to auto increment some to make a similar slug unique such as my-cool-slug-2 -3, -4 etc. I am following this post https://stackoverflow.com/a/15972027/635027 to do this but I ran into an issue.
The slug stops at a -1 count when inserting into MySQL and keeps entering that over an over instead of increment to the next integer when finding a duplicate. Below is my query and associated lines. What am I doing wrong?
$slug = 'my-cool-slug';
$slug_query = "SELECT * FROM pv_events WHERE event_slug LIKE '".$slug."%'";
$slug_result = mysqli_query($conn,$slug_query);
$slugs = mysqli_fetch_array($slug_result,MYSQLI_ASSOC);
if(mysqli_num_rows($slug_result) !== 0 && in_array($slug, $slugs)){
$max = 0;
//keep incrementing $max until a space is found
while(in_array( ($slug . '-' . ++$max ), $slugs) );
//update $slug with the appendage
$slug .= '-' . $max;
}

mysqli_fetch_array selects the next row, not the entire result set, so $slugs would only contain the first result.
Secondly, if you want to start with 2, it would make sense to set $max to 1, not 0. The first iteration of your while, 1 will be added.

Just select "event_slug" instead "*"
$slug_query = "SELECT event_slug FROM pv_events WHERE event_slug LIKE '".$slug."%'";
Use mysqli_fetch_all
$slugs = mysqli_fetch_all($slug_result,MYSQLI_ASSOC);

Related

Getting Count on Number of Instances in Array (subtracting after continue; statement in loop)

I have a 'Pricing History Table' based off MySQL table.
Because we have a lot of alike listings, a lot of these entries appear as duplicates, aside from of course the ItemID.
Here's how I'm currently weeding out duplicates (not really duplicates, but similar listings that have the same SKUs, Y-m-d Date, Previous Price, New Price and Sales Channels. -- and also trying to get a count (see $count logic below) of how many alike/"duplicate" rows were found)
$inventoryhistoryrows = array();
$skuarray = array();
foreach ($pricehistoryarray as $ph_key => $ph_values) {
// defining variables, etc.
. . . . .
$ph_sku_timestamp = $inventoryskus . ' ' . $ph_timestamp . ' ' . $ph_previousprice . ' ' . $ph_newprice . ' ' . $ph_channel;
if (in_array($ph_sku_timestamp, $skuarray)) { continue; }
$skuarray[] = $ph_sku_timestamp;
if(isset($prev)) {
$newcount = $count - $prev;
$prev = $count;
}
else {
$prev = $count;
$newcount = $count;
}
$inventoryhistoryrows[] = array($newcount, $ph_itemid, $inventoryskus, $ph_previousprice, $ph_newprice, $ph_channel, $ph_timestamp);
This is working.... but my $newcount is always one row ahead!
Here's an illustration of output in table:
Note the arrows on the far left side. The $newcount variables are correct but the entire first column needs to moved up by one row.
Meaning, 1 should be removed from the first row. 3 Should be in the first row. 17 Should be in the second row.
I can of course see that the reason why 1 is showing up in the first row is due to this statement
else {
$newcount = $count;
}
Meaning it will always return 1 for the first row, as prev does not exist. But I simply put this there as I was unsure of a proper way to get the data as I wanted.
Anyone have any ideas on how I can do this? In the initial foreach loop for $pricehistoryarray (I suppose this would be the better solution), or a relatively simply method for shifting up only the first column once the $inventoryhistoryrows array is constructed?
Apparently this might be better off in the MySQL Query (see comments)
This seems to be working
SELECT COUNT(*) as count
, itemid
, previousprice
, newprice
, channel
, timestamp
FROM listing_price_history
WHERE listing_price_history.timestamp > DATE_SUB(now(), INTERVAL 30 DAY)
GROUP
BY previousprice
, newprice
, channel
, DATE(timestamp)
ORDER
BY listing_price_history.timestamp DESC
Big thanks to #Cid for the guidance

How to insert ID +1 and get last id?

I want to insert id and + 1 insert the form fields into a MySQL table. I want to get the last id for the insert operation as the return value of my query but I have some problems with it.
this is my code for get last id.
function GenIDInv()
{
$CI = get_instance();
$CI->db->select('n_id');
$CI->db->from('sltax_notification_name');
$CI->db->order_by("n_id", "desc");
$query = $CI->db->get();
$result = $query->row();
if(!empty($result)){
$result = $result->n_id;
$rid = substr($result,6,9);
$id = $rid+1;
echo date('Ym') . sprintf("%'.03d\n",$id);
}
}
when i insert id it not +1
What i understood is that you want 201812001 to 201812002
Try this:
$rid = substr($result, 8, 1);
//echo $rid; // $rid should contains 1
$id = $rid+1;
Codeigniter documents: http://codeigniter.org.cn/user_guide/database/query_builder.html?highlight=max#CI_DB_query_builder::select_max
SELECT Max(n_id) FROM sltax_notification_name;
I make an assumption that your field n_id is compose like this : [YYYYMM][XXX] => [DATE][ID]
first question what happens if your id is greater than 999 ?
i will assumpt that you want to handle id greater than 999.
So now, the problem we need to resolve is how to add 1 to the id part, and keep it padded with 0 on the left.
You get your last id from database that's nice, it is probably a string.
The first thing we want to do is get the id part separate from date part.
$n_id = $result->n_id;
$id = substr($n_id, 6, strlen($n_id)) // we know the first 6 characters are part of the date and the rest is part of id
then we want to add one to $id
$id += 1; // that statement will cast our string to int
#Now we want to cast it to string and pad with 0 if needed
if (strlen($id) < 3) {
$id = str_pad($id, 3, '0', STR_PAD_LEFT);
}
Now, we just have to stick the piece together
$date = new Datetime();
$newN_id = $date->format('Ym').(string)$id

Prevent duplicate ids from being added to session (array)

I got a session which adds ids to an array, the problem is every id gets added even if the id is already present. How can I prevent duplicate id's from being added to the array?
I figured I need to check for the id using in_array but I don't know exactly how to use it correctly.
I send the id of the product to my quote page using this link:
<p><a class="offertelink" href="offerte.php?product='.$productcr[0]['id'].'">Request a quote</a></p>
Then on that page I use the following code:
if(!isset($_SESSION['product'])){
$_SESSION['product'] = array();
}
// CHECK FIRST THAT $_GET['product'] IS SET BEFORE ADDING IT TO SESSION
if( isset($_GET['product'])){
$_SESSION['product'][] = $_GET['product'];
}
$prods = implode(",", $_SESSION['product']);
And finally load all the products with the ids that are inside the array:
if(count($_SESSION['product']) != 0){
// offerte overzicht
$offerte = "SELECT * FROM `snm_content` WHERE `id` in (".$conn->real_escape_string($prods).") AND state = 1";
$offertecon = $conn->query($offerte);
$offertecr = array();
while ($offertecr[] = $offertecon->fetch_array());
}
But now everytime I reload the page, the id is added again, it's not really bad since the products are only loaded once, but still I would like to fix this, because I think a query checking for tons of duplicate ids is not the best way.
Using in_array is simple - you just check if element is in array:
var_dump(in_array($element, $array));
In your case it is:
var_dump(in_array($_GET['product'], $_SESSION['product']));
And the check is:
// i advise you to check product value as `int`.
// Because values as `empty string` or `0` or `false` are considered set
if( 0 < intval($_GET['product']) && !in_array($_GET['product'], $_SESSION['product']) ) {
$_SESSION['product'][] = $_GET['product'];
}
But the more clever solution is to use product id as an array key with some fixed value (1 or true for example):
$_SESSION['product'] = [
'101' => 1,
'102' => 1,
'106' => 1,
];
In this case you don't even need to check if your key exists - if it exists it will be overwritten, if not - will be added:
if( 0 < intval($_GET['product']) ) {
$_SESSION['product'][ $_GET['product'] ] = 1;
}
// but here you need to take array keys instead of values
$prods = implode(",", array_keys($_SESSION['product']));
Option 1
Use in_array() to prevent duplicates:
// CHECK FIRST THAT $_GET['product'] IS SET BEFORE ADDING IT TO SESSION
if( isset($_GET['product'])){
if(!in_array($_GET['product'], $_SESSION['product']){
// product not exists in array
$_SESSION['product'][] = $_GET['product'];
}
}
Option 2 empty array before adding products
//if(!isset($_SESSION['product'])){
$_SESSION['product'] = array();
//}

mysql count occurrences of special character in a field

I am wanting to count all occurrences of the # symbol in a field and originally i thought LIKE '%#%' would be the way to go, but if the character appears in the field more than once it only counts it as one.
What other method are there that i could use that would count every occurrence?
Thanks.
EDIT
For anyone needing it, this is what i ended up using that works.
$count = 0;
$sql = mysql_query("SELECT LENGTH(field_name) - LENGTH(REPLACE(field_name,'#','')) AS 'occurs' FROM table_name WHERE field_name LIKE '%#%'");
while ($data = mysql_fetch_assoc($sql)) {
$count += $data['occurs'];
}
echo $count;
select length('aa:bb:cc:dd')-length(replace('aa:bb:cc:dd',':',''));
source: http://lists.mysql.com/mysql/215049
You could make this even simpler by using the ``substr_count function in php. see below.
$message = $row['themessage'];
echo substr_count($message, '#');
what this will return is the number of times # has occurred in your "themessage" field in your database.

php "count()" function and DB

I have a Joomla 1.5 site. I have articles in my site with different "status". What I'm trying to do is "count" and show how many articles have for example "status = 1"(expired) or "status = 3"(blocked) or "status = 2"(active) etc..
Here is the statuses in PhpMyAdmin - http://awesomescreenshot.com/07a8ijz75
Here is what I wrote, but it ALWAYS gives me same result - 1
<?php echo count($this->row->status==1) ?>
Did I miss something?
Thanks
Use the SQL count function.
select count(*) from articles where status = 1;
Use your DB! If you are sorting, counting, etc, data from a database in PHP code you're doing it wrong.
If you want all statuses, do something like:
select status, count(*) from articles group by status;
The count function in PHP counts all the elements in an array, and in your example you passed it a boolean value. As a result count doesn't know what to do with it, and so it returns -1, which isn't a valid count.
My PHP is really rusty (I haven't used it in a looong time), but here are two possible ways to accomplish what you want:
1. Use a function map/reduce style
<?php
$row[0]->status = 1;
$row[1]->status = 2;
$row[2]->status = 1;
$row[3]->status = 3;
$row[4]->status = 1;
// Count the number of statuses that are equal to 1
echo array_reduce(array_map(function($x) {
return $x->status == 1 ? 1: 0;
}, $row), function($x, $y) {return $x + $y;});
You'll have to replace the $row variable with $this->row, obviously. The code is essentially working in two steps. The inner part:
array_map(function($x) {
return $x->status == 1 ? 1: 0;
}, $row)
Creates a list where every status that's equal to 1 becomes a 1 and everything else becomes a 0. So you have an array of "array(1, 0, 1, 0, 1)". The out part of the code:
array_reduce( ... , function($x, $y) {return $x + $y;});
Takes the new array as the first argument and sums it all up by passing in the first two values of the array into the function, and then each following value and the result of the last function call. As a result all the values get summed, and you have a proper count of the matching values.
2. Use a simple procedural style
<?php
$row[0]->status = 1;
$row[1]->status = 2;
$row[2]->status = 1;
$row[3]->status = 3;
$row[4]->status = 1;
// Do it again, but in a procedural style
$num_1_statuses = 0;
foreach ($row as $r) {
if ($r->status == 1) {
$num_1_statuses++;
}
}
echo $num_1_statuses;
This should be really straightforward, it just has a variable that gets incremented whenever a row's status matches.

Categories