I would like to know how can I do a SELECT from a Magento core table but not using pure SQL but using collections.
Currently, inside a class that extends Mage_Core_Model_Abstract, on a given function I have the following code:
$resource = Mage::getSingleton("core/resource");
$tableName_SalesQuoteItem = $resource->getTableName("sales/quote_item");
$readConnection = $resource->getConnection("core_read");
$sqlInstruction = "SELECT item_id FROM {$tableName_SalesQuoteItem} WHERE sku = :sku AND quote_id = :quote_id;";
$binds = array("sku" => $itemSku, "quote_id" => $quoteID);
$result = $readConnection->query($sqlInstruction, $binds);
if($row = $result->fetch()) {
$currentItemID = $row["item_id"];
}
Any ideas?
Thanks!
The issue appears to be is that you're trying to load the header table 'sales/quote' and call items on it, when the items are stored in the sub-table sales/quote_item
Here's a functional prototype:
<?php
require_once( 'app/Mage.php' );
umask(0);
Mage::app('default');
$sCustomerId = 1;
$oQuotes = Mage::getModel( 'sales/quote' )->getCollection();
$oQuotes->addFieldToFilter( 'customer_id', $sCustomerId );
foreach( $oQuotes as $oQuote )
{
var_dump( $oQuote->getId() );
var_dump( $oQuote->getData( 'customer_email' ) );
var_dump( $oQuote->getData( 'customer_id' ) );
$oItems = Mage::getModel( 'sales/quote_item' )
->getCollection()
->setQuote( $oQuote );
foreach( $oItems as $oItem )
{
var_dump( $oItem->getData( 'sku' ) );
var_dump( $oItem->getData( 'name' ) );
var_dump( $oItem->getData( 'description' ) );
var_dump( $oItem->getData( 'price' ) );
}
}
$iCountQuotes = $oQuotes->count();
var_dump( $iCountQuotes );
?>
From your question it appears that you are looking for an ORM way to achieve the same thing you are doing with your query.
Here you go:
$collection = Mage::getModel('sales/quote')->getCollection();
$collection->addAttributeToFilter('sku',$itemSku);
$collection->addAttributeToFilter('quote_id',$quoteID);
if($collection->count())
{
//Add your code here
$firstItem = $collection->getFirstItem();
print_r($firstItem);
}
Read more about Magento ORM basics here
You could alternatively try addFieldToFilter if addAttributeToFilter doesn't work.
Related
So basically I am writing a new wordpress theme, Usually i add a new category in wordpress using the admin panel by filling in some info: "name" and the "slug".
I want to do this in my theme by overriding the funtions.php file
For example creating a new category named : New category , with the slug new_category .
Is it possible ?
And of course, I know that this idea doesn't exactly follow some theme programming guidelines such as envato guideline or the Wordpress.org publishers guideline. And yes the best thing would be to make a plugin for this. But here I am talking about a practical point of view, So is it possible? could you just point me up in the right direction (maybe a link to some doc or so?).
Thanks to #Coder comments I wrote this code that works like a charm for me :
$mycat_name = 'New category'; //The name of category that I want to add
$mycat_slug = 'new-category'; //The slug (no spaces, lower-cases)
$mycat = $wpdb->get_results( "SELECT t.*, tt.* FROM $wpdb->terms AS t
INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id
WHERE tt.taxonomy = 'category' AND t.name = '" . $mycat_name . "'");
$checking = sizeof($mycat) ;
//found out that size is 0 if there the category doesn't exist
if ($checking === 0){
$category = array('cat_name'=>$mycat_name, 'category_nicename'=>$mycat_slug);
wp_insert_category($category);
}
So this works and you an just add it anywhere (maybe index.php) , also this wil require you to add the following function that I got from wordpress taxonomy file
function wp_insert_category( $catarr, $wp_error = false ) {
$cat_defaults = array(
'cat_ID' => 0,
'taxonomy' => 'category',
'cat_name' => '',
'category_description' => '',
'category_nicename' => '',
'category_parent' => '',
);
$catarr = wp_parse_args( $catarr, $cat_defaults );
if ( trim( $catarr['cat_name'] ) == '' ) {
if ( ! $wp_error ) {
return 0;
} else {
return new WP_Error( 'cat_name', __( 'You did not enter a category name.' ) );
}
}
$catarr['cat_ID'] = (int) $catarr['cat_ID'];
// Are we updating or creating?
$update = ! empty( $catarr['cat_ID'] );
$name = $catarr['cat_name'];
$description = $catarr['category_description'];
$slug = $catarr['category_nicename'];
$parent = (int) $catarr['category_parent'];
if ( $parent < 0 ) {
$parent = 0;
}
if ( empty( $parent )
|| ! term_exists( $parent, $catarr['taxonomy'] )
|| ( $catarr['cat_ID'] && term_is_ancestor_of( $catarr['cat_ID'], $parent, $catarr['taxonomy'] ) ) ) {
$parent = 0;
}
$args = compact( 'name', 'slug', 'parent', 'description' );
if ( $update ) {
$catarr['cat_ID'] = wp_update_term( $catarr['cat_ID'], $catarr['taxonomy'], $args );
} else {
$catarr['cat_ID'] = wp_insert_term( $catarr['cat_name'], $catarr['taxonomy'], $args );
}
if ( is_wp_error( $catarr['cat_ID'] ) ) {
if ( $wp_error ) {
return $catarr['cat_ID'];
} else {
return 0;
}
}
return $catarr['cat_ID']['term_id'];
}
Works for me, a Quick and dirty way to push gategories in your thee directly.
From a practical point (this is good) but still a bad idea with regards to wordpress publishers guidelines where this code must at least be in a plugin.
I'm in the process of developing a WordPress plugin. When editing a user's profile page, I need to be able to retrieve the ID of that user (not the currently logged in user).
I'm using the Advanced Custom fields plugin, and using a load filter for the function in question.
add_filter( 'acf/load_field/name=funbotic_parents', 'funbotic_load_parents' );
function funbotic_load_parents( $field ) {
$args = array(
'role' => 'customer',
'orderby' => 'display_name',
'order' => 'ASC',
);
$parent_data_array = get_users( $args );
// Clear choices array in case it was previously set.
$field['choices'] = array();
foreach ( $parent_data_array as $parent ) {
$parent_ID = $parent->ID;
$parent_display_name = $parent->display_name;
$field['choices'][$parent_ID] = $parent_display_name;
}
$current_user = (int) $_GET['user_id'];
$previously_associated_parents = get_user_meta( $current_user_id, 'funbotic_parents' );
if ( empty( $previously_associated_parents ) || is_null( $previously_associated_parents ) ) {
update_user_meta( $current_user_id, 'funbotic_previously_associated_parents', $previously_associated_parents );
} else {
$new_meta = funbotic_clean_array( $previously_associated_parents );
update_user_meta( $current_user_id, 'funbotic_previously_associated_parents', $new_meta );
}
return $field;
}
The line $current_user = (int) $_GET['user_id']; is returning null. Is there a way to pull 'user_id' from the URL? It's not an ideal solution but at this point I'm starting to get desperate. The URL looks like this:
http://dev-funbotic.local/wp-admin/user-edit.php?user_id=115&wp_http_referer=%2Fwp-admin%2Fusers.php%3Fs%3Dtest%26action%3D-1%26new_role%26course_id%26group_id%26paged%3D1%26action2%3D-1%26new_role2
You can try getting the current url and breaking it down to query params like this:
$query = explode('&', $_SERVER['QUERY_STRING']);
$params = array();
if(!empty($query[0])){
foreach( $query as $param ){
list($name, $value) = explode('=', $param, 2);
$params[urldecode($name)][] = urldecode($value);
}
}
then you can access the user_id by $params['user_id'][0]
I'm programming a web app. The backend is a RESTFul app based in Laravel 4.
I'm having problems with a particular controller.
BedsController.php
class BedsController extends \BaseController {
/**
* Display a listing of the resource.
* GET /beds
*
* #return Response
*/
public function index()
{
//
$user = JWTAuth::parseToken()->authenticate();
$data = Input::get('room');
$retorno = array();
$hoy = date('Y-m-d');
if( $data ){
$d = intval( $data );
$beds = Bed::where('room', '=', $d )->get( array('size', 'room', 'id', 'name') );
foreach( $beds as $b ){
$b->stay = Stay::where('bed', '=', $b->id )
->where('indate', '<=', $hoy )
->where('outdate', '>=', $hoy )
->get( array( 'id', 'room', 'bed', 'guest', 'booking', 'indate', 'outdate' ) );
dd( $b->stay );
if( isset( $b->stay->guest ) ){
$b->stay->huesped = Guest::find( $b->stay->guest );
}else{}
if( isset( $b->stay->booking ) ){
$b->stay->huesped = Booking::find( $b->stay->booking );
}
//dd( $b->stay );
array_push( $retorno, $b );
}
//$room = Room::find( $d );
//return $room->camas()->get( 'size', 'room', 'id');
//$beds = Bed::where('room', $data )->get();
}else{
$beds = Bed::where('hotel', '=', $user->hostel )->get( array('size', 'room', 'id', 'name') );
foreach( $beds as $b ){
$be = $b['attributes'];
$st = array();
$stay = Stay::where('bed', '=', $b->id )
->where('indate', '<=', $hoy )
->where('outdate', '>=', $hoy )
->get( array( 'id', 'room', 'bed', 'guest', 'booking', 'indate', 'outdate' ) );
//return $stay[0];
$st = $stay[0];
//dd( $stay[0] );
if( isset( $stay[0] ) ){
if( $stay[0]['attributes']['guest'] > 0 ){
$be['huesped'] = Guest::find( $b->stay->guest );
}else{}
if( $stay[0]['attributes']['booking'] ){
$be['reserva'] = Booking::find( $b->stay->booking );
}
$be['stay'] = $st;
}
array_push( $retorno, $be);
$be = array();
}
}
return $retorno;
}
So, when I make a call to mysiteapp.local/beds, I should get back a composite array with the bed's data and, if there's a reservation, or if that bed's occupied at the moment, the stay info and guest's info.
But all I get is a compiling error message sayin':
error:{type: "ErrorException", message: "Undefined offset: 0",…}
file:"/home/pablo/htdocs/pbertran/angularh/api/vendor/laravel/framework/src/Illuminate/Support/Collection.php"
line:788
message:"Undefined offset: 0"
type:"ErrorException"
Have been googling around, but couldn't find any solution.
Any ideas?
Thanks in advance!
You make assumptions about that index being present, which may not always be the case. Your logic should be more thussly:
$st = isset($stay[0]) ? $stay[0] : false;
if ($st){
//now you can use it safely.
}
To add another outcome, I was doing a "double" GroupBy on the collection:
$price_change->grouped_lines = $price_change->lines->groupBy('PriceListID')->transform(function($item, $k) {
return $item->groupBy('StockID');
});
The above basically groups the collection by 2 keys so:
$price_change->grouped_lines[PriceListID][StockID]->
I received the "Undefined offset 0 - collection.php" error
To fix it I had to first do a isset() on the first key then the second:
if(isset($price_change->grouped_lines[1]) && isset($price_change->grouped_lines[1][23]))
I've noticed a strange behaviour of one of my functions. Just take a look. Using first function I'm displaying some custom fields data in the backend:
add_filter( 'manage_edit-shop_order_columns', 'MY_COLUMNS_FUNCTION', 10 );
function MY_COLUMNS_FUNCTION( $columns ) {
$new_columns = ( is_array( $columns ) ) ? $columns : array();
unset( $new_columns['order_actions'] );
//edit this for you column(s)
//all of your columns will be added before the actions column
$new_columns['product_name'] = 'Product';
$new_columns['authors_income'] = 'Author';
$new_columns['order_actions'] = $columns['order_actions'];
return $new_columns;
}
add_action( 'manage_shop_order_posts_custom_column', 'MY_COLUMNS_VALUES_FUNCTION', 2 );
function MY_COLUMNS_VALUES_FUNCTION( $column ) {
global $post;
$order = new WC_Order( $post->ID );
$items = $order->get_items();
//start editing, I was saving my fields for the orders as custom post meta
//if you did the same, follow this code
if ( $column == 'authors_income' ) {
foreach ( $items as $item ) {
echo $item['PLN-dla-autora'];
echo ' zł';
}
}
if ( $column == 'product_name' ) {
foreach ( $items as $item ) {
echo $item['name'];
}
}
}
add_filter( "manage_edit-shop_order_sortable_columns", 'MY_COLUMNS_SORT_FUNCTION' );
function MY_COLUMNS_SORT_FUNCTION( $columns ) {
$custom = array(
//start editing
'authors_income' => 'PLN-dla-autora',
'product_name' => 'name'
//stop editing
);
return wp_parse_args( $custom, $columns );
Everything works there like a charm. Then I have second function, which somehow does the same, yet it will print the data into the CSV file. Unfortunatelly, this code doesnt work (it display only column header, no data included). I dont see any major differences between those functions so why is that?
function wc_csv_export_modify_column_headers( $column_headers ) {
$new_headers = array(
'author_income' => 'PLN dla autora',
// add other column headers here in the format column_key => Column Name
);
return array_merge( $column_headers, $new_headers );
}
add_filter( 'wc_customer_order_csv_export_order_headers', 'wc_csv_export_modify_column_headers' );
// set the data for each for custom columns
function wc_csv_export_modify_row_data( $order_data, $order ) {
$custom_data = array(
'author_income' => get_post_meta( $order->id, 'PLN dla autora', true ),
// add other row data here in the format column_key => data
);
return array_merge( $order_data, $custom_data );
}
add_filter( 'wc_customer_order_csv_export_order_row', 'wc_csv_export_modify_row_data', 10, 2 );
I have a collection of products in Magento that I would like to be able to get the media gallery images out of. However I am finding that I have to iterate though my collection and load the product again to get the getMediaGalleryImages() function to work properly.
$products = Mage::getModel('catalog/product')
->getCollection()
->addAttributeToSelect('*')
->addAttributeToFilter('visibility', 4)
->addAttributeToFilter('status', 1);
foreach($products as $product) {
$_product = Mage::getModel('catalog/product')->load($product->getId());
$product->getMediaGalleryImages(); // This returns nothing
$_product->getMediaGalleryImages(); // Returns the Collection of Images
}
Obviously I could continue just reloading the product each time, but that would add quite a bit of overhead to the time required to run this code.
Is there a way to add in the media gallery images to the collection?
You can use
$product->load('media_gallery');
before getMediaGalleryImages (on the products you loaded in the collection).
One simple method for future reference:
Outside your foreach add
$mediaBackend = Mage::getModel('catalog/product_attribute_backend_media');
$mediaGalleryAttribute = Mage::getModel('eav/config')->getAttribute(Mage::getModel('catalog/product')->getResource()->getTypeId(), 'media_gallery');
$mediaBackend->setAttribute($mediaGalleryAttribute);
and then do the foreach:
foreach ($productCollection as $product) {
$mediaBackend->afterLoad($product);
}
You will have then the gallery loaded on product.
load product's cached image using collection by following codes
Mage::helper('catalog/image')->init($_product, 'small_image')->resize(135);
//or
Mage::helper('catalog/image')->init($_product, 'thumbnail')->resize(135);
//or
Mage::helper('catalog/image')->init($_product, 'image')->resize(135);
this is the collection which i used
$collection = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect('small_image') //or
->addAttributeToSelect('thumbnail') //or
->addAttributeToSelect('image');
You can create a helper class, and use it every time you need media gallery images to be loaded for a collection of products:
class My_Package_Helper_Media extends Mage_Core_Helper_Abstract {
public function addMediaGalleryAttributeToProductCollection( &$productCollection )
{
$storeId = Mage::app()->getStore()->getId();
$ids = array();
foreach ( $productCollection as $product ) {
$ids[] = $product->getEntityId();
}
$resource = Mage::getSingleton( 'core/resource' );
$conn = Mage::getSingleton( 'core/resource' )->getConnection( 'catalog_read' );
$select = $conn->select()
->from(
array( 'mg' => $resource->getTableName( 'catalog/product_attribute_media_gallery' ) ),
array(
'mg.entity_id', 'mg.attribute_id', 'mg.value_id', 'file' => 'mg.value',
'mgv.label', 'mgv.position', 'mgv.disabled',
'label_default' => 'mgdv.label',
'position_default' => 'mgdv.position',
'disabled_default' => 'mgdv.disabled'
)
)
->joinLeft(
array( 'mgv' => $resource->getTableName( 'catalog/product_attribute_media_gallery_value' ) ),
'(mg.value_id=mgv.value_id AND mgv.store_id=' . $storeId . ')',
array()
)
->joinLeft(
array( 'mgdv' => $resource->getTableName( 'catalog/product_attribute_media_gallery_value' ) ),
'(mg.value_id=mgdv.value_id AND mgdv.store_id=0)',
array()
)
->where( 'entity_id IN(?)', $ids );
$mediaGalleryByProductId = array();
$stmt = $conn->query( $select );
while ( $gallery = $stmt->fetch() ) {
$k = $gallery[ 'entity_id' ];
unset( $gallery[ 'entity_id' ] );
if ( !isset($mediaGalleryByProductId[$k]) ) {
$mediaGalleryByProductId[$k] = array();
}
$mediaGalleryByProductId[$k][] = $gallery;
}
unset( $stmt ); // finalize statement
// Updating collection ...
foreach ( $productCollection as &$product ) {
$productId = $product->getEntityId();
if ( isset( $mediaGalleryByProductId[ $productId ] ) ) {
$product->setData( 'media_gallery', array( 'images' => $mediaGalleryByProductId[ $productId ] ) );
}
}
unset( $mediaGalleryByProductId );
}
}
Sample usage:
$coll = Mage::getResourceModel('catalog/product_collection')
->setStoreId( Mage::app()->getStore()->getId() )
->addAttributeToFilter( 'sku', array( 'in' => array( 'AAA', 'BBB' ) ) );
Mage::helper('my_package/media')->addMediaGalleryAttributeToProductCollection( $coll );
Here the code you were looking for, sorry for the delay :)
It come from this discussion:
http://www.magentocommerce.com/boards/viewthread/17414/
I just added some extra check on the number of id a and pagination
function addMediaGalleryAttributeToCollection(Mage_Catalog_Model_Resource_Product_Collection $_productCollection)
{
if (Mage::getStoreConfig('color_selector_plus/colorselectorplusgeneral/showonlist', Mage::app()->getStore())) {
$_mediaGalleryAttributeId = Mage::getSingleton('eav/config')->getAttribute('catalog_product', 'media_gallery')->getAttributeId();
$_read = Mage::getSingleton('core/resource')->getConnection('catalog_read');
$pageCur = $_productCollection->getCurPage();
$pageSize = $_productCollection->getPageSize();
$offset = $pageSize * ($pageCur - 1);
$ids = $_productCollection->getAllIds($pageSize, $offset);
// added check on products number: if 0 ids the following query breaks
if (count($ids) > 0) {
$sql = '
SELECT
main.entity_id, `main`.`value_id`, `main`.`value` AS `file`, `value`.`disabled`,
/*`value`.`label`, `value`.`position`, */
/*`default_value`.`label` AS `label_default`, */
/*`default_value`.`position` AS `position_default`, */
`default_value`.`disabled` AS `disabled_default`
FROM `catalog_product_entity_media_gallery` AS `main`
LEFT JOIN `catalog_product_entity_media_gallery_value` AS `value`
ON main.value_id=value.value_id AND value.store_id=' . Mage::app()->getStore()->getId() . '
LEFT JOIN `catalog_product_entity_media_gallery_value` AS `default_value`
ON main.value_id=default_value.value_id AND default_value.store_id=0
WHERE (
main.attribute_id = ' . $_read->quote($_mediaGalleryAttributeId) . ')
AND (main.entity_id IN (' . $_read->quote($_productCollection->getAllIds()) . '))
/*ORDER BY IF(value.position IS NULL, default_value.position, value.position) ASC */
';
$_mediaGalleryData = $_read->fetchAll($sql);
$_mediaGalleryByProductId = array();
foreach ($_mediaGalleryData as $_galleryImage) {
$k = $_galleryImage['entity_id'];
unset($_galleryImage['entity_id']);
if (!isset($_mediaGalleryByProductId[$k])) {
$_mediaGalleryByProductId[$k] = array();
}
$_mediaGalleryByProductId[$k][] = $_galleryImage;
}
unset($_mediaGalleryData);
foreach ($_productCollection as &$_product) {
$_productId = $_product->getData('entity_id');
if (isset($_mediaGalleryByProductId[$_productId])) {
$_product->setData('media_gallery', array('images' => $_mediaGalleryByProductId[$_productId]));
}
}
unset($_mediaGalleryByProductId);
}
}
return $_productCollection;
}