Use existing MySQL database in CodeIgniter - mysql

In my PHP websites I’m using SiteTranslator script for a website translated into 30 languages. Each translation is stored in its own table (text_en, text_de...) and each table has 3 columns (textKey, textValue, lastUpdate).
Now I would like to use that database in my CodeIgniter application.
What would be the best way to do it?

You could use multiple databases as suggested, you would still need to setup your app language files
{read more in the user guide}
Based on the first uri segment you could try something like this.
Adding routes
$route['en|fr|gr/test'] = 'test';
First segment checks for en OR fr OR whatever else.
Then the Main Controller catches the first segment before the test controller is initialized and the db(object) && app(language) files are set
www.site.com/en/test => load english language file(application/language/english/mylanguage) and db
www.site.com/fr/test => load french language file(application/language/french/mylanguage) and db ...and so on
Main Controller
class MY_Controller extends CI_Controller{
protected $lang, $db;
public function __construct(){
parent::__construct();
$this->set_language();
}
protected function set_language(){
switch($this->uri->segment(1))
{
case 'en':
$this->lang = $this->lang->load('mylanguage', 'english');
$this->db = $this->load->database('en', TRUE);
break;
case 'fr':
$this->lang = $this->lang->load('mylanguage', 'french');
$this->db = $this->load->database('fr', TRUE);
break;
default:
$this->lang = $this->lang->load('mylanguage', 'english');
$this->db = $this->load->database('en', TRUE);
break;
}
}
}

Related

Need to change timezone dynamically for existing project

There is an existing project only for one country. But for now, it should be used for multiple countries. So I need some place to change timezones. I decided to update & insert in only London/Sydney timezone. I need to change the timezone for all select queries. I just tried with middlewares, but I could not achieve it. Please give your suggestions.
Linux server, MySQL, Laravel, Vagrant
namespace App\Http\v2018_06_12\Middleware;
use App;
use App\Order;
use Closure;
class LocaleMiddleware
{
public function handle($request, Closure $next, $guard = null)
{
$locale = ($request->hasHeader('locale')) ? $request->header('locale') : 'uk';
$timezone = env('APP_TIMEZONE');
if ('aus' == $locale) {
$timezone = 'Australia/Sydney';
}
config(['app.timezone' => $timezone]);
date_default_timezone_set($timezone);
print_r(Order::select('delivery_time')->orderBy('id', 'DESC')->first()->toArray());
return $next($request);
}
}

Table name having additional underscores added

