Wordpress database insert() and update() - using NULL values - php

Wordpress ships with the wpdb class which handles CRUD operations. The two methods of this class that I'm interested in are the insert() (the C in CRUD) and update() (the U in CRUD).
A problem arises when I want to insert a NULL into a mysql database column - the wpdb class escapes PHP null variables to empty strings. How can I tell Wordpress to use an actual MySQL NULL instead of a MySQL string?

If you want it to compatible you would have to SHOW COLUMN and determine ahead if NULL is allowed. If it was allowed then if the value was empty($v) use val = NULL in the query.
$foo = null;
$metakey = "Harriet's Adages";
$metavalue = "WordPress' database interface is like Sunday Morning: Easy.";
if ($foo == null) {
$wpdb->query( $wpdb->prepare( "
INSERT INTO $wpdb->postmeta
( post_id, meta_key, meta_value, field_with_null )
VALUES ( %d, %s, %s, NULL )",
10, $metakey, $metavalue ) );
} else {
$wpdb->query( $wpdb->prepare( "
INSERT INTO $wpdb->postmeta
( post_id, meta_key, meta_value, field_with_null )
VALUES ( %d, %s, %s, %s)",
10, $metakey, $metavalue, $foo ) );
}

Here's a solution to your problem. In "wp-content" folder, create a file named "db.php" and put this code in it:
<?php
// setup a dummy wpdb to prevent the default one from being instanciated
$wpdb = new stdclass();
// include the base wpdb class to inherit from
//include ABSPATH . WPINC . "/wp-db.php";
class wpdbfixed extends wpdb
{
function insert($table, $data, $format = null) {
$formats = $format = (array) $format;
$fields = array_keys($data);
$formatted_fields = array();
$real_data = array();
foreach ( $fields as $field ) {
if ($data[$field]===null)
{
$formatted_fields[] = 'NULL';
continue;
}
if ( !empty($format) )
$form = ( $form = array_shift($formats) ) ? $form : $format[0];
elseif ( isset($this->field_types[$field]) )
$form = $this->field_types[$field];
else
$form = '%s';
$formatted_fields[] = "'".$form."'";
$real_data[] = $data[$field];
}
//$sql = "INSERT INTO <code>$table</code> (<code>" . implode( '</code>,<code>', $fields ) . "</code>) VALUES (" . implode( ",", $formatted_fields ) . ")";
$sql = "INSERT INTO $table (" . implode( ',', $fields ) . ") VALUES (" . implode( ",", $formatted_fields ) . ")";
return $this->query( $this->prepare( $sql, $real_data) );
}
function update($table, $data, $where, $format = null, $where_format = null)
{
if ( !is_array( $where ) )
return false;
$formats = $format = (array) $format;
$bits = $wheres = array();
$fields = (array) array_keys($data);
$real_data = array();
foreach ( $fields as $field ) {
if ($data[$field]===null)
{
$bits[] = "$field = NULL";
continue;
}
if ( !empty($format) )
$form = ( $form = array_shift($formats) ) ? $form : $format[0];
elseif ( isset($this->field_types[$field]) )
$form = $this->field_types[$field];
else
$form = '%s';
$bits[] = "$field = {$form}";
$real_data[] = $data[$field];
}
$where_formats = $where_format = (array) $where_format;
$fields = (array) array_keys($where);
foreach ( $fields as $field ) {
if ( !empty($where_format) )
$form = ( $form = array_shift($where_formats) ) ? $form : $where_format[0];
elseif ( isset($this->field_types[$field]) )
$form = $this->field_types[$field];
else
$form = '%s';
$wheres[] = "$field = {$form}";
}
$sql = "UPDATE $table SET " . implode( ', ', $bits ) . ' WHERE ' . implode( ' AND ', $wheres );
return $this->query( $this->prepare( $sql, array_merge($real_data, array_values($where))) );
}
}
$wpdb = new wpdbfixed(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
?>
In this way you can use null values with wpdb!

I find this on Wordpress StackExchange forum and it works very well for me.
// Add a filter to replace the 'NULL' string with NULL
add_filter( 'query', 'wp_db_null_value' );
global $wpdb;
$wpdb->update(
'table',
array(
'status' => 'NULL',
),
array( 'id' => 1 )
);
// Remove the filter again:
remove_filter( 'query', 'wp_db_null_value' );
and the function wp_db_null_value is:
/**
* Replace the 'NULL' string with NULL
*
* #param string $query
* #return string $query
*/
function wp_db_null_value( $query )
{
return str_ireplace( "'NULL'", "NULL", $query );
}
Because in my case I cannot use $db->prepare() function...

wpdb insert() and update() works with NULL values, it was patched many years ago but never mentioned in the Codex.
In your case:
$wpdb->update(
'table',
array(
'status' => null,
),
array( 'id' => 1 ),
null,
'%d'
);
Ref: https://core.trac.wordpress.org/ticket/15158#no0

I tried to edit one of the other solutions listed here, because it resulted in the format array being misaligned with the data array, but failed.
Here is a solution that modifies the wpdb from the latest version of wordpress, in order to allow inserting and updating null values into SQL tables using insert() and update():
/*
* Fix wpdb to allow inserting/updating of null values into tables
*/
class wpdbfixed extends wpdb
{
function insert($table, $data, $format = null) {
$type = 'INSERT';
if ( ! in_array( strtoupper( $type ), array( 'REPLACE', 'INSERT' ) ) )
return false;
$this->insert_id = 0;
$formats = $format = (array) $format;
$fields = array_keys( $data );
$formatted_fields = array();
foreach ( $fields as $field ) {
if ( !empty( $format ) )
$form = ( $form = array_shift( $formats ) ) ? $form : $format[0];
elseif ( isset( $this->field_types[$field] ) )
$form = $this->field_types[$field];
else
$form = '%s';
//***Steve Lee edit begin here***
if ($data[$field]===null) {
unset($data[$field]); //Remove this element from array, so we don't try to insert its value into the %s/%d/%f parts during prepare(). Without this, array would become shifted.
$formatted_fields[] = 'NULL';
} else {
$formatted_fields[] = $form; //Original line of code
}
//***Steve Lee edit ends here***
}
$sql = "{$type} INTO `$table` (`" . implode( '`,`', $fields ) . "`) VALUES (" . implode( ",", $formatted_fields ) . ")";
return $this->query( $this->prepare( $sql, $data ) );
}
function update($table, $data, $where, $format = null, $where_format = null)
{
if ( ! is_array( $data ) || ! is_array( $where ) )
return false;
$formats = $format = (array) $format;
$bits = $wheres = array();
foreach ( (array) array_keys( $data ) as $field ) {
if ( !empty( $format ) )
$form = ( $form = array_shift( $formats ) ) ? $form : $format[0];
elseif ( isset($this->field_types[$field]) )
$form = $this->field_types[$field];
else
$form = '%s';
//***Steve Lee edit begin here***
if ($data[$field]===null)
{
unset($data[$field]); //Remove this element from array, so we don't try to insert its value into the %s/%d/%f parts during prepare(). Without this, array would become shifted.
$bits[] = "`$field` = NULL";
} else {
$bits[] = "`$field` = {$form}"; //Original line of code
}
//***Steve Lee edit ends here***
}
$where_formats = $where_format = (array) $where_format;
foreach ( (array) array_keys( $where ) as $field ) {
if ( !empty( $where_format ) )
$form = ( $form = array_shift( $where_formats ) ) ? $form : $where_format[0];
elseif ( isset( $this->field_types[$field] ) )
$form = $this->field_types[$field];
else
$form = '%s';
$wheres[] = "`$field` = {$form}";
}
$sql = "UPDATE `$table` SET " . implode( ', ', $bits ) . ' WHERE ' . implode( ' AND ', $wheres );
return $this->query( $this->prepare( $sql, array_merge( array_values( $data ), array_values( $where ) ) ) );
}
}
global $wpdb_allow_null;
$wpdb_allow_null = new wpdbfixed(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
Insert this code into somewhere that always gets run, like your functions.php, and then use your new global $wpdb_allowed_null->insert() and ->update() as normal.
I preferred this method vs. overriding the default $wpdb, in order to preserve the DB behavior that the rest of Wordpress and other plugins will expect.

Related

add hook in product search query

I'm developing a plugin for my shopping site. The plugin works like this. Color variations of the same product are on different product pages. The products are connected together as shown in the photo below.
and on the product page as small photos, it is shown as color variants of the product.
It works flawlessly so far.
but I am using multi-vendor plugin on my website.
. I want it to search only the products belonging to the author, the user, that is the store, while selecting the product.
for this, is it possible to add a filter to the query made in the ajax request and rewrite the query?
add_filter('woocommerce_product_pre_search_products', 'woocommerce_product_pre_search_products', 10, 6);
function woocommerce_product_pre_search_products( $custom_query=false, $term, $type, $include_variations, $all_statuses, $limit) {
global $wpdb;
$post_types = $include_variations ? array( 'product', 'product_variation' ) : array( 'product' );
$join_query = '';
$type_where = '';
$status_where = '';
$limit_query = '';
// When searching variations we should include the parent's meta table for use in searches.
if ( $include_variations ) {
$join_query = " LEFT JOIN {$wpdb->wc_product_meta_lookup} parent_wc_product_meta_lookup
ON posts.post_type = 'product_variation' AND parent_wc_product_meta_lookup.product_id = posts.post_parent ";
}
/**
* Hook woocommerce_search_products_post_statuses.
*
* #since 3.7.0
* #param array $post_statuses List of post statuses.
*/
$post_statuses = apply_filters(
'woocommerce_search_products_post_statuses',
current_user_can( 'edit_private_products' ) ? array( 'private', 'publish' ) : array( 'publish' )
);
// See if search term contains OR keywords.
if ( stristr( $term, ' or ' ) ) {
$term_groups = preg_split( '/\s+or\s+/i', $term );
} else {
$term_groups = array( $term );
}
$search_where = '';
$search_queries = array();
foreach ( $term_groups as $term_group ) {
$search_terms = array( $term_group );
$term_group_query = '';
$searchand = '';
foreach ( $search_terms as $search_term ) {
$like = '%' . $wpdb->esc_like( $search_term ) . '%';
// Variations should also search the parent's meta table for fallback fields.
if ( $include_variations ) {
$variation_query = $wpdb->prepare( " OR ( wc_product_meta_lookup.sku = '' AND parent_wc_product_meta_lookup.sku LIKE %s ) ", $like );
} else {
$variation_query = '';
}
$term_group_query .= $wpdb->prepare( " {$searchand} ( ( posts.post_title LIKE %s) OR ( posts.post_excerpt LIKE %s) OR ( posts.post_content LIKE %s ) OR ( wc_product_meta_lookup.sku LIKE %s ) $variation_query)", $like, $like, $like, $like ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$searchand = ' AND ';
}
if ( $term_group_query ) {
$search_queries[] = $term_group_query;
}
}
if ( ! empty( $search_queries ) ) {
$search_where = ' AND (' . implode( ') OR (', $search_queries ) . ') ';
}
if ( ! empty( $include ) && is_array( $include ) ) {
$search_where .= ' AND posts.ID IN(' . implode( ',', array_map( 'absint', $include ) ) . ') ';
}
if ( ! empty( $exclude ) && is_array( $exclude ) ) {
$search_where .= ' AND posts.ID NOT IN(' . implode( ',', array_map( 'absint', $exclude ) ) . ') ';
}
$search_where .= ' AND posts.post_author='. get_current_user_id();
if ( 'virtual' === $type ) {
$type_where = ' AND ( wc_product_meta_lookup.virtual = 1 ) ';
} elseif ( 'downloadable' === $type ) {
$type_where = ' AND ( wc_product_meta_lookup.downloadable = 1 ) ';
}
if ( ! $all_statuses ) {
$status_where = " AND posts.post_status IN ('" . implode( "','", $post_statuses ) . "') ";
}
if ( $limit ) {
$limit_query = $wpdb->prepare( ' LIMIT %d ', $limit );
}
// phpcs:ignore WordPress.VIP.DirectDatabaseQuery.DirectQuery
$search_results = $wpdb->get_results(
// phpcs:disable
"SELECT DISTINCT posts.ID as product_id, posts.post_parent as parent_id FROM {$wpdb->posts} posts
LEFT JOIN {$wpdb->wc_product_meta_lookup} wc_product_meta_lookup ON posts.ID = wc_product_meta_lookup.product_id
$join_query
WHERE posts.post_type IN ('" . implode( "','", $post_types ) . "')
$search_where
$status_where
$type_where
ORDER BY posts.post_parent ASC, posts.post_title ASC
$limit_query
"
// phpcs:enable
);
$product_ids = wp_parse_id_list( array_merge( wp_list_pluck( $search_results, 'product_id' ), wp_list_pluck( $search_results, 'parent_id' ) ) );
if ( is_numeric( $term ) ) {
$post_id = absint( $term );
$post_type = get_post_type( $post_id );
if ( 'product_variation' === $post_type && $include_variations ) {
$product_ids[] = $post_id;
} elseif ( 'product' === $post_type ) {
$product_ids[] = $post_id;
}
$product_ids[] = wp_get_post_parent_id( $post_id );
}
return wp_parse_id_list( $product_ids );
}

Wordpress Database query and Output as HTML list

I'm trying to get a PHP Code to work in order to make a Database query within a Wordpress database table. The results (all distinct values of one specific column) should be put out within an HTML list. I want to be able to place the output everywhere in my content, so it should be accessable via shortcode.
Here's what I got so far. This code does not produce any errors in wordpress or the console, but it also doesn't do the trick... Nothing appears at the desired place.
class my_Shortcode {
var $echo;
function __construct() {
add_shortcode( 'my_plugin', array( $this, 'shortcode' ) );
}
function shortcode( $atts ) {
global $wpdb;
$table = isset( $atts['table'] ) ? $atts['table'] : false;
$column = isset( $atts['column'] ) ? $atts['column'] : false;
$listDisplay = isset( $atts['listDisplay'] ) ? $atts['listDisplay'] : false;
if ( $listDisplay == true ) {
if ( false != $table && false != $column ) {
$this->echo = "";
$results = $wpdb->get_results(
prepare('SELECT DISTINCT ' . $column . ' FROM ' . $table)
);
$this->echo .= "<div class=\"list\"><ul>";
foreach ($results as $result) {
$this->echo .= "<li>$result</li>\n";
}
$this->echo .= "</ul></div>";
return $this->echo;
}
}
}
}
I'm glad about any suggestions!
Do you want likve this?
<?php
echo do_shortcode("[my_plugin table='wp_posts' column=id]");
?>
class my_Shortcode {
var $echo;
function __construct() {
add_shortcode( 'my_plugin', array( $this, 'shortcode' ) );
}
function shortcode( $atts ) {
global $wpdb;
$table = isset( $atts['table'] ) ? $atts['table'] : false;
$column = isset( $atts['column'] ) ? $atts['column'] : false;
$listDisplay = isset( $atts['listDisplay'] ) ? $atts['listDisplay'] : true;
if ( $listDisplay == true ) {
if ( false != $table && false != $column ) {
$this->echo = "";
$results = $wpdb->get_results("SELECT DISTINCT $column FROM $table ",ARRAY_A);
$this->echo .= "<div class=\"list\"><ul>";
foreach ($results as $key => $result) {
$keys = array_keys( $result);
$this->echo .= '<li>'.$result[ $keys[0] ].'</li>\n';
}
$this->echo .= "</ul></div>";
return $this->echo;
}
}
}
}
$test = new my_Shortcode();

Fetching and echoing results with php

I'm having an issue displaying the results of query. The weird thing is, all of the results are being obtained and only one is not. I'm at a complete loss.
I'm going to describe, to the best of my knowledge, how this code is supposed to work. I built it from a tutorial.
In "listProducts.php" all the products in the database are listed in a table.
<table id="productTable">
<tr>
<th>UPC</th>
<th>Title</th>
<th>Thumb</th>
<th>Price</th>
<th>Stock</th>
<th>Lead Time</th>
<th></th>
</tr>
<?php foreach ( $results['products'] as $product ) {
list($week, $day) = explode("|", $product->lead);
echo htmlspecialchars($product->lead);
?>
<tr onclick="location='products.php?action=editProduct&productId=<?php echo $product->id?>'">
<td><img src="../<?php echo $product->thumb ?>"/></td>
<td><?php echo htmlspecialchars($product->upc)?></td>
<td><?php echo htmlspecialchars($product->title)?></td>
<td style="text-align:right;">$<?php echo number_format($product->price, 2 )?></td>
<td style="text-align:right;"><?php echo number_format($product->stock, 0)?></td>
<td style="text-align:right;"><? echo $week.'|'.$day;?></td>
<td><button >Edit</button></td>
</tr>
<? } ?>
</table>
The problem is lead, which exists in the database as lead, is not being or has not been fetched and therefore not being exploded and is therefore not being echoed as week and day.
Even if, for testing purposes, I echo just lead, i get nothing.
<? echo htmlspecialchars($products->lead)?>
There is a listProducts() function and some class junk that i did not come up with, but I have thoroughly manipulated to my own ends so I'm fairly confident that they should work. But, I'll post them anyway.
function listProducts() {
$results = array();
$data = Product::getList();
$results['products'] = $data['results'];
$results['totalRows'] = $data['totalRows'];
$results['pageTitle'] = "All Products";
if ( isset( $_GET['error'] ) ) {
if ( $_GET['error'] == "productNotFound" ) $results['errorMessage'] = "Error: Product not found.";
}
if ( isset( $_GET['status'] ) ) {
if ( $_GET['status'] == "changesSaved" ) $results['statusMessage'] = "Your changes have been saved.";
if ( $_GET['status'] == "productDeleted" ) $results['statusMessage'] = "Product deleted.";
}
require( TEMPLATE_PATH . "/admin/listProducts.php" );
}
And here is the parts of the product class that i think deal with displaying the list... cus it says get list.
public static function getList( $numRows=100, $order="title DESC" ) {
$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$sql = "SELECT SQL_CALC_FOUND_ROWS *, id FROM products
ORDER BY " . $order . " LIMIT :numRows";
$st = $conn->prepare( $sql );
$st->bindValue( ":numRows", $numRows, PDO::PARAM_INT );
$st->execute();
$list = array();
while ( $row = $st->fetch() ) {
$product = new Product( $row );
$list[] = $product;
}
// Now get the total number of products that matched the criteria
$sql = "SELECT FOUND_ROWS() AS totalRows";
$totalRows = $conn->query( $sql )->fetch();
$conn = null;
return ( array ( "results" => $list, "totalRows" => $totalRows[0] ) );
}
and some constructors and variables. I don't know if they are necessary or not
public $id = null;
public $upc = null;
public $title = null;
public $thumb = null;
public $description = null;
public $price = null;
public $stock = null;
public $lead = null;
public function __construct( $data=array() ) {
if ( isset( $data['id'] ) ) $this->id = (int) $data['id'];
if ( isset( $data['upc'] ) ) $this->upc = preg_replace ( "/[^\.\,\-\_\'\"\#\?\!\:\$ a-zA-Z0-9()]/", "", $data['upc'] );
if ( isset( $data['title'] ) ) $this->title = preg_replace ( "/[^\.\,\-\_\'\"\#\?\!\:\$ a-zA-Z0-9()]/", "", $data['title'] );
if ( isset( $data['thumb'] ) ) $this->thumb = $data['thumb'];
if ( isset( $data['description'] ) ) $this->description = $data['description'];
if ( isset( $data['price'] ) ) $this->price = $data['price'];
if ( isset( $data['stock'] ) ) $this->stock = (int) $data['stock'];
if ( isset( $data['week'] ) && isset( $data['day'] ) ) $this->lead = $data['week']."|".$data['day'];
}

WordPress $wpdb->update set float to null?

Is there a way to set a column to NULL using $wpdb->update();?
When I attempt to, WordPress attempts to typecast that column to a float, which converts NULL to 0.
I've checked the core code and inside of $wpdb->update(), the $format parameter is only expecting %s, %f, and %d. I went so far as to set $wpdb->field_types['myCol'] to 'NULL', but both only serve to break $wpdb->update()'s query (interestingly enough, it shifts the values for each column over after the NULL).
There is a related question here, but that answer only deals with INSERT, not UPDATE.
From a data integrity standpoint, NULL is very important for this column, so I have to be able to set it as such when necessary.
As you yourself note, the $format parameter is only expecting %s, %f, and %d. The whole thing will get passed through prepare which also doesn't take a null format specifier because it basically accepts the same format specifiers that are accepted by (v)(s)printf but without the argument swapping. You can't pass NULL through update. You have the same choices as mentioned in the post suggested as a possible duplicate, and in essence it is.
Just don't use the update function. Write your own SQL and use it with $wpdb->query. If you are dealing with your own tables that should be fine.
Create your own database class that will do what you want. It is a little know fact that you can replace WordPress' $wpdb with a drop-in.
Here is a solution that modifies the wpdb from the latest version of wordpress, in order to allow inserting and updating null values into SQL tables using insert() and update():
/*
* Fix wpdb to allow inserting/updating of null values into tables
*/
class wpdbfixed extends wpdb
{
function insert($table, $data, $format = null) {
$type = 'INSERT';
if ( ! in_array( strtoupper( $type ), array( 'REPLACE', 'INSERT' ) ) )
return false;
$this->insert_id = 0;
$formats = $format = (array) $format;
$fields = array_keys( $data );
$formatted_fields = array();
foreach ( $fields as $field ) {
if ( !empty( $format ) )
$form = ( $form = array_shift( $formats ) ) ? $form : $format[0];
elseif ( isset( $this->field_types[$field] ) )
$form = $this->field_types[$field];
else
$form = '%s';
//***edit begin here***
if ($data[$field]===null) {
unset($data[$field]); //Remove this element from array, so we don't try to insert its value into the %s/%d/%f parts during prepare(). Without this, array would become shifted.
$formatted_fields[] = 'NULL';
} else {
$formatted_fields[] = $form; //Original line of code
}
//***edit ends here***
}
$sql = "{$type} INTO `$table` (`" . implode( '`,`', $fields ) . "`) VALUES (" . implode( ",", $formatted_fields ) . ")";
return $this->query( $this->prepare( $sql, $data ) );
}
function update($table, $data, $where, $format = null, $where_format = null)
{
if ( ! is_array( $data ) || ! is_array( $where ) )
return false;
$formats = $format = (array) $format;
$bits = $wheres = array();
foreach ( (array) array_keys( $data ) as $field ) {
if ( !empty( $format ) )
$form = ( $form = array_shift( $formats ) ) ? $form : $format[0];
elseif ( isset($this->field_types[$field]) )
$form = $this->field_types[$field];
else
$form = '%s';
//***edit begin here***
if ($data[$field]===null)
{
unset($data[$field]); //Remove this element from array, so we don't try to insert its value into the %s/%d/%f parts during prepare(). Without this, array would become shifted.
$bits[] = "`$field` = NULL";
} else {
$bits[] = "`$field` = {$form}"; //Original line of code
}
//***edit ends here***
}
$where_formats = $where_format = (array) $where_format;
foreach ( (array) array_keys( $where ) as $field ) {
if ( !empty( $where_format ) )
$form = ( $form = array_shift( $where_formats ) ) ? $form : $where_format[0];
elseif ( isset( $this->field_types[$field] ) )
$form = $this->field_types[$field];
else
$form = '%s';
$wheres[] = "`$field` = {$form}";
}
$sql = "UPDATE `$table` SET " . implode( ', ', $bits ) . ' WHERE ' . implode( ' AND ', $wheres );
return $this->query( $this->prepare( $sql, array_merge( array_values( $data ), array_values( $where ) ) ) );
}
}
global $wpdb_allow_null;
$wpdb_allow_null = new wpdbfixed(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
Insert this code into somewhere that always gets run, like your functions.php, and then use your new global $wpdb_allowed_null->insert() and ->update() as normal.
I preferred doing it this way vs. overriding the default $wpdb, in order to preserve the DB behavior that the rest of Wordpress and other plugins will expect.

Magento : Issue Category name is auto renaming while saving

i am importing the products with advance data flow profile and facing the weird problem while saving the category as i am passing the category name to my function as
Parent Category/Child category
The / sign between categories automatically create and assign the product to child category
it is working as expected but in my case the Parent Category name is renaming somehow i have checked that i am passing the right name to the function...
e.g. Semipreciuos gem stone beads/Stone type is saving as Semipreciuos gem stone bead/Stone type
The last s word is missing from the name
protected function _addCategories($categories,$desc='',$discountable,$store) {
$rootId = $store->getRootCategoryId ();
if (! $rootId) {
return array();
}
$rootPath = '1/' . $rootId;
if (empty ( $this->_categoryCache [$store->getId ()] )) {
$collection = Mage::getModel ( 'catalog/category' )->getCollection ()->setStore($store)->addAttributeToSelect ( 'name' );
$collection->getSelect ()->where ( "path like '" . $rootPath . "/%'" );
foreach ( $collection as $cat ) {
$pathArr = explode ( '/', $cat->getPath () );
$namePath = '';
for($i = 2, $l = sizeof ( $pathArr ); $i < $l; $i ++) {
$name = $collection->getItemById ( $pathArr [$i] )->getName ();
$namePath .= (empty ( $namePath ) ? '' : '/') . trim ( $name );
}
$cat->setNamePath ( $namePath );
}
$cache = array();
foreach ( $collection as $cat ) {
$cache [strtolower ( $cat->getNamePath () )] = $cat;
$cat->unsNamePath ();
}
$this->_categoryCache [$store->getId ()] = $cache;
}
$cache = & $this->_categoryCache [$store->getId ()];
$catIds = array();
foreach ( explode ( ',', $categories ) as $categoryPathStr ) {
$categoryPathStr = preg_replace ( '#s*/s*#', '/', trim ( $categoryPathStr ) );
if (! empty ( $cache [$categoryPathStr] )) {
$catIds [] = $cache [$categoryPathStr]->getId ();
continue;
}
$path = $rootPath;
$namePath = '';
foreach ( explode ( '/', $categoryPathStr ) as $catName ) {
$namePath .= (empty ( $namePath ) ? '' : '/') . strtolower ( $catName );
if (empty ( $cache [$namePath] )) {
$cat = Mage::getModel('catalog/category')->setStoreId($store->getId())->setPath ( $path )->setName ( $catName )->// comment out the following line if new categories should stay inactive
setIsActive(1)->setDescription($desc)->setData('discountable',$discountable)->save();
$cache [$namePath] = $cat;
}
$catId = $cache [$namePath]->getId ();
$path .= '/' . $catId;
}
##Assigning product to child category
/*$parentId = null;
$currentcat = Mage::getModel("catalog/category")->load($catId);
$parentId = $currentcat->getParentId();
if($parentId){
$catIds[] = $parentId;
}
*/
if ($catId) {
$catIds [] = $catId;
}
}
return join ( ',', $catIds );
}
Above is my category function for creating categories... any one has any idea what is going on..
It is not related to Magento, but rather to PHP & regular expression.
$categoryPathStr = preg_replace ( '#s*/s*#', '/', trim ( $categoryPathStr ) );
That line replaces "s*/s*" with "/", which is why you have your last s removed. I see no real reason for that preg_replace (?), so just remove that line, or replace it with
$categoryPathStr = trim ( $categoryPathStr );
so that leading/ending white spaces get removed.

Categories