I have following xml:
<config>
<global>
<resources>
<dbresource>
<connection>
<host><![CDATA[localhost]]></host>
<username><![CDATA[root]]></username>
<password><![CDATA[1234]]></password>
<dbname><![CDATA[db_test]]></dbname>
</connection>
</dbresource>
...
...
I want to add all these Informations like(host, username, password and dbname) in admin_core_data and read them to connect to an external database. I know how to read/write data into admin_core_data using system.xml.
and I can connect to external database with config.xml but I need to let the employee to change it easily in "admin/system/configuration" because they cant edit xml files.
or any other idea guys, what to do in this situation?
Any advice guys?
Thank you..
There is slight different approach by which you can implement the functionality. Add a new system.xml and then need to update the database configuration in madel files.
const XML_CONFIG_EDB_HOST = 'edb_settings/dbconnection/host';
const XML_CONFIG_EDB_DBNAME = 'edb_settings/dbconnection/dbname';
const XML_CONFIG_EDB_USERNAME = 'edb_settings/dbconnection/username';
const XML_CONFIG_EDB_PASSWORD = 'edb_settings/dbconnection/password';
const EXTERNAL_RESOURCE_NAME = 'edb_connection';
/* #var array */
protected $_config;
/* #var Varien_Db_Adapter_Pdo_Mysql */
protected $_connection;
public function __construct() {
$this->_setConnection();
}
/**
* Gets the Config Settings in the Admin Settings for DB Connection
* #return array
*/
public function getConfig() {
if (!$this->_config) {
$this->_config = array();
// Setting the Values from the Admin Config
$this->_config['host'] = Mage::getStoreConfig(self::XML_CONFIG_EDB_HOST);
$this->_config['dbname'] = Mage::getStoreConfig(self::XML_CONFIG_EDB_DBNAME);
$this->_config['username'] = Mage::getStoreConfig(self::XML_CONFIG_EDB_USERNAME);
$this->_config['password'] = Mage::getStoreConfig(self::XML_CONFIG_EDB_PASSWORD);
// Setting the default Values
$this->_config['initStatements'] = 'SET NAMES utf8';
$this->_config['model'] = 'mysql4';
$this->_config['type'] = 'pdo_mysql';
$this->_config['pdoType'] = '';
$this->_config['active'] = '1';
}
return $this->_config;
}
/**
* Gets External DB Connection Resource
*
* #return Varien_Db_Adapter_Pdo_Mysql
*/
public function getConnection() {
if (!$this->_connection) {
$this->_setConnection();
}
return $this->_connection;
}
private function _setConnection() {
if (!$this->_connection) {
$this->_connection = Mage::getSingleton('core/resource')->createConnection(self::EXTERNAL_RESOURCE_NAME, 'pdo_mysql', $this->getConfig());
}
}
public static function getConnectionName() {
return self::EXTERNAL_RESOURCE_NAME;
}
You can take a reference from below link
External database configuration
You could use Magento standard way of getting store config.
$configValue = Mage::getStoreConfig('sectionName/groupName/fieldName');
sectionName, groupName and fieldName should be defined in etc/system.xml file of your module.
The above code will automatically fetch config value of currently viewed store.
Check some system.xml files to see how it is defined in Magento, so you can easily add it to your module.
Related
Spartacus lists 10 products in the pagination defualt on its product listing page. But I wanted it to be 12.
In my .ts file normally for PLP
protected productListComponentServiceDefault: ProductListComponentService,
I was using the structure.
but I created "CutomProductListComponentService" by customizing the "ProductListComponentService" file.
protected defaultPageSize = 12;
I did what I wanted by adding. Pagination artok 12 works.
But after this customization, the "SORTING" operation within the page does not work anymore.
Inside CutomProductListComponentService I added the following:
import { Injectable } from '#angular/core';
import { ActivatedRoute, Router } from '#angular/router';
import {
ActivatedRouterStateSnapshot,
CurrencyService,
LanguageService,
ProductSearchPage,
ProductSearchService,
RouterState,
RoutingService,
} from '#spartacus/core';
import { combineLatest, Observable, using } from 'rxjs';
import {
debounceTime,
distinctUntilChanged,
filter,
map,
shareReplay,
tap,
} from 'rxjs/operators';
// #ts-ignore
import { ProductListRouteParams, SearchCriteria } from './product-list.model';
/**
* The `ProductListComponentService` is used to search products. The service is used
* on the Product Listing Page, for listing products and the facet navigation.
*
* The service exposes the product search results based on the category and search
* route parameters. The route parameters are used to query products by the help of
* the `ProductSearchService`.
*/
#Injectable({ providedIn: 'root' })
export class CustomProductListComponentService {
// TODO: make it configurable
protected defaultPageSize = 12;
protected readonly RELEVANCE_ALLCATEGORIES = ':relevance:allCategories:';
constructor(
protected productSearchService: ProductSearchService,
protected routing: RoutingService,
protected activatedRoute: ActivatedRoute,
protected currencyService: CurrencyService,
protected languageService: LanguageService,
protected router: Router
) {}
/**
* Emits the search results for the current search query.
*
* The `searchResults$` is _not_ concerned with querying, it only observes the
* `productSearchService.getResults()`
*/
protected searchResults$: Observable<
ProductSearchPage
> = this.productSearchService
.getResults()
.pipe(filter((searchResult) => Object.keys(searchResult).length > 0));
/**
* Observes the route and performs a search on each route change.
*
* Context changes, such as language and currencies are also taken
* into account, so that the search is performed again.
*/
protected searchByRouting$: Observable<
ActivatedRouterStateSnapshot
> = combineLatest([
this.routing.getRouterState().pipe(
distinctUntilChanged((x, y) => {
// router emits new value also when the anticipated `nextState` changes
// but we want to perform search only when current url changes
return x.state.url === y.state.url;
})
),
...this.siteContext,
]).pipe(
debounceTime(0),
map(([routerState, ..._context]) => (routerState as RouterState).state),
tap((state: ActivatedRouterStateSnapshot) => {
const criteria = this.getCriteriaFromRoute(
state.params,
state.queryParams
);
this.search(criteria);
})
);
/**
* This stream is used for the Product Listing and Product Facets.
*
* It not only emits search results, but also performs a search on every change
* of the route (i.e. route params or query params).
*
* When a user leaves the PLP route, the PLP component unsubscribes from this stream
* so no longer the search is performed on route change.
*/
readonly model$: Observable<ProductSearchPage> = using(
() => this.searchByRouting$.subscribe(),
() => this.searchResults$
).pipe(shareReplay({ bufferSize: 1, refCount: true }));
/**
* Expose the `SearchCriteria`. The search criteria are driven by the route parameters.
*
* This search route configuration is not yet configurable
* (see https://github.com/SAP/spartacus/issues/7191).
*/
protected getCriteriaFromRoute(
routeParams: ProductListRouteParams,
queryParams: SearchCriteria
): SearchCriteria {
return {
query: queryParams.query || this.getQueryFromRouteParams(routeParams),
pageSize: queryParams.pageSize || this.defaultPageSize,
currentPage: queryParams.currentPage,
sortCode: queryParams.sortCode,
};
}
/**
* Resolves the search query from the given `ProductListRouteParams`.
*/
protected getQueryFromRouteParams({
query,
categoryCode,
brandCode,
}: ProductListRouteParams) {
if (query) {
return query;
}
if (categoryCode) {
return this.RELEVANCE_ALLCATEGORIES + categoryCode;
}
// TODO: drop support for brands as they should be treated
// similarly as any category.
if (brandCode) {
return this.RELEVANCE_ALLCATEGORIES + brandCode;
}
}
/**
* Performs a search based on the given search criteria.
*
* The search is delegated to the `ProductSearchService`.
*/
protected search(criteria: SearchCriteria): void {
const currentPage = criteria.currentPage;
const pageSize = criteria.pageSize;
const sort = criteria.sortCode;
this.productSearchService.search(
criteria.query,
// TODO: consider dropping this complex passing of cleaned object
Object.assign(
{},
currentPage && { currentPage },
pageSize && { pageSize },
sort && { sort }
)
);
}
/**
* Get items from a given page without using navigation
*/
getPageItems(pageNumber: number): void {
this.routing
.getRouterState()
.subscribe((route) => {
const routeCriteria = this.getCriteriaFromRoute(
route.state.params,
route.state.queryParams
);
const criteria = {
...routeCriteria,
currentPage: pageNumber,
};
this.search(criteria);
})
.unsubscribe();
}
/**
* Sort the search results by the given sort code.
*/
sort(sortCode: string): void {
this.route({ sortCode });
}
/**
* Routes to the next product listing page, using the given `queryParams`. The
* `queryParams` support sorting, pagination and querying.
*
* The `queryParams` are delegated to the Angular router `NavigationExtras`.
*/
protected route(queryParams: SearchCriteria): void {
this.router.navigate([], {
queryParams,
queryParamsHandling: 'merge',
relativeTo: this.activatedRoute,
});
}
/**
* The site context is used to update the search query in case of a
* changing context. The context will typically influence the search data.
*
* We keep this private for now, as we're likely refactoring this in the next
* major version.
*/
private get siteContext(): Observable<string>[] {
// TODO: we should refactor this so that custom context will be taken
// into account automatically. Ideally, we drop the specific context
// from the constructor, and query a ContextService for all contexts.
return [this.languageService.getActive(), this.currencyService.getActive()];
}
}
I call the Sort function in plp.ts as follows.
constructor(
protected productListComponentService: CustomProductListComponentService,
) {}
sortList(sortCode: string): void {
this.productListComponentService.sort(sortCode);
}
Sort process doesn't work. Can you help me? Thank you very much in advance.
You also need to replace "ProductListComponentService" to "CustomProductListComponentService" in "ProductFacetService".
The better way to do this is:
In providers of "ProductListModule", add:
{
provide: ProductListComponentService,
useClass: CustomProductListComponentService,
},
http://hapifhir.io/doc_custom_structures.html
this article discusses a DomainResource.
There are situations however when you might want to create an entirely
custom resource type. This feature should be used only if there is no
other option, since it means you are creating a resource type that
will not be interoperable with other FHIR implementations.
I've implemented the code verbatum. (I show the classes below (with no "guts" just for brevity) (full code at the url))
/**
* This is an example of a custom resource that also uses a custom
* datatype.
*
* Note that we are extensing DomainResource for an STU3
* resource. For DSTU2 it would be BaseResource.
*/
#ResourceDef(name = "CustomResource", profile = "http://hl7.org/fhir/profiles/custom-resource")
public class CustomResource extends DomainResource {
}
and
/**
* This is an example of a custom datatype.
*
* This is an STU3 example so it extends Type and implements ICompositeType. For
* DSTU2 it would extend BaseIdentifiableElement and implement ICompositeDatatype.
*/
#DatatypeDef(name="CustomDatatype")
public class CustomDatatype extends Type implements ICompositeType {
}
And I've "registered it" in my code base:
if (null != this.fhirContext)
{
this.fhirContext.registerCustomType(CustomResource.class);
this.fhirContext.registerCustomType(CustomDatatype.class);
}
(~trying to follow the instructions from the URL above)
// Create a context. Note that we declare the custom types we'll be using
// on the context before actually using them
FhirContext ctx = FhirContext.forDstu3();
ctx.registerCustomType(CustomResource.class);
ctx.registerCustomType(CustomDatatype.class);
// Now let's create an instance of our custom resource type
// and populate it with some data
CustomResource res = new CustomResource();
// Add some values, including our custom datatype
DateType value0 = new DateType("2015-01-01");
res.getTelevision().add(value0);
CustomDatatype value1 = new CustomDatatype();
value1.setDate(new DateTimeType(new Date()));
value1.setKittens(new StringType("FOO"));
res.getTelevision().add(value1);
res.setDogs(new StringType("Some Dogs"));
// Now let's serialize our instance
String output = ctx.newXmlParser().setPrettyPrint(true).encodeResourceToString(res);
System.out.println(output);
But that looks like a console-app usage of two objects...not how to wire it into the fhir-server.
I've been trying for 3 hours now to figure out what URL to use.
some things I've tried:
http://127.0.0.1:8080/fhir/CustomResource
http://127.0.0.1:8080/fhir/profiles/custom-resource
http://127.0.0.1:8080/fhir/custom-resource
to no avail...
What is the URL?
And how do I populate the values for it?
Ok.
So the CustomResource still needs its own IResourceProvider. (thanks to daniels in the comments of the original question)
Here is a basic working example.
You'll do everything I listed in the original question AND you'll make and register an IResourceProvider for the new customresource.
new IResourceProvider
package mystuff.resourceproviders;
import org.hl7.fhir.dstu3.model.DateType;
import org.hl7.fhir.dstu3.model.IdType;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.rest.server.IResourceProvider;
import mystuff.CustomDatatype;
import mystuff.CustomResource;
import org.hl7.fhir.dstu3.model.DateTimeType;
import org.hl7.fhir.dstu3.model.StringType;
import org.hl7.fhir.instance.model.api.IBaseResource;
import java.util.Date;
public class CustomResourceProvider implements IResourceProvider {
#Override
public Class<? extends IBaseResource> getResourceType() {
return CustomResource.class;
}
/* the IdType (datatype) will be different based on STU2 or STU3. STU3 version below */
#Read()
public CustomResource getResourceById(#IdParam IdType theId) {
// Now let's create an instance of our custom resource type
// and populate it with some data
CustomResource res = new CustomResource();
res.setId(theId);
// Add some values, including our custom datatype
DateType value0 = new DateType("2015-01-01");
res.getTelevision().add(value0);
CustomDatatype value1 = new CustomDatatype();
value1.setDate(new DateTimeType(new Date()));
value1.setKittens(new StringType("FOO"));
res.getTelevision().add(value1);
res.setDogs(new StringType("Some Dogs"));
return res;
}
}
then you'll register this (as documented here):
http://hapifhir.io/doc_rest_server.html#_toc_create_a_server
instead of this:
#Override
protected void initialize() throws ServletException {
/*
* The servlet defines any number of resource providers, and
* configures itself to use them by calling
* setResourceProviders()
*/
List<IResourceProvider> resourceProviders = new ArrayList<IResourceProvider>();
resourceProviders.add(new RestfulPatientResourceProvider());
resourceProviders.add(new RestfulObservationResourceProvider());
setResourceProviders(resourceProviders);
}
you'll have something like this
#Override
protected void initialize() throws ServletException {
/*
* The servlet defines any number of resource providers, and
* configures itself to use them by calling
* setResourceProviders()
*/
List<IResourceProvider> resourceProviders = new ArrayList<IResourceProvider>();
resourceProviders.add(new CustomResourceProvider());
setResourceProviders(resourceProviders);
}
URL for testing this (most probable local development url that is)
http://127.0.0.1:8080/fhir/CustomResource/12345
and you'll get back this JSON response.
{
"resourceType": "CustomResource",
"id": "12345",
"meta": {
"profile": [
"http://hl7.org/fhir/profiles/custom-resource"
]
},
"televisionDate": [
"2015-01-01"
],
"televisionCustomDatatype": [
{
"date": "2019-01-14T11:49:44-05:00",
"kittens": "FOO"
}
],
"dogs": "Some Dogs"
}
I trying to keep original file name when using System/Models/File, I got following code to extend this model:
namespace System\Models;
class NewFile extends File { public function fromPost($uploadedFile) { if ($uploadedFile === null) { return; }
$this->file_name = $uploadedFile->getClientOriginalName();
$this->file_size = $uploadedFile->getClientSize();
$this->content_type = $uploadedFile->getMimeType();
$this->disk_name = $this->getDiskName();
/*
* getRealPath() can be empty for some environments (IIS)
*/
$realPath = empty(trim($uploadedFile->getRealPath()))
? $uploadedFile->getPath() . DIRECTORY_SEPARATOR . $uploadedFile->getFileName()
: $uploadedFile->getRealPath();
//$this->putFile($realPath, $this->disk_name);
$this->putFile($realPath, $this->file_name);
return $this;
It works with file itself, it keeps original name but problem is link to attached file is still being generated. Broke my mind but cant get this work. Can anyone elaborate how to fix it?
Oh I see it seems its try to use disk_name to generate URL
so you did well for saving an image
//$this->putFile($realPath, $this->disk_name);
$this->putFile($realPath, $this->file_name);
but you just need to replace one line .. just undo your changes and make this one change
$this->file_name = $uploadedFile->getClientOriginalName();
$this->file_size = $uploadedFile->getClientSize();
$this->content_type = $uploadedFile->getMimeType();
// $this->disk_name = $this->getDiskName();
$this->disk_name = $this->file_name;
// use same file_name for disk ^ HERE
Link logic ( for referance only ) vendor\october\rain\src\Database\Attach\File.php and modules\system\models\File.php
/**
* Returns the public address to access the file.
*/
public function getPath()
{
return $this->getPublicPath() . $this->getPartitionDirectory() . $this->disk_name;
}
/**
* Define the public address for the storage path.
*/
public function getPublicPath()
{
$uploadsPath = Config::get('cms.storage.uploads.path', '/storage/app/uploads');
if ($this->isPublic()) {
$uploadsPath .= '/public';
}
else {
$uploadsPath .= '/protected';
}
return Url::asset($uploadsPath) . '/';
}
Just make disk_name also same as file_name so when file saved on disk it will use original name and when the link is generated it also use disk_name which is original file_name
now your link and file name are synced and will be same always.
if any doubt please comment.
I'm aware of VichUpload and namers, but I have to face two different file uploads, and I need special naming conventions that I'm unable to get with the current VichUpload documentation.
First file upload is for an entity called "School", which manages every single school, and its logo. So, taking as web root '../web/files/schools/', then I'd take the school_id and then the 'logo' folder with the uploaded file name, so it could be '../web/files/schools/000001/logo.png'.
Then, the second entity is 'students' to store the photo, with a school_id foreign key from School entity. So, the resulting file name would depend on the school id, and the student id, being the root for student '../web/files/schools/<school_id>/students/<student_id>.[jpg|png]', having student_id a six zero padding on the left.
This is the section in config.yml about this (updated info):
school_image:
upload_destination: "../web/files/images/schools"
uri_prefix: "/files/images/schools"
directory_namer:
service: vich_uploader.directory_namer_subdir
options: { property: 'schoolDirectory', chars_per_dir: 6, dirs: 1 }
namer:
service: vich_uploader.namer_property
options: { property: 'idSlug' }
inject_on_load: true
delete_on_update: true
delete_on_remove: true
student_image:
upload_destination: "../web/files/images/schools"
uri_prefix: "/files/images/schools"
directory_namer:
service: vich_uploader.directory_namer_subdir
options: { property: 'userDirectory', chars_per_dir: 6, dirs: 1 }
namer:
service: vich_uploader.namer_property
options: { property: 'userImage'}
inject_on_load: true
delete_on_update: true
delete_on_remove: true
in school entity (might work with a dirty workaround):
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* #Vich\UploadableField(mapping="school_image", fileNameProperty="imageName")
*
* #Assert\Image()
*
* #var File
*/
private $imageFile;
public function getIdSlug()
{
$slug = sprintf("%06d", $this->getId());
return $slug;
}
public function getSchoolDirectory()
{
$slug = sprintf("%06d", $this->getId());
return $slug;
}
in student entity (not working, as explained below):
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* #Vich\UploadableField(mapping="student_image", fileNameProperty="imageName")
*
* #Assert\Image()
*
* #var File
*/
private $imageFile;
public function getUserDirectory()
{
$schoolDir = $this->getSchool()->getSchoolDirectory();
$dir = $schoolDir.'/students/'.sprintf("%06d", $this->getId());
return $dir;
}
public function getUserImage()
{
return $this->getUsername() . $this->getImageFile()->getExtension();
}
This setup with both "namer" and "directory_namer" seems to ignore the paths in directory_namer and use a path "<namer>/<namer>.ext" instead of "<directory_namer>/<namer>.ext". If I change the getUserImage() function and prepend the result of getUserDirectory() (i.e., the db stores "<directory_namer>/<namer>.ext" instead of just "<namer>.ext"), the "<directory_namer>" path is ignored and just "<namer>.ext" is created.
Since upload_prefix and uri_destination don't seem to handle variable data, how can I setup a namer or whatever to get this path for both cases?
BTW, I'm using Symfony 3.1 and composer hasn't allowed to update vich beyond "1.7.x-dev", according to bundled composer.json in vendor folder. If you find that it should work with this setup and the possible solution is to upgrade, I would thank to be pointed to the specific files which fix the problem, so I can manually paste whatever is wrong.
SOLUTION:
The problem was that, due to the "old" version, there was a missing directory_namer class, PropertyDirectoryNamer, with vich_uploader.namer_directory_property servicename, instead of vich_uploader.directory_namer_subdir, which was a wrong class for this purpose. I copied this class and registered it in the namer.xml file, and then I got the expected results. Now I'm going to try to mark this as solved.
You need to create custom directory namer class that implements
Vich\UploaderBundle\Naming\DirectoryNamerInterface
For example:
namespace App\Services;
use Vich\UploaderBundle\Mapping\PropertyMapping;
class SchoolDirectoryNamer implements DirectoryNamerInterface
{
public function directoryName($object, PropertyMapping $mapping): string
{
// do what you want with $object and $mapping
$dir = '';
return $dir;
}
}
Then, make it as a service.
services:
# ...
app.directory_namer.school:
class: App\Services\SchoolDirectoryNamer
Last step is config vich_uploader
vich_uploader:
# ...
mappings:
school:
upload_destination: school_image
directory_namer: app.directory_namer.school
student:
upload_destination: student_image
directory_namer: app.directory_namer.student
source : VichUploaderBundle - How To Create a Custom Directory Namer
Can I change the database config per method in a controller?
$db['default']['db_debug'] = TRUE;
The default is TRUE, while I need to make it false in a certain method to catch the error and do something else (for example show 404 page).
When I tried $this->config->load('database') it fails.
Another question :
Can I check an incorrect query and catch it to some variables rather than displaying it to users other than setting the db_debug config to FALSE?
I checked the code of system/database/DB_Driver and found that:
$this->db->db_debug = FALSE;
will work in my controller to enable/disable the debug thing on the fly.
Expanding on the answer by comenk, you can extend the database class and implement various methods by which to achieve your goal.
First, you'll need to extend the core Loader class by creating a MY_Loader.php file
class MY_Loader extends CI_Loader
{
function __construct()
{
parent::__construct();
}
/**
* Load the Standard and/or Extended Database function & Driver class
*
* #access public
* #return string
*/
function database( $params = '', $return = FALSE, $active_record = NULL )
{
$ci =& get_instance();
if (class_exists('CI_DB') AND $return == FALSE AND $active_record == NULL AND isset($ci->db) AND is_object($ci->db))
{
return FALSE;
}
$my_db = config_item('subclass_prefix').'DB';
$my_db_file = APPPATH.'core/'.$my_db.EXT;
if(file_exists($my_db_file))
{
require_once($my_db_file);
}
else
{
require_once(BASEPATH.'database/DB'.EXT);
}
// Load the DB class
$db =& DB($params, $active_record);
$my_driver = config_item('subclass_prefix').'DB_'.$db->dbdriver.'_driver';
$my_driver_file = APPPATH.'core/'.$my_driver.EXT;
if(file_exists($my_driver_file))
{
require_once($my_driver_file);
$db = new $my_driver(get_object_vars($db));
}
if ($return === TRUE)
{
return $db;
}
// Initialize the db variable. Needed to prevent
// reference errors with some configurations
$ci->db = '';
$ci->db = $db;
}
}
By implementing the above this will allow you to create a MY_DB_mysqli_driver.php whereby mysqli is replaced by whatever driver you're using in your CI database.php config.
At this point you'd add comenk's answer to MY_DB_mysqli_driver.php
function debug_on() {
return $this->db_debug = TRUE;
}
function debug_off() {
return $this->db_debug = FALSE;
}
function in_error() {
return (bool) $this->_error_number();
}
Then in your model/controller,
$this->db->debug_off();
$this->db->query('SELECT * FROM `table`');
if( $this->db->in_error() ) {
show_404();
}
$this->db->debug_on();
you must add function on system/database/DB_driver.php
function debug_on()
{
$this->db_debug = TRUE;
return TRUE;
}
function debug_off()
{
$this->db_debug = FALSE;
return FALSE;
}
after that you can simply do this command to changes at run-time
$this->db->debug_off();
$this->db->reconnect();
$this->db->db_debug = 0; // 0: off, 1: on
That worx for me...
You can look at the $GLOBALS variable to locate this generic setting.
To hide bad SQL (and other errors) from users, you need to set the php error reporting level. CodeIgniter ships in basically development mode.
Go to index.php and replace this
error_reporting(E_ALL);
with this
error_reporting(0);
This is the quick way to do it. You can also implement this using a hook, so you don't have to touch CI files. You can also add logic to that hook so that it only sets it on the production server.
For debugging SQL, you can create a class that inherits from CI_Model, then create all your model classes to extend that class. In that class, you can add code for running queries that writes the queries to the log so that you can debug them easier. This won't help if the query itself is bad, but you should be able to figure that out before you get to that point.