I'm a bit new to PHP so this has got me a bit confused. I assume it's not an error within the code but rather the code logic.
There are two template files at use here:
Search - Which displays the search page.
search_item - Which is formatting for the returned results of the search.
I have dumped the execution of the query and it is returning true so this leads me to believe the query is successful and has received data from the form.
Below is the function for the Search.php page. (Displayed in the url as index.php?action=search from the controller)
public function handleAction() {
global $user, $config;
$database = Database::getDatabase();
$driver = $database->getDriver();
$search = $_POST['keywords'];
$stmt = $driver->prepare('SELECT * FROM clansoc_clans WHERE clan_name LIKE :keywords');
$stmt->bindValue(':keywords', '%' . $search . '%');
$stmt->execute();
$results = array();
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$results[] = array(
'id' => $row['id'],
'clan_name' => htmlspecialchars($row['clan_name'], ENT_QUOTES),
'short_desc' => htmlspecialchars($row['clan_short_desc'], ENT_QUOTES),
'clan_avatar' => $row['clan_avatar']
);
}
$results_list_registry = new ViewRegistry();
$results_list = new View('Results List', $results_list_registry, false);
$results_list_contents = "";
//$i = $offset;
foreach($results as $result) {
$results_list_result_registry = new ViewRegistry();
$this->view->getViewRegistry()->setVariable('id', $result['id']);
$this->view->getViewRegistry()->setVariable('name', $result['clan_name']);
$this->view->getViewRegistry()->setVariable('desc', $result['short_desc']);
$this->view->getViewRegistry()->setVariable('avatar', $result['clan_avatar']);
$results_list_result = new View('Results List Result', $results_list_result_registry);
$results_list_result->setView('search_item');
$results_list_contents .= $results_list_result->export(false);
}
$results_list->setView($results_list_contents);
$this->view->getViewRegistry()->setVariable('results', $results_list);
}
My question in simpler terms:
Why is the script not displaying the results of the query?
Related
Hi first of all I should tell you that English is not my first language so excuse any misunderstandings. What I'm trying here is to access to the "donors" table data using the foreign key in the "packets" table and I need to get that data in the controller to use. I refer PacketID in my view and in the staff controller I need to get the specific DonorMobile and DonorName to send an SMS to that donor. I have tried creating multiple model functions but didn't work. Can it be done by that way or is there any other way? TIA!
Screenshots of donors and packets tables
donors table and
packets table
Staff controller - I know you can't access data like $donorData->DonorID in the controller
public function markAsUsed($packet)
{
$this->load->Model('Donor_Model');
$donorData = $this->Donor_Model->getDonors($packet);
$this->load->Model('Donor_Model');
$data = $this->Donor_Model->markAsUsed($donorData->DonorID);
$sid = 'twilio sid';
$token = 'twilio token';
$donorMobile = '+94' . $donorData->DonorMobile;
$twilioNumber = 'twilio number';
$client = new Twilio\Rest\Client($sid, $token);
$message = $client->messages->create(
$donorMobile, array(
'from' => $twilioNumber,
'body' => 'Thank you ' . $donorData->DonorName . ' for your blood donation. Your donation has just saved a life.'
)
);
if ($message->sid) {
$this->load->Model('Donor_Model');
$this->Donor_Model->changeStatus($data->isAvailable);
redirect('staff/viewpackets');
}
}
Model
function getDonors($packet) {
$data = $this->db->get_where('packets', array('PacketID' => $packet));
return $data->row();
}
function markAsUsed($donor)
{
$data = $this->db->get_where('donors', array('DonorID' => $donor));
return $data->row();
}
function changeStatus($packet)
{
$data = array(
'isAvailable' => False,
);
return $this->db->update('packets', $data, ['PacketID' => $packet]);
}
What you did in the answer is not advisable, using loops to fetch from tables will slow the system by large when you have large datasets. What was expected is to use JOIN queries to join the donors and packets tables as shown below:
$this->db->select('donors_table.DonorName,donors_table.DonorMobile,packets_table.*')->from('packets_table');
$this->db->join('donors_table','donors_table.DonorID=packets_table.DonorID');
$query = $this->db->get();
$result = $this->db->result();
Then you can iterate through each donor as below:
foreach($result as $row){
$donarName = $row->DonorName;
$donorMobile = $row->DonorMobile;
}
NB: It is always advisable to perform any fetch, insert, delete or update operations from the model, that is why Codeigniter is an MVC. Stop fetching data directly from database within Controllers.
Found the answer! You can do this only using the controller.
$packetData = $this->db->get_where('packets', array('PacketID' => $packet));
foreach ($packetData->result() as $row) {
$donorID = $row->DonorID;
$packetDonatedDate = $row->DonatedDate;
}
$donorData = $this->db->get_where('donors', array('DonorID' => $donorID));
foreach ($donorData->result() as $row) {
$donarName = $row->DonorName;
$donorMobile = $row->DonorMobile;
}
I've a system that I need to get a minor tweak made to and hope someone can advise.I've a custom field from a modal called 'cancle_order_reason' that needs to be added to a transactions table when a internal refund is made. Currently the table says just 'internal', but I want it to give the info from the 'cancle_order_reason' field for greater info.
From what I can see the relevant controllers are
packages/catalyst/controllers/dashboard/catalyst/orders.php which is where the modal is.
public function add_refund_order(){
$valt = Loader::helper('validation/token');
if (!$valt->validate('add_refund_order', $this->post('token'))) {
throw new Exception($valt->getErrorMessage());
}
Loader::model('proforms_item','proforms');
$pfo = ProFormsItem::getByID($this->post('orderID'));
$orderID = $this->request('orderID');
$question_set = $pfo->asID;
$setAttribs = AttributeSet::getByID($question_set)->getAttributeKeys();
foreach ($setAttribs as $ak) {
if($ak->getAttributeType()->getAttributeTypeHandle() == 'price_total'){
$value = $pfo->getAttributeValueObject($ak);
$db = Loader::db();
$avID = $value->getAttributeValueID();
$amount = money_format('%(#4n',$this->post('credit_amount'));
$ak->getController()->savePayment($avID,$amount,2);
}
}
$desc = trim($amount . ' ' . $this->request('cancle_order_reason'));
$date = date('Y-m-d');
$u = new User();
$data = array(
'ProformsItemID'=> $this->request('orderID'),
'action'=> 'Refund (Internal)',
'amount'=> $amount,
'description'=> $desc,
'uID'=> $u->uID,
'date' => $date
);
Loader::model('order_history', 'catalyst');
$oh = new OrderHistory();
$oh->addOrderHistoryItem($data);
$this->redirect('/dashboard/catalyst/orders/refund_added_order/?view_order='.$orderID);
}
and then the model controller:
models/attribute/types/price_total/controller.php
public function savePayment($avID=null, $amount, $credit=null, $transID='internal', $type='internal', $status=1){
// $credit == 2 is refund
$this->load();
$db = Loader::db();
if($this->getAttributeValueID()){
$avID = $this->getAttributeValueID();
}
$db->Execute("INSERT INTO atPriceTotalPayments (avID,amount,payment_date,credit,transactionID,type,status) VALUES(?,?,?,?,?,?,?)", [$avID, $amount, date('Y-m-d'), $credit, $transID, $type, $status]);
$this->updatePaidAmount($avID);
}
What is needed is for the details contained in field name ‘cancle_order_reason’ on the modal to be used in place of the ‘internal’ on $transID=‘internal’ on the models/attribute/types/price_total/controller.php. I’ve tested replacing ‘internal’ with some other text, and it updates, so it is the correct one to update.
I’ve tried:
$amount = money_format('%(#4n',$this->post('credit_amount'));
$transID = $this->request('cancle_order_reason');
$ak->getController()->savePayment($avID,$amount,$transID);
And nothing changes.
Changing the other controller so
$transID='internal'
becomes
$transID
results in an error:
Too few arguments to function
PriceTotalAttributeTypeController::savePayment(), 3 passed in
/home/bookinme/web/test.book-in.me/public_html/packages/catalyst/controllers/dashboard/catalyst/orders.php
on line 842 and at least 4 expected.
I use the default codeiginter pagination library. I tried implementing this in a previously created page which shows all vacancies, but since we are getting TOO many on the site, the performance is terrible. This is why I need pagination on this page. Note that this is not the cleanest solution, there is a new track going on which overhauls the entire page and starts from scratch. This is a quick & dirty solution because we need to keep it working on our live environment until the rework is done.
This is the controller code I have:
public function overviewVacancies($city = null)
{
$this->is_logged_in();
// Load Models
$this->load->model('vacancy/vacancies_model');
$this->load->model('perk/interests_model');
$this->load->model('perk/engagement_model');
$this->load->model('user/userSavedVacancies_model');
// Passing Variables
$data['title'] = lang("page_title_activities_overview");
$data['description'] = lang('meta_desc_activities');
$data['class'] = 'vacancy';
$data['engagements'] = $this->engagement_model->getAll();
$data['interests'] = $this->interests_model->getAllInterests();
$data['bread'] = $this->breadcrumbmanager->getDashboardBreadcrumb($this->namemanager->getDashboardBreadName("0"), $this->namemanager->getDashboardBreadName("1"));
$data['tasks'] = $this->interests_model->getAllTasks();
// Set session data
$this->session->set_userdata('previous',"http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]");
$this->session->set_userdata('previous-title', "1");
$filterdata = array(
'interests' => $this->input->post('interests'),
'skills' => $this->input->post('skills'),
'fulldate' => $this->input->post('daterange'),
'location' => $this->input->post('location'),
'city' => $this->input->post('sublocality_level_1'),
'capital' => $this->input->post('locality')
);
if (!empty($filterdata['interests'])) {
$filterdata['interests'] = rtrim($filterdata['interests'], ";");
$filterdata['interests'] = str_replace(' ', '', $filterdata['interests']);
$filterdata['interests'] = str_replace(';', ',', $filterdata['interests']);
}
if (!empty($filterdata['skills'])) {
$filterdata['skills'] = str_replace(' ', '', $filterdata['skills']);
$filterdata['skills'] = explode(",", $filterdata['skills']);
}
//Manually clear the commune and city variables if the location was empty
if (empty($filterdata['location'])) {
$filterdata['city'] = '';
$filterdata['capital'] = '';
}
if($city == null){
$orgId = $this->organization_model->getOrgIdByName(LOCATION);
}
else{
$orgId = $this->organization_model->getOrgIdByName($city);
$data['bread'] = $this->breadcrumbmanager->getLocalBreadcrumb($this->namemanager->getDashboardBreadName("0"), $city, $data['title'], $data['vacancydetails']);
}
//Set the location to the subdomain automatically (e.g. when the link is clicked) so the activities of that subdomain only show up
if (!empty(LOCATION)) {
$data['title'] = sprintf(lang('page_title_local_activities'), ucwords(LOCATION));
$data['description'] = sprintf(lang('meta_desc_local_activities'), ucwords(LOCATION));
$filterdata['location'] = LOCATION;
$data['bgcolor'] = $this->localSettings_model->getBgColorHexValueForOrgId($orgId->org_id);
}
if (!empty($filterdata['fulldate'])) {
$splitfromandto = explode(" - ", $filterdata['fulldate']);
$filterdata['datefrom'] = $splitfromandto[0];
$filterdata['dateto'] = $splitfromandto[1];
} else {
$filterdata['datefrom'] = null;
$filterdata['dateto'] = null;
}
//Put these variables in the data variable so we can prefill our filters again with the previous values
//This is necessary because we don't use AJAX yet
$data['filterdata'] = $filterdata;
//Pagination : We do it here so we can re-use the filter query to count all our results
$this->load->library('pagination');
$data['all_vacancies'] = $this->vacancies_model->getFilteredVacancies($filterdata);
$pagconfig['base_url'] = base_url().VACANCY_OVERVIEW;
$pagconfig['total_rows'] = count($data['all_vacancies']);
$pagconfig['per_page'] = 1;
$pagconfig['uri_segment'] = 2;
$pagconfig['use_page_numbers'] = TRUE;
$this->pagination->initialize($pagconfig);
$data['links'] = $this->pagination->create_links();
$start = max(0, ( $this->uri->segment(2) -1 ) * $pagconfig['per_page']);
//This variable contains all the data necessary for a vacancy to be displayed on the vacancy overview page
$data['vacancies'] = $this->vacancies_model->getFilteredVacancies($filterdata, false, null, false, null, false, false, $pagconfig['per_page'], $start);
// Template declaration
$partials = array('head' => '_master/header/head', 'navigation' => '_master/header/navigation_dashboard', 'content' => 'dashboard/vacancy/overview', 'footer' => '_master/footer/footer');
$data['vacancygrid'] = $this->load->view('dashboard/vacancy/vacancygrid', $data, TRUE);
$this->template->load('_master/master', $partials, $data);
}
As you can see in the code i keep a variable called $filterdata, this contains all data which is used in our filters, since we don't use AJAX in this version, we need to pass it to the view every time to fill it up again and present it to the visitor.
However, using pagination this breaks because it just reloads my controller method and thus the values in $filterdata are lost.
How do I go about this?
Note: it does not have to be a clean solution, it just needs to work since this page is going offline in a couple of weeks anyway.
Thanks a lot in advance!
<?php
include_once '../includes/db_connect.php';
fetch_evt_values($conn, 7475, 2, 16);
function fetch_evt_values($conn, $p_frm_id, $p_evt_id, $p_usr_id) {
$p_rec_id = 0;
$l_rslt_msg = '';
$l_result = array(
'data' => array(),
'msg' => '0000'
);
$sql = 'BEGIN PHPEVT.EV_MOD.FETCH_EVT_VALUES(';
//$sql .= ':c_load_id,';
$sql .= ':c_frm_id,';
$sql .= ':c_evt_id,';
$sql .= ':c_rec_id,';
$sql .= ':c_usr_id,';
$sql .= ':c_rslt';
$sql .= '); END;';
if ($stmt = oci_parse($conn,$sql)) {
$l_results = oci_new_cursor($conn);
//oci_bind_by_name($stmt,':c_load_id',$p_load_id);
oci_bind_by_name($stmt,':c_frm_id',$p_frm_id);
oci_bind_by_name($stmt,':c_evt_id',$p_evt_id);
oci_bind_by_name($stmt,':c_rec_id',$p_rec_id);
oci_bind_by_name($stmt,':c_usr_id',$p_usr_id);
oci_bind_by_name($stmt,':c_rslt',$l_results,-1,OCI_B_CURSOR);
if(oci_execute($stmt)){ //Execute the prepared query.
oci_execute($l_results);
while($r = oci_fetch_array($l_results,OCI_ASSOC)) {
$l_evt_values = explode('|', $r['EVENT_VALUES']);
foreach($l_evt_values as $l_evt_value) {
list($l_ID, $l_value) = explode('#', $l_evt_value);
$l_values[] = array('ID' => $l_ID, 'VALUE' => $l_value);
}
$l_result['data'][] = array(
'LOAD_ID' => $r['LOAD_ID'],
'REC_ID' => $r['REC_ID'],
'TRAIT' => $l_values,
'G_MSG' => $r['G_MSG']
);
$l_rslt_msg = $r['G_MSG'];
}
} else {
//echo 'cannot get user';
$l_rslt_msg = '0005'; //PHP_MEMBER.FETCH_USER return error code
}
} else {
//echo 'connect fail';
$l_rslt_msg = '0006'; //Could not connect to database.
}
oci_close($conn);
echo json_encode($l_result);
}
?>
So on a webpage, when a user requests an event, a database call is made using this code to retrieve some values in the format :
"62#20000|65#15710|66#6|67#6|68#0|69#0|".
The PHP then breaks it apart by |, splits the ID#Value, puts everything into an array, then returns it as a JSON which is then parsed into a table. The latter works perfectly fine. But when this tries to fetch more than about 600 records or so, I get a 500 Internal Server Error, and I've figured it's something in this PHP that's handling the call.
I'm not convinced it's the database entirely, as a call for 3500 records with no further processing other than the JSON being returned is generally done in 5s or less.
Why would this code be failing at 500+ records? I've tried AJAX timeout of 0.
One of my project use solr1.2 and when i use "sort by score" in search function it's not working.I don't know why?
Can any one explain this.I am totally confuse.
my controller where i do :
protected function globalSearch($searchTerm, $productFilter = array())
{
$solrService = $this->get('syd.solr_service');
$solrQuery = new SolrQuery('*:*');
$solrQuery->addField('id')
->addField('first_product_slug')
->addField('first_product_name')
->addField('name')
->addField('slug')
->addField('thumbnail_path')
->addField('product_slug')
->addField('design_category_id')
->addSortField('score', SolrQuery::ORDER_DESC);
$solrQuery->set("group", "true");
$solrQuery->set("group.field", "first_product_id");
$solrQuery->set("group.limit", 4);
if($searchTerm){
$filterQueries = array();
$searchTerms = explode(' ',$searchTerm);
$searchTerms[] = $searchTerm;
$searchTerm = '("' . implode('" OR "', $searchTerms) . '")';
$filterQuery = sprintf(self::SEARCH_STRING, $searchTerm);
$solrQuery->addFilterQuery($filterQuery);
}
if (!empty($productFilter))
{
$productFiltersArr = array();
$productFilterQry = '';
foreach ($productFilter as $productFilterValue )
{
$productFiltersArr[] = 'first_product_slug:' . $productFilterValue;
}
$productFilterQry = implode(' OR ', $productFiltersArr);
$solrQuery->addFilterQuery($productFilterQry);
}
$solrQuery->setRows(1000);
try {
$solrObject = $solrService->query(
'SydPrintBundle:DesignTemplate',
$solrQuery,
SolrService::WRITER_FORMAT_SOLR_OBJECT
);
$templates = $solrObject->offsetGet('grouped')->offsetGet('first_product_id')->offsetGet('groups');
}
catch (\Exception $e) {
$templates = array();
}
if (!$templates) {
if (!empty($searchTerm)) {
$this->setFlash('catalog-message', 'No results found for your search.');
}
return array();
}
if (!$searchTerm) {
if (!empty($searchTerm)) {
$this->setFlash('catalog-message', 'No results found for your search.');
}
return array();
}
return $templates;
}
When you say when i use "sort by score" in search function it's not working I assume you are telling that the results are not sorted by score.
This is because your main query is *:* and you are adding your search terms via a filter query, which won't influence the score. See https://wiki.apache.org/solr/CommonQueryParameters#fq where it says
This parameter can be used to specify a query that can be used to restrict the super set of documents that can be returned, without influencing score.
So if you make the search term filter query as your main query, then you should see results sorted by score.
Update:
Instead of
$solrQuery = new SolrQuery('*:*');
use
$solrQuery = new SolrQuery();
and instead of
$solrQuery->addFilterQuery($filterQuery);
use
$solrQuery->setQuery($filterQuery);