there is a page which is updated every 5-7 seconds, and on it records from the base are updated, but moments these records are duplicated, Do not tell me why this bug can be?
is a ActiveCaller model
namespace App;
use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;
class ActiveCaller extends Model
{
protected $fillable = ['queue', 'employee_id', 'station', 'state', 'duration',
'client_id', 'last_call'];
public function Employee()
{
return $this->belongsTo(Employee::class);
}
/**
* Convert duration attribute to acceptable format
*
* #param $value
* #return string
*/
public function getDurationAttribute($value)
{
if (empty($value))
return $value;
return $this->sec2hms($value);
}
public function getStateAttribute($value)
{
if (!empty($value))
return trim($value);
return null;
}
/**
* Convert last call attribute to acceptable format
*
* #param $value
* #return string
*/
public function getLastCallAttribute($value)
{
$data = explode("\n", $value);
$result = "";
$i = 0;
$len = count($data) - 1;
foreach ($data as $item) {
$item = str_replace("\r", "", $item);
$delimiter = "</br>";
if ($i == $len)
$delimiter = "";
if (empty($item) || (trim($item) == "No calls yet")) {
$result .= "No calls yet$delimiter";
} else {
$result .= $this->sec2hms($item) . " min. ago $delimiter";
}
$i++;
}
return $result;
}
public function getStationAttribute($value)
{
return str_replace("\r\n", "</br>", $value);
}
private function sec2hms($sec, $padHours = FALSE)
{
$timeStart = Carbon::now();
$timeEnd = Carbon::now()->addSeconds(intval($sec));
return $timeStart->diff($timeEnd)->format('%H:%I:%S');
}
}
is a AmiApiController
class AmiApiController extends Controller
{
public function fetchDashboardData()
{
$this->updateQueueState();
$activeCallers = ActiveCaller::with('Employee')
->where('old', true)
->orderBy('queue')
->orderBy('employee_id')
->orderBy('station', 'asc')
->get();
$waitingList = WaitingList::where('old', false)->get();
$waitingList = $waitingList->unique('client_id');
$charts = Chart::all()->toArray();
$chartFormatData = [
'Total' => [],
'Callers' => [],
'Queues' => [],
];
foreach ($charts as $key => $chart) {
$charts[$key]['data'] = json_decode($chart['data'], 1);
$chartFormatData[$chart['name']]['total'] = 0;
foreach ($charts[$key]['data']['statistic'] as $datum) {
// if ($datum[0] === 'Effort')
// continue;
$chartFormatData[$chart['name']]['label'][] = $datum[0];
$chartFormatData[$chart['name']]['data'][] = $datum[1];
$chartFormatData[$chart['name']]['name'] = $chart['name'];
}
$chartFormatData[$chart['name']]['total'] = array_sum($chartFormatData[$chart['name']]['data']);
// $chartFormatData[$chart['name']]['label'] = array_reverse($chartFormatData[$chart['name']]['label']);
}
return response()->json([
'activeCallers' => $activeCallers,
'charts' => $chartFormatData,
'waitingList' => $waitingList
], 200);
}
this is where we begin to check if we can update the database at this time
/**
* Check whether the database can be updated at this time
*
* - Returns True if no updates are currently being made to the database
* and the latest update was less than 5 seconds later
* -
Returns True if the update already occurs for more than 15 seconds
*
* - Returns False if an update is already in the database
* -
Returns False if the last update was within the last 5 seconds
*
* If the parameter in $ json is passed true (by default)
* the method returns the answer in JSON format
*
* If the parameter is passed false to $ json
* method returns a php-shne Boolean value
*
* #param bool $json
* #return bool|\Illuminate\Http\JsonResponse
*/
public function canWeUpdate($json = true)
{
$result = ['return' => null, 'msg' => null];
$isUpdating = Configuration::where('key', 'is_ami_data_updating')->first();
if (is_null($isUpdating)) {
Configuration::create(['key' => 'is_ami_data_updating', 'value' => 0]);
}
if ($isUpdating->value == true) {
// if an update is currently in progress
$checkingDate = Carbon::now()->addSeconds(-10);
if ($isUpdating->updated_at < $checkingDate) {
// if the update is longer than 15 seconds, we will cancel this update
$isUpdating->update(['value' => false]);
$result['return'] = true;
$result['msg'] = "Old update in database";
} else {
// if the update is less than 15 seconds, we cannot update again
$result['return'] = false;
$result['msg'] = "CURRENTLY UPDATE";
}
} else if ($isUpdating->updated_at > Carbon::now()->addSeconds(-3)) {
// if the last update was less than 5 seconds ago, we cannot update
$result['return'] = false;
$result['msg'] = "TOO EARLY";
} else {
//if the last update was more than 5 seconds ago, we allow the update
$result['return'] = true;
$result['msg'] = "OK";
}
if ($json)
return $this->simpleResponse($result['return'], $result['msg']);
return $result['return'];
}
is a method fot check if new data is in the database
/**
* A method to check if new data is in the database
*
* Returns True if validation time is less than database update time
* Returns False if validation time is longer than database update time
* Returns False if there is no data in the database
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\JsonResponse
*/
public function checkForNewData(Request $request)
{
$date = new Carbon($request->last_call);
$lastRecord = ActiveCaller::latest()->first();
if (is_null($lastRecord))
return $this->simpleResponse(false);
if ($date < $lastRecord->updated_at) {
return $this->simpleResponse(true);
} else
return $this->simpleResponse(false);
}
/**
* Method for loading table data
*
* Agents - information about active numbers in the PBX in all queues
* Waiting - information about numbers in standby mode
*
* #return \Illuminate\Http\JsonResponse
*/
public function renderAgentTable()
{
$agents = ActiveCaller::with('Employee')
->where('old', true)
->orderBy('queue')
->orderBy('station', 'asc')
->get();
$waitingList = WaitingList::all();
$agentsTable = View::make('dashboard.render.agent-table', ['agents' => $agents]);
$waitingTable = View::make('dashboard.render.waiting-list-table', ['waitingList' => $waitingList]);
$result =
[
'agents' => $agentsTable->render(),
'waiting' => $waitingTable->render(),
];
$result = array_merge($result, $this->renderDashboardChart(new Request()));
return response()->json($result);
}
/**
* Method for updating data from AMI
*
* updating data for ActiveCaller
* updating data for WaitingList
*/
public function updateQueueState()
{
if (!$this->canWeUpdate(false)) {
// dd("We can't update (large check)");
return;
}
$lastUpdateTime = ActiveCaller::latest()->first();
if ($lastUpdateTime != null)
if ($lastUpdateTime->created_at > Carbon::now()->addSeconds(-3)) {
// dd("We can't update (small check)");
return;
}
// we notice the launch of the update in the database
$isAmiDataUpdating = Configuration::where('key', 'is_ami_data_updating')->first();
$isAmiDataUpdating->update(['value' => true]);
$this->ClearOldRecords();
$queues = Queue::where('on_dashboard', '=', '1')->get()->toArray();
// we go through all the queues that are available in AMI
foreach ($queues as $queue) {
$command = new AMIQueueMemberState($queue['name']);
// we get a list of numbers and a waiting list of calls
$response = $command->handle();
$agents = $response['agents'];
$callers = $response['callers'];
//convert the waiting list to PeerList
$peerList = PeerInfo::hydrate($agents);
$employees = new Collection();
foreach ($callers as $caller) {
$caller['queue'] = $queue['name'];
WaitingList::create($caller);
}
$peerList->each(function (PeerInfo $peer) use ($employees) {
$record = Record
::where('phone', 'like', '%' . $peer->name . '%')
->where('end_date', null)
->get()->first();
$data = null;
if ($record != null) {
// check if this user already has an entry in active_callers (not old)
$active = ActiveCaller
::where('employee_id', $record['employee_id'])
->where('old', false)
->get()->first();
// if so, add him another number and
// we move on to the next iteration
if ($active != null) {
if ($this->HandleSingleActive($active, $peer->name, $peer->last_call))
return;
}
$peer->station = $record['station_name'];
$peer->employee_id = $record['employee_id'];
$a = collect($peer->toArray());
$data = $a->except(['name', 'pause'])->toArray();
$data['station'] = "$peer->station | $peer->name";
} else {
$peer->station = "- | $peer->name";
$a = collect($peer->toArray());
$data = $a->except(['name', 'pause'])->toArray();
}
ActiveCaller::create($data);
});
}
$this->updateDashboardChart();
$isAmiDataUpdating->update(['value' => false]);
}
How can you get a list of the executed queries when debug is set to 0 ?
I have the following functions in AppController:
// log INSERT, UPDATE, DELETE queries
private function __logQueries(){
$db = &ConnectionManager::getDataSource('default');
$query_logs = $db->getLog();
if( isset($query_logs['log']) && !empty($query_logs['log']) ){
$this->loadModel('SqlLog');
foreach($query_logs['log'] as $log_q){
$query = $log_q['query'];
if( stristr($query, 'INSERT ') || stristr($query, 'UPDATE ') || stristr($query, 'DELETE ') ){
$q_data = array(
'query' => $query,
'page' => $this->Misc->getCurrentPageURL(), // get the current page
'referrer' => trim(env('HTTP_REFERER')) == '' ? '' : env('HTTP_REFERER'),
'ip' => env('REMOTE_ADDR'),
'browser' => env('HTTP_USER_AGENT'),
'user_id' => SessionComponent::check('Auth.User') ? SessionComponent::read('Auth.User.id') : 0,
'username' => SessionComponent::check('Auth.User') ? addslashes(SessionComponent::read('Auth.User.username')) : '',
);
$this->SqlLog->create();
$this->SqlLog->save($q_data);
}
}
} // end if query occured
}
public function beforeRedirect(){
$this->__logQueries();
}
public function afterFilter(){
$this->__logQueries();
}
The insert, update and delete queries get logged when debug is set to 2, but how can I log those queries when debug is set to 0?
Whether queries are being logged depends on the DboSource::$fullDebug property, it's being set in the DboSource constructur, and by default it's true in case debug is > 1.
So all you have to do is overwrite the value of this property with true, this will ensure that as of this point the queries are being logged regardless of the debug setting.
App::uses('ConnectionManager', 'Model');
ConnectionManager::getDataSource('default')->fullDebug = true;
Create your own dbo file in the specified path:
\app\models\datasources\dbo\dbo_mysql_with_log.php
and the content of this file will be
<?php
class DboMysqlBase extends DboSource {
/**
* Description property.
*
* #var string
*/
var $description = "MySQL DBO Base Driver";
/**
* Start quote
*
* #var string
*/
var $startQuote = "`";
/**
* End quote
*
* #var string
*/
var $endQuote = "`";
/**
* use alias for update and delete. Set to true if version >= 4.1
*
* #var boolean
* #access protected
*/
var $_useAlias = true;
/**
* Index of basic SQL commands
*
* #var array
* #access protected
*/
var $_commands = array(
'begin' => 'START TRANSACTION',
'commit' => 'COMMIT',
'rollback' => 'ROLLBACK'
);
/**
* MySQL column definition
*
* #var array
*/
var $columns = array(
'primary_key' => array('name' => 'NOT NULL AUTO_INCREMENT'),
'string' => array('name' => 'varchar', 'limit' => '255'),
'text' => array('name' => 'text'),
'integer' => array('name' => 'int', 'limit' => '11', 'formatter' => 'intval'),
'float' => array('name' => 'float', 'formatter' => 'floatval'),
'datetime' => array('name' => 'datetime', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
'timestamp' => array('name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
'time' => array('name' => 'time', 'format' => 'H:i:s', 'formatter' => 'date'),
'date' => array('name' => 'date', 'format' => 'Y-m-d', 'formatter' => 'date'),
'binary' => array('name' => 'blob'),
'boolean' => array('name' => 'tinyint', 'limit' => '1')
);
/**
* Generates and executes an SQL UPDATE statement for given model, fields, and values.
*
* #param Model $model
* #param array $fields
* #param array $values
* #param mixed $conditions
* #return array
*/
function update(&$model, $fields = array(), $values = null, $conditions = null) {
if (!$this->_useAlias) {
return parent::update($model, $fields, $values, $conditions);
}
if ($values == null) {
$combined = $fields;
} else {
$combined = array_combine($fields, $values);
}
$alias = $joins = false;
$fields = $this->_prepareUpdateFields($model, $combined, empty($conditions), !empty($conditions));
$fields = join(', ', $fields);
$table = $this->fullTableName($model);
if (!empty($conditions)) {
$alias = $this->name($model->alias);
if ($model->name == $model->alias) {
$joins = implode(' ', $this->_getJoins($model));
}
}
$conditions = $this->conditions($this->defaultConditions($model, $conditions, $alias), true, true, $model);
if ($conditions === false) {
return false;
}
if (!$this->execute($this->renderStatement('update', compact('table', 'alias', 'joins', 'fields', 'conditions')))) {
$model->onError();
return false;
}
return true;
}
/**
* Generates and executes an SQL DELETE statement for given id/conditions on given model.
*
* #param Model $model
* #param mixed $conditions
* #return boolean Success
*/
function delete(&$model, $conditions = null) {
if (!$this->_useAlias) {
return parent::delete($model, $conditions);
}
$alias = $this->name($model->alias);
$table = $this->fullTableName($model);
$joins = implode(' ', $this->_getJoins($model));
if (empty($conditions)) {
$alias = $joins = false;
}
$conditions = $this->conditions($this->defaultConditions($model, $conditions, $alias), true, true, $model);
if ($conditions === false) {
return false;
}
if ($this->execute($this->renderStatement('delete', compact('alias', 'table', 'joins', 'conditions'))) === false) {
$model->onError();
return false;
}
return true;
}
/**
* Sets the database encoding
*
* #param string $enc Database encoding
*/
function setEncoding($enc) {
return $this->_execute('SET NAMES ' . $enc) != false;
}
/**
* Returns an array of the indexes in given datasource name.
*
* #param string $model Name of model to inspect
* #return array Fields in table. Keys are column and unique
*/
function index($model) {
$index = array();
$table = $this->fullTableName($model);
if ($table) {
$indexes = $this->query('SHOW INDEX FROM ' . $table);
if (isset($indexes[0]['STATISTICS'])) {
$keys = Set::extract($indexes, '{n}.STATISTICS');
} else {
$keys = Set::extract($indexes, '{n}.0');
}
foreach ($keys as $i => $key) {
if (!isset($index[$key['Key_name']])) {
$col = array();
$index[$key['Key_name']]['column'] = $key['Column_name'];
$index[$key['Key_name']]['unique'] = intval($key['Non_unique'] == 0);
} else {
if (!is_array($index[$key['Key_name']]['column'])) {
$col[] = $index[$key['Key_name']]['column'];
}
$col[] = $key['Column_name'];
$index[$key['Key_name']]['column'] = $col;
}
}
}
return $index;
}
/**
* Generate a MySQL Alter Table syntax for the given Schema comparison
*
* #param array $compare Result of a CakeSchema::compare()
* #return array Array of alter statements to make.
*/
function alterSchema($compare, $table = null) {
if (!is_array($compare)) {
return false;
}
$out = '';
$colList = array();
foreach ($compare as $curTable => $types) {
$indexes = array();
if (!$table || $table == $curTable) {
$out .= 'ALTER TABLE ' . $this->fullTableName($curTable) . " \n";
foreach ($types as $type => $column) {
if (isset($column['indexes'])) {
$indexes[$type] = $column['indexes'];
unset($column['indexes']);
}
switch ($type) {
case 'add':
foreach ($column as $field => $col) {
$col['name'] = $field;
$alter = 'ADD '.$this->buildColumn($col);
if (isset($col['after'])) {
$alter .= ' AFTER '. $this->name($col['after']);
}
$colList[] = $alter;
}
break;
case 'drop':
foreach ($column as $field => $col) {
$col['name'] = $field;
$colList[] = 'DROP '.$this->name($field);
}
break;
case 'change':
foreach ($column as $field => $col) {
if (!isset($col['name'])) {
$col['name'] = $field;
}
$colList[] = 'CHANGE '. $this->name($field).' '.$this->buildColumn($col);
}
break;
}
}
$colList = array_merge($colList, $this->_alterIndexes($curTable, $indexes));
$out .= "\t" . join(",\n\t", $colList) . ";\n\n";
}
}
return $out;
}
/**
* Generate a MySQL "drop table" statement for the given Schema object
*
* #param object $schema An instance of a subclass of CakeSchema
* #param string $table Optional. If specified only the table name given will be generated.
* Otherwise, all tables defined in the schema are generated.
* #return string
*/
function dropSchema($schema, $table = null) {
if (!is_a($schema, 'CakeSchema')) {
trigger_error(__('Invalid schema object', true), E_USER_WARNING);
return null;
}
$out = '';
foreach ($schema->tables as $curTable => $columns) {
if (!$table || $table == $curTable) {
$out .= 'DROP TABLE IF EXISTS ' . $this->fullTableName($curTable) . ";\n";
}
}
return $out;
}
/**
* Generate MySQL index alteration statements for a table.
*
* #param string $table Table to alter indexes for
* #param array $new Indexes to add and drop
* #return array Index alteration statements
*/
function _alterIndexes($table, $indexes) {
$alter = array();
if (isset($indexes['drop'])) {
foreach($indexes['drop'] as $name => $value) {
$out = 'DROP ';
if ($name == 'PRIMARY') {
$out .= 'PRIMARY KEY';
} else {
$out .= 'KEY ' . $name;
}
$alter[] = $out;
}
}
if (isset($indexes['add'])) {
foreach ($indexes['add'] as $name => $value) {
$out = 'ADD ';
if ($name == 'PRIMARY') {
$out .= 'PRIMARY ';
$name = null;
} else {
if (!empty($value['unique'])) {
$out .= 'UNIQUE ';
}
}
if (is_array($value['column'])) {
$out .= 'KEY '. $name .' (' . join(', ', array_map(array(&$this, 'name'), $value['column'])) . ')';
} else {
$out .= 'KEY '. $name .' (' . $this->name($value['column']) . ')';
}
$alter[] = $out;
}
}
return $alter;
}
/**
* Inserts multiple values into a table
*
* #param string $table
* #param string $fields
* #param array $values
*/
function insertMulti($table, $fields, $values) {
$table = $this->fullTableName($table);
if (is_array($fields)) {
$fields = join(', ', array_map(array(&$this, 'name'), $fields));
}
$values = implode(', ', $values);
$this->query("INSERT INTO {$table} ({$fields}) VALUES {$values}");
}
}
class DboMysql extends DboMysqlBase {
/**
* Enter description here...
*
* #var unknown_type
*/
var $description = "MySQL DBO Driver";
/**
* Base configuration settings for MySQL driver
*
* #var array
*/
var $_baseConfig = array(
'persistent' => true,
'host' => 'localhost',
'login' => 'root',
'password' => '',
'database' => 'cake',
'port' => '3306',
'connect' => 'mysql_pconnect'
);
/**
* Connects to the database using options in the given configuration array.
*
* #return boolean True if the database could be connected, else false
*/
function connect() {
$config = $this->config;
$connect = $config['connect'];
$this->connected = false;
if (!$config['persistent']) {
$this->connection = mysql_connect($config['host'] . ':' . $config['port'], $config['login'], $config['password'], true);
} else {
$this->connection = $connect($config['host'] . ':' . $config['port'], $config['login'], $config['password']);
}
if (mysql_select_db($config['database'], $this->connection)) {
$this->connected = true;
}
if (isset($config['encoding']) && !empty($config['encoding'])) {
$this->setEncoding($config['encoding']);
}
$this->_useAlias = (bool)version_compare(mysql_get_server_info($this->connection), "4.1", ">=");
return $this->connected;
}
/**
* Disconnects from database.
*
* #return boolean True if the database could be disconnected, else false
*/
function disconnect() {
if (isset($this->results) && is_resource($this->results)) {
mysql_free_result($this->results);
}
$this->connected = !#mysql_close($this->connection);
return !$this->connected;
}
/**
* Executes given SQL statement.
*
* #param string $sql SQL statement
* #return resource Result resource identifier
* #access protected
*/
function _execute($sql) {
return mysql_query($sql, $this->connection);
}
/**
* Returns an array of sources (tables) in the database.
*
* #return array Array of tablenames in the database
*/
function listSources() {
$cache = parent::listSources();
if ($cache != null) {
return $cache;
}
$result = $this->_execute('SHOW TABLES FROM ' . $this->name($this->config['database']) . ';');
if (!$result) {
return array();
} else {
$tables = array();
while ($line = mysql_fetch_array($result)) {
$tables[] = $line[0];
}
parent::listSources($tables);
return $tables;
}
}
/**
* Returns an array of the fields in given table name.
*
* #param string $tableName Name of database table to inspect
* #return array Fields in table. Keys are name and type
*/
function describe(&$model) {
$cache = parent::describe($model);
if ($cache != null) {
return $cache;
}
$fields = false;
$cols = $this->query('DESCRIBE ' . $this->fullTableName($model));
foreach ($cols as $column) {
$colKey = array_keys($column);
if (isset($column[$colKey[0]]) && !isset($column[0])) {
$column[0] = $column[$colKey[0]];
}
if (isset($column[0])) {
$fields[$column[0]['Field']] = array(
'type' => $this->column($column[0]['Type']),
'null' => ($column[0]['Null'] == 'YES' ? true : false),
'default' => $column[0]['Default'],
'length' => $this->length($column[0]['Type']),
);
if (!empty($column[0]['Key']) && isset($this->index[$column[0]['Key']])) {
$fields[$column[0]['Field']]['key'] = $this->index[$column[0]['Key']];
}
}
}
$this->__cacheDescription($this->fullTableName($model, false), $fields);
return $fields;
}
/**
* Returns a quoted and escaped string of $data for use in an SQL statement.
*
* #param string $data String to be prepared for use in an SQL statement
* #param string $column The column into which this data will be inserted
* #param boolean $safe Whether or not numeric data should be handled automagically if no column data is provided
* #return string Quoted and escaped data
*/
function value($data, $column = null, $safe = false) {
$parent = parent::value($data, $column, $safe);
if ($parent != null) {
return $parent;
}
if ($data === null || (is_array($data) && empty($data))) {
return 'NULL';
}
if ($data === '' && $column !== 'integer' && $column !== 'float' && $column !== 'boolean') {
return "''";
}
if (empty($column)) {
$column = $this->introspectType($data);
}
switch ($column) {
case 'boolean':
return $this->boolean((bool)$data);
break;
case 'integer':
case 'float':
if ($data === '') {
return 'NULL';
}
if ((is_int($data) || is_float($data) || $data === '0') || (
is_numeric($data) && strpos($data, ',') === false &&
$data[0] != '0' && strpos($data, 'e') === false)) {
return $data;
}
default:
$data = "'" . mysql_real_escape_string($data, $this->connection) . "'";
break;
}
return $data;
}
/**
* Returns a formatted error message from previous database operation.
*
* #return string Error message with error number
*/
function lastError() {
if (mysql_errno($this->connection)) {
return mysql_errno($this->connection).': '.mysql_error($this->connection);
}
return null;
}
/**
* Returns number of affected rows in previous database operation. If no previous operation exists,
* this returns false.
*
* #return integer Number of affected rows
*/
function lastAffected() {
if ($this->_result) {
return mysql_affected_rows($this->connection);
}
return null;
}
/**
* Returns number of rows in previous resultset. If no previous resultset exists,
* this returns false.
*
* #return integer Number of rows in resultset
*/
function lastNumRows() {
if ($this->hasResult()) {
return mysql_num_rows($this->_result);
}
return null;
}
/**
* Returns the ID generated from the previous INSERT operation.
*
* #param unknown_type $source
* #return in
*/
function lastInsertId($source = null) {
$id = $this->fetchRow('SELECT LAST_INSERT_ID() AS insertID', false);
if ($id !== false && !empty($id) && !empty($id[0]) && isset($id[0]['insertID'])) {
return $id[0]['insertID'];
}
return null;
}
/**
* Converts database-layer column types to basic types
*
* #param string $real Real database-layer column type (i.e. "varchar(255)")
* #return string Abstract column type (i.e. "string")
*/
function column($real) {
if (is_array($real)) {
$col = $real['name'];
if (isset($real['limit'])) {
$col .= '('.$real['limit'].')';
}
return $col;
}
$col = str_replace(')', '', $real);
$limit = $this->length($real);
if (strpos($col, '(') !== false) {
list($col, $vals) = explode('(', $col);
}
if (in_array($col, array('date', 'time', 'datetime', 'timestamp'))) {
return $col;
}
if (($col == 'tinyint' && $limit == 1) || $col == 'boolean') {
return 'boolean';
}
if (strpos($col, 'int') !== false) {
return 'integer';
}
if (strpos($col, 'char') !== false || $col == 'tinytext') {
return 'string';
}
if (strpos($col, 'text') !== false) {
return 'text';
}
if (strpos($col, 'blob') !== false || $col == 'binary') {
return 'binary';
}
if (strpos($col, 'float') !== false || strpos($col, 'double') !== false || strpos($col, 'decimal') !== false) {
return 'float';
}
if (strpos($col, 'enum') !== false) {
return "enum($vals)";
}
return 'text';
}
/**
* Enter description here...
*
* #param unknown_type $results
*/
function resultSet(&$results) {
if (isset($this->results) && is_resource($this->results) && $this->results != $results) {
mysql_free_result($this->results);
}
$this->results =& $results;
$this->map = array();
$numFields = mysql_num_fields($results);
$index = 0;
$j = 0;
while ($j < $numFields) {
$column = mysql_fetch_field($results,$j);
if (!empty($column->table)) {
$this->map[$index++] = array($column->table, $column->name);
} else {
$this->map[$index++] = array(0, $column->name);
}
$j++;
}
}
/**
* Fetches the next row from the current result set
*
* #return unknown
*/
function fetchResult() {
if ($row = mysql_fetch_row($this->results)) {
$resultRow = array();
$i = 0;
foreach ($row as $index => $field) {
list($table, $column) = $this->map[$index];
$resultRow[$table][$column] = $row[$index];
$i++;
}
return $resultRow;
} else {
return false;
}
}
/**
* Gets the database encoding
*
* #return string The database encoding
*/
function getEncoding() {
return mysql_client_encoding($this->connection);
}
}
class DboMysqlWithLog extends DboMysql {
function _execute($sql) {
//exclude these types of queries from being logged, change if required
if(!preg_match('/^SHOW|SELECT|DESCRIBE|cake_sessions.*/',$sql) && !preg_match('/^SET.*/',$sql)){
//HH_DOCUMENT_ROOT should be defined in one of the core files pointing to the project root directory, if its not there define it
//do not commit changes, if its specific to local machine
//$filename = HH_DOCUMENT_ROOT.DS.'sql.txt';
$filename = 'C:\xampp\htdocs\your_project_dir\app\sql.txt';
$patfile = fopen($filename, 'a+');
$textdata = "$sql\n";
fwrite($patfile, $textdata);
fclose($patfile);
}
return parent::_execute($sql);
}
}
?>
change sql log file path $filename = 'C:\xampp\htdocs\your_project_dir\app\sql.txt';
Step 2: Open /app/config/database.php
and change 'driver' => 'dbo_mysql_with_log',
This will record all your sql scripts in the below path
C:\xampp\htdocs\your_project_dir\app\sql.txt
I'm using cakephp framework.I want to export a database table of a client download in two formats.One is '.csv', the other is a '.txt'.CSV which I have passed 'csvHelper' resolved.Now I want to know how to export '.txt'.Sorry for my poor English, but I think you'll see what I mean, thanks!
Basically you set the header for the filename, like this:
$this->response->type('Content-Type: text/csv');
$this->response->download('myfilename.txt');
Here are some functions I put in my appController, so that any controller can output a CSV file if required:
/**
* Flattens the data that is returned from a find() operation, and puts it into CSV format
* #param $data
* #return string
*/
public function _arrayToCsvFile($data){
$flattenedData = array();
$exportKeyPair = array();
foreach($data as $datumKey => $datumDetails){
$flattenedDatum = Hash::flatten($datumDetails, '.');
$flattenedData[] = $flattenedDatum;
// Find all keys
if($datumKey == 0){
$exportKeys = array_keys($flattenedDatum);
$exportKeyPair = array_combine($exportKeys, $exportKeys);
}
else {
$datumKeys = array_keys($flattenedDatum);
$datumKeyPair = array_combine($datumKeys, $datumKeys);
// Add the datum keys to the exportKeyPair if it's not already there
$exportKeyPair = array_merge($exportKeyPair, $datumKeyPair);
}
}
$exportKeyMap = array();
foreach($exportKeyPair as $exportKey => $exportValue){
$exportKeyMap[$exportKey] = "";
}
$outputCSV = '';
$outputCSV .= $this->_arrayToCsvLine($exportKeyPair);
foreach($flattenedData as $flattenedDatumKey => $flattenedDatumDetails){
// Add any extra keys
$normalisedDatumDetails = array_merge($exportKeyMap, $flattenedDatumDetails);
$outputCSV .= $this->_arrayToCsvLine($normalisedDatumDetails);
}
return $outputCSV;
}
/**
* arrayToCsvLine function - turns an array into a line of CSV data.
*
* #access public
* #param mixed $inputLineArray the input array
* #param string $separator (default: ")
* #param string $quote (default: '"')
* #return string
*/
function _arrayToCsvLine($inputLineArray, $separator = ",", $quote = '"') {
$outputLine = "";
$numOutput = 0;
foreach($inputLineArray as $inputLineKey => $inputLineValue) {
if($numOutput > 0) {
$outputLine .= $separator;
}
$outputLine .= $quote . str_replace(array('"', "\n", "\r"),array('""', "", ""), $inputLineValue) . $quote;
$numOutput++;
}
$outputLine .= "\n";
return $outputLine;
}
/**
* Serves some CSV contents out to the client
* #param $csvContents
* #param array $options
*/
public function _serveCsv($csvContents, $options = array()){
$defaults = array(
'modelClass' => $this->modelClass,
'fileName' => null
);
$settings = array_merge($defaults, $options);
if(empty($settings['fileName'])){
$settings['fileName'] = strtolower( Inflector::pluralize( $settings['modelClass'] ) ) . '_' . date('Y-m-d_H-i') . '.csv';
}
$this->autoRender = false;
$this->response->type('Content-Type: text/csv');
$this->response->download($settings['fileName']);
$this->response->body($csvContents);
}
Now in any controller you can do this (note that you can pass the filename to _serveCsv if required):
/**
* admin_export_csv method
*
* #return void
*/
public function admin_export_csv() {
$this->Order->recursive = 0;
$conditions = array();
$orders = $this->Order->find('all', array('conditions' => $conditions));
$csvContents = $this->_arrayToCsvFile($orders); // Function in AppController
$this->_serveCsv($csvContents, array('filename' => 'export.txt')); // Function in AppController
}
you can use
$this->RequestHandler->respondAs('txt'); to output the correct header.
Please not the header is not set when DEBUG is greater than 2.
And you will still have to build the controller action and set view as ususal.
I'm using Tree Behavior to store a ordered list of items.
When I add new elements to the tree I reorder it calling to the "reorder()" function. It is very slow. I've been trying a lot of things. My last test was a single table with 70 elements (1 parent and 69 childs). The time used for the reorder() function, was 1 minute & 20 seconds. I'm using MySQL and I have indexes in id, parent_id, rght and lft fields.
What could I be doing wrong?
Thanks
I've spent some time investigating this one as well.
It turns out that the reorder function is very inefficient. Basically it sets the left and right fields on the first item to high values, and then reorders the rest of the fields. Then it does the same for the second item, etc. You end up with tens of thousands of queries being run, for a tree with only a hundred items.
I sorted it out with the following code. What this does is only update each record once, and it preserves the gap between left and right values. It recursively goes through the items and reorders them properly.
Create a new file in app/Model/Behavior called "BRTreeBehavior.php", and then modify your model's $actsAs field to use BRTree instead of Tree.
<?php
/**
* Copyright 2015, Perthweb Pty Ltd
*
*/
App::uses('TreeBehavior', 'Model/Behavior');
/**
* BetterReorderTree Behavior.
*
* Improves reorder of tree behavior
*
*/
class BRTreeBehavior extends TreeBehavior {
/**
* Reorder method.
*
* Reorders the nodes (and child nodes) of the tree according to the field and direction specified in the parameters.
* This method does not change the parent of any node.
*
* Requires a valid tree, by default it verifies the tree before beginning.
*
* Options:
*
* - 'id' id of record to use as top node for reordering
* - 'field' Which field to use in reordering defaults to displayField
* - 'order' Direction to order either DESC or ASC (defaults to ASC)
* - 'verify' Whether or not to verify the tree before reorder. defaults to true.
*
* #param Model $Model Model instance
* #param array $options array of options to use in reordering.
* #return boolean true on success, false on failure
* #link http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html#TreeBehavior::reorder
*/
public function reorder(Model $Model, $options = array()) {
$options = array_merge(array('id' => null, 'field' => $Model->displayField, 'order' => 'ASC', 'verify' => true, 'startIndex' => null), $options);
extract($options);
if ($verify && !$this->verify($Model)) {
return false;
}
$verify = false;
extract($this->settings[$Model->alias]);
$fields = array($Model->primaryKey, $field, $left, $right);
$sort = $field . ' ' . $order;
$nodes = $this->children($Model, $id, true, $fields, $sort, null, null, $recursive);
$cacheQueries = $Model->cacheQueries;
$Model->cacheQueries = false;
if ($nodes) {
if($id == null){
$index = 1;
}
else if($startIndex == null){
$index = $nodes[0][$Model->alias][$left];
}
else {
$index = $startIndex;
}
foreach ($nodes as $node) {
$id = $node[$Model->alias][$Model->primaryKey];
$difference = $node[$Model->alias][$right] - $node[$Model->alias][$left];
$nodeData = array(
$Model->alias => array(
$Model->primaryKey => $id,
$left => $index,
$right => $index + $difference
)
);
$Model->create();
$Model->save($nodeData, array('validate' => false, 'callbacks' => false, 'fieldList' => array($left, $right)));
$Model->clear();
$startIndex = $index + 1;
if ($difference != 1) {
$this->reorder($Model, compact('id', 'field', 'order', 'verify', 'startIndex'));
}
$index += $difference + 1;
}
}
$Model->cacheQueries = $cacheQueries;
return true;
}
}
I've started working on a theme from scratch, I've tried to replace the title of the textfield but when imploding the search variable into search_form, the result is blank. Any error that I could be missing?
`function mytheme_preprocess_search_block_form(&$form) {
$form['search'] = array();
$hidden = array();
// Provide variables named after form keys so themers can print each element independently.
foreach (element_children($form['form']) as $key) {
echo $key;
$type = $form['form'][$key]['#type'];
echo '__'.$type.'<br />';
if ($type == 'hidden' || $type == 'token') {
$hidden[] = drupal_render($form['form'][$key]);
}
else {
if($key == 'search_block_form')
{
$form['form'][$key]['#title'] = t('');
//$form['search'][$key] = drupal_render($form['form'][$key]);
}
else
{
$form['search'][$key] = drupal_render($form['form'][$key]);
}
}
}
// Hidden form elements have no value to themers. No need for separation.
$form['search']['hidden'] = implode($hidden);
// Collect all form elements to make it easier to print the whole form.
$form['search_form'] = implode($form['search']);
var_dump($form);
exit;
}`
Refer to http://drupal.org/node/1092122:
<?php
/**
* Implements hook_theme().
*/
function MYMODULE_theme($existing, $type, $theme, $path) {
return array(
'article_node_form' => array(
'render element' => 'form',
'template' => 'article-node-form',
// this will set to module/theme path by default:
'path' => drupal_get_path('module', 'MYMODULE'),
),
);
}
?>
<?php
/**
* Preprocessor for theme('article_node_form').
*/
function template_preprocess_article_node_form(&$variables) {
// nodeformcols is an alternative for this solution.
if (!module_exists('nodeformcols')) {
$variables['sidebar'] = array(); // Put taxonomy fields in sidebar.
$variables['sidebar'][] = $variables['form']['field_tags'];
hide($variables['form']['field_tags']);
// Extract the form buttons, and put them in independent variable.
$variables['buttons'] = $variables['form']['actions'];
hide($variables['form']['actions']);
}
}
?>
article-node-form.tpl.php
<?php echo drupal_render_children($form)?>