Ok, so I'm very new to Drupal and I'm trying to create a custom module that generates a page that the user can navigate to. When the user clicks on the page, I'm trying to retrieve the titles of all the content pieces from the database and arrange them in a table using table_theme. Everything is working except the generating of the rows in the table. It's giving me this message at the top of the page:
"Warning: Invalid argument supplied for foreach() in theme_table() (line 2107 of /srv/bindings/4d0bbd3c7be847abb26f62e0dacbcc24/code/includes/theme.inc)."
This message appears once for each title that I retrieve from the database. Here is my content_titles.module file (my custom module file):
<?php
/**
* #file
* A module that creates a page to display all existing content titles
*/
/**
* Implements hook_help()
*
* Displays help and module information
*
* #param path
* Which path of the site we're using to display help
* #param arg
* Array that holds the current path as returned from arg() function
*/
function content_titles_help($path, $arg) {
switch ($path) {
case "admin/help#content_titles":
return '' . t("Displays all existing content titles
on an overview page") . '';
break;
}
}
/**
* Implements hook_menu()
*
* Enables the module to register a link to be placed in a menu
*/
function content_titles_menu() {
$items['test/content_titles'] = array(
'title' => 'Overview Test Page',
'page callback' => 'content_titles_simple',
'access callback' => TRUE,
'expanded' => TRUE,
);
return $items;
}
/**
* Constructs the Content Titles page
*/
function content_titles_simple() {
return array('#markup' => create_content_table());
}
/**
* This function will create the table to hold the content titles in
*/
function create_content_table() {
// Retrieve content titles from the database
$results = db_query('SELECT title FROM {node}');
$header = array('Content Titles');
$rows = array();
while ($row = $results->fetchAssoc()) {
$rows[] = $row['title'];
}
print_r($rows); // FOR DEBUGGING PURPOSES
$output = theme('table', array('header' => $header,
'rows' => $rows));
return $output;
}
The problem appears to be with my use of the theme function. I don't see how any of my arguments are invalid though. I'm passing the theme type of 'table' and two arrays that I've checked aren't empty (that's why I use print_r to print the array that I store my titles from the database in). I'm pretty stumped here. Any idea what the problem could be?
Thanks for the help everyone, I figured it out! I needed to push arrays onto the $rows array instead of the values. I changed this section of code:
$rows = array();
while ($row = $results->fetchAssoc()) {
$rows[] = $row['title'];
}
To:
$rows = array();
while ($row = $results->fetchAssoc()) {
$rows[] = array($row['title']);
}
You must use as below:
$header = array(
array('data' => t('Content Titles'), 'field' => 'title'),
);
$rows = array();
$query = db_select('node', 'n')->fields('n', array('title'));
$pager = $query->extend('PagerDefault')
->limit(10);
$results = $pager->execute();
foreach ($results as $row) {
$rows[] = array($row->title);
}
return theme('table', array(
'header' => $header,
'rows' => $rows)) . theme('pager');
Thanks
I am new to magento and I am not able to make out how one can remove the unwanted states from dropdown list in magento. I tried to edit my below function as per this link http://doejo.com/blog/magento-how-to-remove-certain-states-from-state-region-list-at-checkout-or-registration/ but it did not work. Below i sthe code for removing unwanted states but when I add to my class in local folder, not getting any results.
$excludeRegions = array('AE','AA');
foreach ($collection as $region) {
if (!$region->getRegionId()) {
continue;
}
***//Here is the code from the link given
//BOF Custom Logic Here***
$regionCode = $region->getCode();
$this->_select->from(array('region'=>$this->_regionTable),
array('region_id'=>'region_id', 'country_id'=>'country_id', 'code'=>'code', 'default_name'=>'default_name')
)->where('code NOT IN (?)', $exclude_regions);
_getRegions function edited as per above code and link respectively.
protected function _getRegions($storeId)
{
$countryIds = array();
$countryCollection = $this->getCountryCollection()->loadByStore($storeId);
foreach ($countryCollection as $country) {
$countryIds[] = $country->getCountryId();
}
/** #var $regionModel Mage_Directory_Model_Region */
$regionModel = $this->_factory->getModel('directory/region');
/** #var $collection Mage_Directory_Model_Resource_Region_Collection */
$collection = $regionModel->getResourceCollection()
->addCountryFilter($countryIds)
->load();
$regions = array(
'config' => array(
'show_all_regions' => $this->getShowNonRequiredState(),
'regions_required' => $this->getCountriesWithStatesRequired()
)
);
$excludeRegions = array('AE','AA');
foreach ($collection as $region) {
if (!$region->getRegionId()) {
continue;
}
***//Here is the code from the link given
//BOF Custom Logic Here***
$regionCode = $region->getCode();
$this->_select->from(array('region'=>$this->_regionTable),
array('region_id'=>'region_id', 'country_id'=>'country_id', 'code'=>'code', 'default_name'=>'default_name')
)->where('code NOT IN (?)', $exclude_regions);
//EOF Custom Logic Here
$regions[$region->getCountryId()][$region->getRegionId()] = array(
'code' => $region->getCode(),
'name' => $this->__($region->getName())
);
}
return $regions;
}
After making the above changes, I tried below steps as my code is in /app/code/core/Mage/Directory/Helper/Data.php
Create a module Vids_Directory in pool local like app/code/local/Vids/Directory
Create app/etc/modules/Vids_Directory.xml
Create app/code/local/Vids/Directory/etc/config.xml
create app/code/local/Vids/Helper/Data.php
Here is my custom.info
name = Custom
description = Custom module
core = 7.x
package = Own
and custom.module
<?php
/**
* #file
* An example custom module for selecting, updating and deleting query
*/
/**
* Implementation of hook_block_info()
*/
echo 'Today: \n';
echo date('m/d/Y');
function custom_block_info() {
$block['custom'] = array('info' => t('Custom block'))
return $block;
}
/**
* Implements hook_block_view.
*/
function custom_block_view($delta = '') {
global $user;
$block['content'] = t('Hello #user from IP #host',array(
'#user' => format_username($user),
'#host' => $user->hostname`enter code here`
));
$result = db_select('node','a')
->fields('a', array('title'))
->execute();
foreach($result as $node) {
$items[] = array(
'data' => t($node->title)
);
}
$block['content'] .= theme('item_list', array(
'items' => $items
));
return $block;
}
But this custom module is not displaying data in the sidebar where had i put the block. i have place the echo statement above the code it's not even displaying that echo statement in block can any one tell me how to resolve this????
P.S. I have installed drupal i ve changed nothing in database!
Check if your module is active in the modules list (admin/modules) if so try to put your echo statements in a hook_init like this:
function custom_init(){
echo 'Today: \n';
echo date('m/d/Y');
}
then clear all drupal cache Configuration > Performance > Clear alla caches (admin/config/development/performance)
I have lot of products with custom options, now I have requirement to update only custom options through csv file. so how we can do this programatically?
i found one solution for updating custom options programatically here is the solution
$product = Mage::getModel('catalog/product')->load($product_id);
$values = array();
foreach ($product->getOptions() as $o) {
$p = $o->getValues();
}
}
foreach($p as $v)
{
$values[$v->getId()]['option_type_id']= $v->getId();
$values[$v->getId()]['title']= 'test';
$values[$v->getId()]['price']= 23;
$values[$v->getId()]['price_type']= 'fixed';
$values[$v->getId()]['sku']= $value1;
}
$v->setValues($values);
$v->saveValues();
$product->save();
hope this help someone
this only update custom options value
I think this is also useful...
If you are customize the products .
<?php
$magePath = 'app/Mage.php';
require_once $magePath;
Varien_Profiler::enable();
Mage::setIsDeveloperMode(true);
ini_set('display_errors', 1);
umask(0);
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
$product_ids = array(1,2,167);
$productmodel = Mage::getModel('catalog/product');
foreach ($product_ids as $product_id) {
/**i use this two arrays for collecte value because i uses inside setData of
current option*/
$cos=array();
$co=array();
$product = $productmodel->load($product_id);
$options = $product->getProductOptionsCollection();
if (isset($options)) {
foreach ($options as $o) {
$title = $o->getTitle();
/**
this block is for changing information of specific option from collection options inside
current product
the save method for this option in end of code
*/
if ($title == "Line 1/Front") {
$o->setProduct($product);
$o->setTitle("Line 1/Ftont");
$o->setType("drop_down");
$o->setIsRequire(1);
$o->setSortOrder(0);
}
/**
this block for update or add information of specific value inside current option
*/
$optionType = $o->getType();
//test type
if ($optionType == "drop_down") {
//getting collection of value related to current option
$values = $o->getValuesCollection();
$found = false;
foreach ($values as $k => $v) {
//test existing of value for update
if (1 == preg_match("/said$/i", $v->getTitle())) {
//update and save
$v->setTitle("morad")
->setSku("kk")
->setPriceType("fixed")
->setSortOrder(0)
->setPrice(floatval(13.0000));
$v->setOption($o)->save();
/**
this ligne is important i collecte all value required for normalize save function
related to current option
*/
$cos[]=$v->toArray($co);
}
}
/**
create new value object you can use $option->getValueInstance() for working with
getSingleton
*/
$value = Mage::getModel('catalog/product_option_value');
$value->setOption($o)
->setTitle('valueiwant')
->setSku("nn")
->setPriceType("fixed")
->setSortOrder(1)
->setPrice(12)
/**
this ligne is important (relation forigien key) for related this new value
to specific option
*/
->setOptionId($o->getId());
$value->save();
/**
this ligne is important i collecte all value required for normalize save function
related to current option
*/
$cos[]=$value->toArray($co);
}
$o->setData("values",$cos)->save();
//var_dump($cos);
}
}
}
Do you create a module to do that ? If you do, you must use the cron system of Magento and call a method of a custom model :
<config>
<!--...-->
<crontab>
<jobs>
<company_test>
<schedule>
<cron_expr>0,15,30,45 * * * *</cron_expr>
</schedule>
<run>
<model>test/testmodel::testMethod</model>
</run>
</company_module>
</jobs>
</crontab>
</config>
When this is done, you can update the option of a specific product by using the model Mage_Catalog_Model_Product_Option. I don't know how the CSV is made, but the algorithm can be something like that :
// foreach option
/** #var $opt Mage_Catalog_Model_Product_Option */
$opt = Mage::getModel('catalog/product_option');
$opt->setProduct($product);
$optionArray = array(
'is_delete' => 0,
'title' => 'Blabla',
'previous_group' => '',
'previous_type' => '',
'type' => 'field', //can be radio, drop_down, file, area...
'is_require' => 0,
'sort_order' => 42,
'values' => array()
);
$opt->addOption($optionArray);
$opt->saveOptions();
// end foreach
Also check this link : http://subesh.com.np/2009/12/adding-custom-options-product-magento/
I'm trying to use FlexiGrid plugin with CodeIgniter, but when the page displays the grid shows, but there are no records, and there is a little message saying that you should wait while it's processing, which never goes away...
I'm using one of my own databases, so I modified parts of the code to use fields in my database (id, username, email).
Flexigrid controller:
<?php
class Flexigrid extends CI_Controller
{
/* function Flexigrid ()
{
parent::Controller();
$this->load->helper('flexigrid');
}
*/
function __construct()
{
parent::__construct();
$this->load->helper('flexigrid');
}
function index()
{
//ver lib
/*
* 0 - display name
* 1 - width
* 2 - sortable
* 3 - align
* 4 - searchable (2 -> yes and default, 1 -> yes, 0 -> no.)
*/
$colModel['id'] = array('id', 40, TRUE, 'center', 2);
$colModel['username'] = array('username', 40, TRUE, 'center', 0);
$colModel['email'] = array('email', 180, TRUE, 'left', 1);
/*
* Aditional Parameters
*/
$gridParams = array(
'width' => 'auto',
'height' => 400,
'rp' => 15,
'rpOptions' => '[10,15,20,25,40]',
'pagestat' => 'Displaying: {from} to {to} of {total} items.',
'blockOpacity' => 0.5,
'title' => 'Hello',
'showTableToggleBtn' => true
);
/*
* 0 - display name
* 1 - bclass
* 2 - onpress
*/
$buttons[] = array('Delete', 'delete', 'test');
$buttons[] = array('separator');
$buttons[] = array('Select All', 'add', 'test');
$buttons[] = array('DeSelect All', 'delete', 'test');
$buttons[] = array('separator');
//Build js
//View helpers/flexigrid_helper.php for more information about the params on this function
$grid_js = build_grid_js('flex1', site_url("/ajax"), $colModel, 'id', 'asc', $gridParams, $buttons);
$data['js_grid'] = $grid_js;
$data['version'] = "0.36";
$data['download_file'] = "Flexigrid_CI_v0.36.rar";
$this->load->view('flexigrid', $data);
}
function example()
{
$data['version'] = "0.36";
$data['download_file'] = "Flexigrid_CI_v0.36.rar";
$this->load->view('example', $data);
}
}
?>
Flexigrid view (only changes in head to correct paths to css and js):
<head>
<title>Flexigrid Implemented in CodeIgniter</title>
<link href="<?=$this->config->item('base_url');?>assets/flexigrid/css/style.css" rel="stylesheet" type="text/css"/>
<link href="<?=$this->config->item('base_url');?>assets/flexigrid/css/flexigrid.css" rel="stylesheet"
type="text/css"/>
<script type="text/javascript" src="<?=base_url()?>assets/scripts/jquery-1.5.1.min.js"></script>
<script type="text/javascript"
src="<?=$this->config->item('base_url');?>assets/flexigrid/js/jquery.pack.js"></script>
<script type="text/javascript"
src="<?=$this->config->item('base_url');?>assets/flexigrid/js/flexigrid.pack.js"></script>
</head>
ajax_model:
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* Eye View Design CMS module Ajax Model
*
* PHP version 5
*
* #category CodeIgniter
* #package EVD CMS
* #author Frederico Carvalho
* #copyright 2008 Mentes 100Limites
* #version 0.1
*/
class Ajax_model extends CI_Model
{
/**
* Instanciar o CI
*/
/* public function Ajax_model()
{
parent::Model();
$this->CI =& get_instance();
}*/
function __construct()
{
parent::__construct();
$this->CI =& get_instance();
}
public function get_countries()
{
//Select table name
$table_name = "users";
//Build contents query
$this->db->select('id,username,email')->from($table_name);
$this->CI->flexigrid->build_query();
//Get contents
$return['records'] = $this->db->get();
//Build count query
$this->db->select('count(id) as record_count')->from($table_name);
$this->CI->flexigrid->build_query(FALSE);
$record_count = $this->db->get();
$row = $record_count->row();
//Get Record Count
$return['record_count'] = $row->record_count;
//Return all
return $return;
}
/**
* Remove country
* #param int country id
* #return boolean
*/
public function delete_country($country_id)
{
$delete_country = $this->db->query('DELETE FROM country WHERE id=' . $country_id);
return TRUE;
}
}
?>
Ajax controller (had to use the non-JSon extension code, so the other part is commented out, according to the instructions on the FlexiGrid web site. Also, I was a bit puzzled when modifying the $recorde_item array, because the example had id twice at the beginning. I thought this must be a mistake, but tried adding a second id row too, didn't help either):
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
class Ajax extends CI_Controller
{
/* function Ajax ()
{
parent::Controller();
$this->load->model('ajax_model');
$this->load->library('flexigrid');
}*/
function __construct()
{
parent::__construct();
$this->load->model('ajax_model');
$this->load->library('flexigrid');
}
function index()
{
//List of all fields that can be sortable. This is Optional.
//This prevents that a user sorts by a column that we dont want him to access, or that doesnt exist, preventing errors.
$valid_fields = array('id', 'username', 'email');
$this->flexigrid->validate_post('id', 'asc', $valid_fields);
//Get "countries"
$records = $this->ajax_model->get_countries();
//Init json build
if ($this->flexigrid->init_json_build($records['record_count'])) {
//Add records
foreach ($records['records']->result() as $row)
{
$record_item = array($row->id,
$row->username,
$row->email
);
$this->flexigrid->json_add_item($record_item);
}
//Last item added, close up.
$this->flexigrid->json_add_item();
}
//Print please
$this->output->set_header($this->config->item('json_header'));
$this->output->set_output($this->flexigrid->json_build);
/*$this->output->set_header($this->config->item('json_header'));*/
/*
* Json build WITH json_encode. If you do not have this function please read
* http://flexigrid.eyeviewdesign.com/index.php/flexigrid/example#s3 to know how to use the alternative
*/
/* foreach ($records['records']->result() as $row)
{
$record_items[] = array($row->id,
$row->id,
$row->iso,
$row->name,
'<span style=\'color:#ff4400\'>' . addslashes($row->printable_name) . '</span>',
$row->iso3,
$row->numcode,
'<a href=\'#\'><img border=\'0\' src=\'' . $this->config->item('base_url') . 'public/images/close.png\'></a> '
);
}
//Print please
$this->output->set_output($this->flexigrid->json_build($records['record_count'], $record_items));*/
}
//Delete Country
function deletec()
{
$countries_ids_post_array = split(",", $this->input->post('items'));
foreach ($countries_ids_post_array as $index => $country_id)
if (is_numeric($country_id) && $country_id > 1)
$this->ajax_model->delete_country($country_id);
$error = "Selected countries (id's: " . $this->input->post('items') . ") deleted with success";
$this->output->set_header($this->config->item('ajax_header'));
$this->output->set_output($error);
}
}
?>
Well, that should be it. I also had to change the "extends Controller" etc to "extends CI_Controller" since the code in the example seems to be for an older version of CodeIgniter.
But again, it doesn't work. I only get an empty grid. The database table does definitely have the fields I mentioned. I can't find any typos myself at least. It's also my default database in CodeIgniter, and I have no trouble connecting to it in other cases. And it is autoloaded, so I'm guessing that should work automatically, right? I shouldn't have to connect to the database manually here, since it uses the $db variable...
Any ideas then why it isn't working?
I Implemented Flexigrid with Codeigniter 2.1.0. You can download the code from my blog. Flexigrid in Codeigniter 2.1.0 and you can check the tutorial at Flexigrid Tutorial
Not sure if you still need this help or not, and i'm not sure i'm the best to teach as i'm still new to PHP and don't know the most "secure" practices, however, the following is what I was able to do with flexgrid and may help future users, or spark a more "secure" idea from a more advanced user. Without further adieu, my solution:
In the javasript grabbing the and using the json is EASY, check it:
keep in mind i tried to keep this very generic & removed all possible personal values ... it think
var flexset = {
url: 'https://www.yourSite.com/index.php/yourController/yourDBFunc',
dataType: 'json',
colModel : [
{display: 'A Column', name: 'a_col', width: 80, sortable: true, align: 'center'}, // where name=the name of the column in the database
{display: 'Another Column', name: 'another_col', width: 110, sortable: false, align: 'center'}
],
buttons : [ {name: "aButton", onpress: someFunction} ],
searchitems : [
{display: 'A Column (some more info if you want)', name: 'a_col', isdefault: true}, // where name=the name of the column in the database
{display: 'Quantity', name: 'charge'}
],
sortname: "a_col", // the name of the column in the database
sortorder: "desc", // desc or asc
usepager: true,
title: 'Some grid title',
useRp: true,
rp: 20,
showTableToggleBtn: true,
resizable: true,
width: "100%",
height: "400px",
singleSelect: true,
onSuccess: function() {
// do some work each time grid is loaded/refreshed, for instance, manipulate certain cells to have specific bgcolor based on content
console.log('onSuccess:\t\t', this, gridData);
console.log('Your inner table:\t', gridData.bDiv);
// you can get specific cells by searching from an attribute called "abbr" on each cell,
// it will = the same "name" you used when setting up the column that cell belongs too
console.log($(gridData.bDiv).find("td[abbr=transactionType]"));
}
}
$("#yourGrid").flexigrid(flexset);
In php, it gets a little harder as i use 2 functions, one public and one private. The private one actually makes the DB query while the public one is accessed by flexigrid to get the resulting data as json_encoded.
The Public Function
public function getJSONData() {
// to ensure its being pulled from a logged user,
// i always set at least one "where" var by hand,
// in this case, i am going to set the where to
// look for all rows containing this user's id,
// so i quickly grab the session var for the current id
$userID = $this->session->userdata('userID');
// should easily be greater than false in this case unless maybe it's id is 0?
// in any case, this is not the exact var i check, but same exact concept and my stuff works
if ($userID) {
// Return JSON data
$data = array();
// first i check post for a page number and go ahead and set the page
// this will be usful later in setting up the page query
$data['page'] = floatval(($this->input->post('page', TRUE))) ? floatval($this->input->post('page', TRUE)) : 1;
$value = array(
'select' => '*',
'where' => array( 'ownerID' => $userID ), // here you see my preset where clause, not absolutly necesary but useful, with some slight manipulation, you could easily redo this how you like
'orderBy' => array( 'a_col' => 'desc' ) // here i set a default orderby in case it's not provided by the post
);
// Get all other POSSIBLE posted data and save it to $value for passing to private func
if ($this->input->post('qtype', TRUE) && $this->input->post('query', TRUE)) $value['where'][$this->input->post('qtype', TRUE)] = $this->input->post('query', TRUE);
if ($this->input->post('sortname', TRUE) && $this->input->post('sortorder', TRUE)) $value['orderBy'] = array( $this->input->post('sortname', TRUE) => $this->input->post('sortorder', TRUE) );
if ($this->input->post('rp', TRUE)) $value['limit'] = array( $this->input->post('rp', TRUE) => (($data['page'] - 1) * floatval($this->input->post('rp', TRUE))) );
// call private function to get the desired data from db
$results = $this->getDBData($value);
// set return data's total count
$data['total'] = $results["total"]["absolute"];
// now we clearly define our "ROWS" for the return data to display in our final grid output
$data['rows'] = array();
foreach($results["rows"] as $k => $v) {
$data['rows'][] = array(
"id" => $v["id"],
"cell" => array( // keep in mind the order of these result here need match the order of the cols you set in the flexset options
$v["a_col"],
$v["another_col"]
)
);
};
// finally, json encode the data to be returned
$data = json_encode($data);
echo($data); // and echo the data to our ajax caller
};
}
The Private Funtion should be pretty self-explanitory
private function getDBData($val) {
$data = array( 'options'=>array(), 'rows'=>array(), 'total'=>array( 'absolute'=>0, 'offset'=>0 ) );
if (array_key_exists("from", $val)) {
$select = (array_key_exists("select", $val)) ? $val["select"] : "*";
$from = $val["from"]; // cannot be changed
$where = array(); // (col => value)
$orderBy = array(); // (name => direction)
$limit = array(); // "totalLimit" or (start => offset)
$limitType = "array";
$total = 0;
if (array_key_exists("where", $val)) if (gettype($val["where"]) === "array") $where = $val["where"];
if (array_key_exists("orderBy", $val)) if (gettype($val["orderBy"]) === "array") $orderBy = $val["orderBy"];
if (array_key_exists("limit", $val)) {
if (gettype($val["limit"]) === "array" || gettype($val["limit"]) === "integer" || gettype($val["limit"]) === "string") {
$limit = $val["limit"];
$limitType = gettype($val["limit"]);
};
};
$options = array( 'select'=>$select, 'from'=>$from, 'where'=>$where, 'orderBy'=>$orderBy, 'limit'=>$limit, 'limitType'=>$limitType );
$this->db->select($select);
$this->db->from($from);
if (count($where) > 0) $this->db->where($where);
if (count($orderBy) > 0) {
foreach ($orderBy as $k => $v) {
$this->db->order_by($k, $v);
};
};
if (gettype($limit) === "array") {
foreach ($limit as $k => $v) {
$this->db->limit($k, $v);
};
}
elseif (gettype($limit) === "integer" || gettype($limit) === "string") {
$this->db->limit($limit);
};
$records = $this->db->get();
$results = $records->result_array();
if (count($where) > 0) {
$total = $this->db->get_where($from, $where)->num_rows;
}
else {
$total = $this->db->get($from)->num_rows;
};
$data["options"] = $options;
$data["rows"] = $results;
$data["total"]["absolute"] = $total;
$data["total"]["offset"] = $records->num_rows;
};
return($data);
}