I have an API that grabs data from a table, serialises the data and then sends back via the service. The code is written using CakePHP using MySQL.
When I pass in the table name (such as RX_Scaled), an error is being returned that the table r_x_scaled can't be found (which don't surprise me, the table name in the database is rx_scaled).
My Model/Table for rx_scaled is defined like this
class rx_scaleds extends Table
{
public function initialize(array $config)
{
parent::initialize($config);
$this->table('rx_scaled');
}
With the Model/Entity
class rx_scaled extends Entity
{
}
My service API is set like this within the APIController.php file
public function getData($tablename, $id="", $filter = "-", $order = "-", $take = 0)
{
$the_table = $tablename;
$this->autoRender = false;
$table = TableRegistry::get($tablename);
$data = null;
switch (strtolower($the_table))
{
case "rx_scaled":
$data = $table->find();
echo $data;
break;
}
(this is truncated)
The odd thing is that this error does not occur in all tables.
I'm obviously not doing something correctly, but I'm not sure what
You named your table object rx_scaleds but then you pass RX_Scaled to the getData action
cake try not finding a Table Object named RX_Scaled try to inflect the name of the mysql table: so using cake's conventions RX_Scaled is mapped to r_x_scaled
So what can you do?
Use cake conventions
Name you table RxScaledsTable
class RxScaledsTable extends Table
Name you entity RxScaled
class RxScaled extends Entity
and pass the string 'RxScaled' to your action

Write database queries in Magento custom module

I created a custom module in my Magento. This is working good. My module's name is mymodule.
Mymodule.php
class Myshop_Mymodule_Block_Mymodule extends Mage_Core_Block_Template
{
public function myfunction()
{
return "Hello User";
}
}
The path of the Mymodule.php file is C:\wamp\www\magento\app\code\local\Myshop\Mymodule\Block.
Now I want to display some data from database. For example I would like to display the admin's email id. How can I display this??
I tried like this.
$read = Mage::getSingleton('core/resource')->getConnection('core_read');
//database write adapter
$write = Mage::getSingleton('core/resource')->getConnection('core_write');
$result = $read->fetchAll("select email from admin_user where user_id= 1");
var_dump($result);
I write these lines in Mymodule.php inside myfunction. But nothing displayed(display only "Hello User").
So my question is how to display or write database queries in magento custom module.
Please someone help me..Any help is really appreciable..
We generally avoid using adapters when magento by default provides models for the basic tables. In your case, you can fetch the admin details using following :
<?php
$userDetails = Mage::getModel('admin/user')->load(1);
//where 1 is your admin user id
echo $userDetails->getEmail();
?>
Hence, your function can be modified as :
<?php
class Myshop_Mymodule_Block_Mymodule extends Mage_Core_Block_Template
{
public function myfunction()
{
$userDetails = Mage::getModel('admin/user')->load(1);
return $userDetails->getEmail();
}
}
You can get data from database in magento as
$collection = Mage::getModel("mumodule/mymodule")->getCollection();
foreach($collection as $data){
..Your Code ..
}

How to use database specific functions in Laravel Eloquent ORM for modular usage

Im developing a project which uses ORM to make project run on every database system as much as we can.
Project uses postgresql right now. Im wondering how to use database specific functions without losing ORM modularity.
For example:
I have to use "extract" function for one query like so;
DELETE FROM tokens AS t WHERE (extract(epoch from t.created_at) + t.expires) < extract(epoch from NOW())
If i want to use model class to achieve this. Soon or late i need to write extract function where clause in raw format
Tokens::whereRaw('(extract(epoch from t.created_at) + t.expires) < extract(epoch from NOW())')->get();
If i use query builder
DB::table('tokens')->whereRaw('(extract(epoch from t.created_at) + t.expires) < extract(epoch from NOW())')->select()->get();
Same things happens
I need something like when i use postgresql ORM need to use EXTRACT() function or when i use mysql ORM need to use UNIX_TIMESTAMP() function
What the ways i can use to achieve this ?
This could go in the respective drivers, but Taylor Otwell's view on driver-specific functions is, that you simply should use raw statements, just like you do.
However in Eloquent you can pretty easily do it yourself:
// BaseModel / trait / builder macro or whatever you like
public function scopeWhereUnix($query, $col, $operator = null, $value = null)
{
if (func_num_args() == 3)
{
list($value, $operator) = array($operator, '=');
}
switch (class_basename($query->getQuery()->getConnection()))
{
case 'MySqlConnection':
$col = DB::raw("unix_timestamp({$col})");
break;
case 'PostgresConnection':
$col = DB::raw("extract(epoch from {$col})");
break;
}
$query->where($col, $operator, $value);
}
Now you can do this:
Tokens::whereUnix('created_at', 'value')->toSql();
// select * from tokens where unix_timestamp(created_at) = 'value'
// or
// select * from tokens where extract(epoch from created_at) = 'value'
You have a bit more complex condition, but you still can achieve that with a little bit of hack:
Tokens::whereUnix(DB::raw('created_at) + (expires', '<', time())->toSql();
// select * from tokens where unix_timestamp(created_at) + (expires) < 12345678
// or
// select * from tokens where extract(epoch from created_at) + (expires) < 12345678
Unfortunately Query\Builder (DB::table(..)) is not that easy to extend - in fact it is not extendable at all, so you would need to swap it with your own Builder class, what is rather cumbersome.
Take this logic out of the models.
Create a repository for Postgres, let's call it PostgresTokenRepository. The constructor of this repository should look like...
<?php
class PostgresTokenRepository implements TokenRepositoryInterface
{
protected $token;
public function __construct(Token $token)
{
$this->token = $token;
}
public function getTokens()
{
return $this->token->whereRaw('(extract(epoch from t.created_at) + t.expires) < extract(epoch from NOW())')->get();
}
}
And you will need an interface... TokenRepositoryInterface
interface TokenRepositoryInterface
{
public function getTokens();
}
Now you should be all set as far as the repository goes. If you need to do a MySQL implementation, just create a MysqlTokenRepository which will look similar except the getTokens() function would use UNIX_TIMESTAMP().
Now you need to tell Laravel that when you are looking for an implementation of TokenRepositoryInterface, it should return PostgresTokenRepository. For that, we will need to create a service provider.
<?php
class UserServiceProvider extends \Illuminate\Support\ServiceProvider
{
public function register()
{
$this->app->bind('TokenRepositoryInterface', 'PostgresTokenRepository');
}
}
And now the only thing left to do is add this Service Provider to the service providers array in config/app.php.
Now whenever you need this repository in your controllers, you can have them automatically injected. Here is an example...
class TokenController extends BaseController
{
protected $token;
public function __construct(TokenRepositoryInterface $token)
{
$this->token = $token;
}
public function index()
{
$tokens = $this->token->getTokens();
return View::make('token.index')->with('tokens', $tokens);
}
}
The purpose for doing it this way is when you want to start using the MySQL implementation, all you have to do is modify the service provider to return MysqlTokenRepository instead of PostgresTokenRepository. Or if you want to write a new implementation all together, it will all be possible without having to change production code. If something doesn't work, simply change that one line back to PostgresTokenRepository.
One other benefit that sold me is this gives you the capability of keeping your models and controllers very light and very testable.
I ended up creating a global scope. Created a trait like ExpiresWithTimestampsTrait that contains the logic for whereExpires scope. The scope does adding where clause that specific to database driver.
public function scopeWhereExpired($query)
{
// Eloquent class is my helper for getting connection type based on the #jarek's answer
$type = Eloquent::getConnectionType($this);
switch ($type) {
case Eloquent::CONNECTION_POSTGRESS:
return $query->whereRaw("(round(extract(epoch from (created_at)) + expires)) < round(extract(epoch from LOCALTIMESTAMP))");
break;
default:
break;
}
}
So i just need to use that trait on the model. I need to add just an "case" clause to whereExpires scope for support mysql with where clause in the future when i start using mysql
Thanks to everybody!

Symfony2 execute SQL file in Doctrine Fixtures Load

I'm migrating an old web app based on SQL Server and ASP to Symfony2 and MySQL. I made some queries and export old data to individual SQL files.
How can I execute thoses files in my fixtures, when I run the command
$php app/console doctrine:fixtures:load
Now I have some fixtures that works directly with Doctrine ORM and entities, but I have a lot of data to import.
I find a good solution. I didn't find an exec method in class ObjectManager, so... this work very well for me.
public function load(ObjectManager $manager)
{
// Bundle to manage file and directories
$finder = new Finder();
$finder->in('web/sql');
$finder->name('categories.sql');
foreach( $finder as $file ){
$content = $file->getContents();
$stmt = $this->container->get('doctrine.orm.entity_manager')->getConnection()->prepare($content);
$stmt->execute();
}
}
In this solution your fixture class has to implement the ContainerAwareInterface with the method
public function setContainer( ContainerInterface $container = null )
{
$this->container = $container;
}
You can load the file contents as a string, and execute native SQL using the EntityManager:
class SQLFixtures extends AbstractFixture implements OrderedFixtureInterface
{
$filename = '/path/to/sql/file.sql';
public function load(ObjectManager $manager) {
$sql = file_get_contents($filename); // Read file contents
$manager->getConnection()->exec($sql); // Execute native SQL
$manager->flush();
}
public function getOrder() {
return 99; // Order in which this fixture will be executed
}
}
Answer for Zend Framework 2.5.3 using Doctrine Data-Fixtures.
Not sure if this applies to the given answers, but they are trying a bit too hard. If you inspect the given $manager object, you'll find that it already is the EntityManager (of interface ObjectManager) (at least, in ZF2). As such you're able to get the Connection directly and it's possible to execute without using $this->container->get('doctrine.orm.entity_manager')
Below a snippet which I use for creating the first user "system", with a createdBy FK reference to itself.
public function load(ObjectManager $manager)
{
$sql = 'INSERT INTO users (
id, username, email, display_name, `password`, created_by)
VALUES (:id, :username, :email, :display_name, :password, :created_by)';
$password = $this->createSuperDuperEncryptedPassword();
// $manager === `EntityManager|ObjectManager`, `->getConnection()` is available
$stmt = $manager->getConnection()->prepare($sql);
$stmt->bindValue(':id', 1);
$stmt->bindValue(':username', 'system');
$stmt->bindValue(':email', 'system#system.test');
$stmt->bindValue(':display_name', 'system');
$stmt->bindValue(':password', password );
$stmt->bindValue(':created_by', 1); // Self reference
$stmt->execute();
}