I'm fairly new to Drupal, and I need your help on this issue:
I have built a module on Drupal 7 which makes a database query to extract the name and the email of all users. The code is this:
<?php
/**
*
*/
function myexample_block_info() {
$blocks['myblock'] = array(
'info' => t('My Custom Modue'),
);
return $blocks;
}
function myexample_block_view($delta = '') {
$block = array();
$results = db_select('users','a')
->fields('a', array('name', 'mail'))
->execute();
$header = array(t('NAME'), t('MAIL'));
$rows = array();
foreach ($results as $node) {
$rows[] = array(
$node->name,
$node->mail,
);
}
$block['content'] = theme('table', array('header' => $header, 'rows' => $rows));
return $block;
}
I put the block into "Side-bar first"-Bartik theme. The code works and it retrieves what I want. But the problem with the display. I'm getting the results repeated 3 times:
Results
Why am I getting the results repeated three times. I cant seem to find anything wrong with the code. Could anyone help me please? Thanks in advance.
What are you trying to achieve ? If you are just trying to extract data from the DB this is not the way to go. You should extract data via mysql client directly.
Related
I am a newbie in Drupal. Please accept my ignorance. I have a page with a custom hook to override the view and display list of posts with default sorting or no sorting. I want to sort the array based on the node create date. But not sure where to plug the sorting argument. Can anyone please help? I have this code block in my_view.module file.
function _sites_by_park_page_get_node_references($fieldName, $property, $park_id) {
$results = array();
$parks = _sites_by_park_page_get_sites($park_id);
foreach ($parks['features'] as $feature) {
foreach($feature['properties'][$property] as $key => $value) {
if (!array_key_exists($key, $results)) {
$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node');
$query->fieldCondition($fieldName, 'value', $value);
$result = $query->execute();
$node = node_load(array_shift(array_keys($result['node'])));
$results[$key] = $node->title;
}
}
}
return $results;
}
/**
* Return GeoJSON formatted park data
*/
function _sites_by_park_page_get_sites($park_id) {
// Uses a lot of memory thanks to views and GD image resizing, could use some garbage collection opimisation
ini_set('memory_limit', '512M');
$data_view = views_get_view('sites_by_park_data');
$data_view->set_arguments(array($park_id));
$data_view->execute('page');
// Build our own, more lightweight geojson structure for faster page loads (Leaflet module generated 2MB of data vs this custom module's 40kb-ish for 140 parks)
$results = array(
'type' => 'FeatureCollection',
'features' => array(),
);
foreach($data_view->result as $result) {
// Initialise some arrays that may be merged between result sets (for instance when multiple activities contribute to a site's overall data)
if (!isset($results['features'][$result->nid])) {
$results['features'][$result->nid] = array(
'type' => 'Feature',
'properties' => array()
);
}
}
$results['features'] = array_values($results['features']);
return $results;
}
As per MilanG's suggestion I have done this through admin section. Change the sorting order and it works fine now.
Looking to limit the returned fields of a WP Query to help with speeding up the response from the server and reducing the amount of data retrieved. For the query I'm using, it only needs up to 3 fields of data, the rest is brought in through ACF get_field_object in the loop. Other functions I'm using such as get_posts or get_terms have field options but are limited to a small number of things, such as 'slug' only or 'id => slug'.
I'm used to developing in CakePHP, which has the option to specify each and every field to return, but the project calls for wordpress for other functionality and so I'm quite limited.
TL;DR need to speed up getting posts from Wordpress
I used fields parameter in the query and run get posts on this query.
For example: In my case, I just needed to get the Post ids for multiple categories, so I created a query like this:
$the_query = new WP_Query( array(
'ignore_sticky_posts' => 1,
'posts_per_page' => -1,
'cat' => '2,6,7' ,
'fields' => 'ids',
'post_type' => 'post',
'post_status' => 'publish',
)
);
Run the get_posts on this query:
$posts = $the_query->get_posts();
$posts will get only the IDs of particular categories posts.
Or it can also be done with the standard and popular way and i.e., by running the loop of have_posts:
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) {
$the_query->the_post();
$post_id_array[] = get_the_ID();
}
}
These are the two ways to help with speeding up the response from the server and reducing the amount of data retrieved
WP_Query will return objects...so it's pretty fast. However, if you really want to limit what's returned, you can do so with the Return Fields Parameter of WP_Query.
I don't know how much it will help but below is how I'm getting a flattened array from a CPT. It's not the fastest but it could be worse. I'm using ACF to get a Custom Field but you could just get back the slug or you could get back multiple fields instead:
// Query Jobs Args
$query_args = array(
'post_type' => 'job',
'posts_per_page' => -1,
'fields' => 'ids'
);
// Get Jobs Query
$query = new WP_Query($query_args);
// Loop Persistent Vars
$job_ids = array();
// Loop Over Jobs
foreach($query->posts as $post_id) {
$job_ids[] = get_field('job_id', $post_id);
}
// Do stuff with flattened array of job ids
This is what I've done to limit the fields from WP_Query, especially, when I want to json_encode them. The $return variable contains my array of posts with only the fields listed in the $fields array.
$query = new WP_Query( array( 'post_type' => 'my_custom_type' ) );
$return = array();
$fields = array('post_title', 'ID'); //list of fields I want in $return
$posts = $query->get_posts();
foreach($posts as $post) {
$newPost = array();
foreach($fields as $field) {
$newPost[$field] = $post->$field;
}
$return[] = $newPost;
}
Interestingly enough, you can do this with the WP Rest API using the _fields parameter
https://yoursite.com/wp-json/wp/v2/posts?_fields=author,id,excerpt,title,link
More info on the API here: https://developer.wordpress.org/rest-api/
I'm working on an edit method. After saving data, an email is sent out with the changes made during the edit. Everything works except for one infuriating but crucial bug. Here it is distilled down very simply:
$data = $this->SupportTicket->readForView($st_id);
$this->SupportTicket->id = $st_id;
if ($this->SupportTicket->save($this->request->data)) {
//call custom model method to pull view data
$data = $this->SupportTicket->readForView($st_id);
//do something with this data
}
The issue is that $data comes out with the pre-save data. So what I then try to do with the new data doesn't work.
I can't just use $this->request->data because it doesn't have the full data that I want in it.
The save does however work. If I refresh the view method for the same record, it shows as updated. So it's saving, but when I do the find after saving it is giving me old data.
Any ideas?
Update: it doesn't happen with findById($st_id) so it must be something to do with my custom method. Code:
public function readForView($id)
{
$data = $this->find('first', array(
'conditions' => array(
'SupportTicket.id' => $id
),
'contain' => array(
'User',
'Owner'
)
));
if (empty($data)) {
throw new notFoundException('Ticket not found');
}
$data['SupportTicket']['type_long'] = $this->getLongType($data['SupportTicket']['type']);
$data['SupportTicket']['status_long'] = $this->getLongStatus($data['SupportTicket']['status']);
$data['SupportTicket']['name'] = 'Support Ticket #' . $data['SupportTicket']['id'] . ' - ' . $data['SupportTicket']['title'];
return $data;
}
Copying the code from this method into the Controller gives the same result.
I've found this helpful: https://edivad.wordpress.com/2008/04/15/cakephp-disable-model-queries-caching/
By model:
class Project extends AppModel {
var $cacheQueries = false;
...
By function:
function someFunction {
$this->Model->cacheQueries = false;
...
try using last Insert ID
$id=$this->getLastInsertID();
public function readForView($id)
I have a table with data from the database, I would like it to have a Pager, I have all the code from an example (of buildamodule.com) among other sites, and my table get's rendered, but it doesn't generate a pager, although I have more rows then the limit:
the function:
function get_loyaltycodes(){
$headers = array(
array(
'data' => t('Code')
),
array(
'data' => t('Info')
),
array(
'data' => t('Points')
),
array(
'data' => t('Consumed by')
),
);
$limit = variable_get('codes_per_page',5);
$query = db_select('loyalty_codes','lc');
$query -> fields('lc',array('code','info','points','uid'))
-> orderBy('lc.info','ASC')
-> extend('PagerDefault')
-> limit($limit);
//to see all codes for a certain amount of points, just append the number of points to the URL
$arg = arg(2);
if($arg != '' && is_numeric($arg))
{
$query->condition('points', $arg);
}
// Fetch the result set.
$result = $query->execute();
$rows = array();
// Loop through each item and add to the $rows array.
foreach ($result as $row) {
$rows[] = array(
$row->code,
$row->info,
$row->points,
$row->uid,
);
}
// Format output.
$output = theme('table', array('header' => $headers, 'rows' => $rows)) . theme('pager');
return $output;
the $limit variable is set to 5 in the settings form, and it is 5 in the database too.
Anybody who has any idea in why the pager is not showing? perhaps something in the formatting off the output?
Help is very much appreciated!
apparently I can't log in right know because I'm behind a firewall, anyway I seem to have fixed it, stupid mistake though:
the ‘->extend(‘PagerDefault’) extension in the query had to be the first function in the daisy chain. If not there is no error but the function seems to not be called.
$query = db_select('loyalty_codes','lc')
->extend('PagerDefault')
-> fields('lc',array('code','info','points','uid'))
-> orderBy('lc.info','ASC')
-> limit(5);//$limit);
I currently have index, view, add and edit from my tickets/views and am planning to add another view called current. I want to display only the "Resolved" tickets on that view but have no idea how to do it. I've been trying to figure this out for the past couple of days with no luck. Where should I put the "find" code and what should I include on my tickets/current view code? Here's what I have tried so far:
/controllers/tickets_controller
function current() {
$current = $this->set('tickets', $this->Ticket->find('all', array(
'conditions' => array('Ticket.status' => 'Resolved'),
'order' => array('Ticket.created' => 'desc')
)));
$this->set('tickets', $this->paginate());
}
/views/tickets/current.ctp
<?php
$i = 0;
foreach ($tickets as $ticket):
$class = null;
if ($i++ % 2 == 0) {
$class = ' class="altrow"';
}
?>
This code displays the same as /views/tickets/index.ctp (with all the records from the table).
Thanks,
Lyman
You were almost there. $this->set('foo') in Cake is one way you can pass variables to the view.
What the code below does is set a variable called current the return value of the find method which has a custom condition, which can be accessed from the view. (It's an array in this case; but you can set anything)
You don't need the paginate() here unless you plan to use pagination in this view.
So something like this should do the trick ($curr is a bad variable name but I wasn't feeling inventive. (resolved_tickets would make more sense (why current?))
//controllers/tickets_controller
function current() {
$this->set('current', $this->Ticket->find('all',
array('conditions' => array('Ticket.status' => 'Resolved'),
'order' => array('Ticket.created' => 'desc')
)));
}
/views/tickets/current.ctp
<?php
$i = 0;
// adjust the variable in the foreach
foreach ($current as $curr):
$class = null;
if ($i++ % 2 == 0) {
$class = ' class="altrow"';
}
echo $curr['Ticket']['id']; // example
?>