-
-
Save keulu/b54791e968231ed438d4cc3dec893aa0 to your computer and use it in GitHub Desktop.
<?php namespace Libraries\Core; | |
/** | |
* How to use : | |
* | |
* setup your configuration : | |
* | |
* in Config/App search for $defaultLocale and configure your $supportedLocales | |
* | |
* | |
* setup your model : | |
* | |
* <?php namespace App\Models; | |
* | |
* use Libraries\Core\MY_I18n_Model; | |
* | |
* class JobModel extends MY_I18n_Model | |
* { | |
* protected $table = 'jobs'; | |
* protected $primaryKey = 'id'; | |
* | |
* protected $i18nTable = 'jobs_i18n'; | |
* // protected $autofillEmptyFields = true; | |
* protected $i18nKeys = [ | |
* 'title' | |
* ]; | |
* | |
* [...] | |
* } | |
* | |
* Setup your database | |
* | |
* CREATE TABLE IF NOT EXISTS `jobs` ( | |
* `id` int(11) NOT NULL AUTO_INCREMENT, | |
* `title` varchar(50) NOT NULL, | |
* `created_at` datetime NOT NULL, | |
* `updated_at` datetime DEFAULT NULL, | |
* `deleted` tinyint(1) NOT NULL DEFAULT '0', | |
* `deleted_at` datetime DEFAULT NULL, | |
* PRIMARY KEY (`id`) | |
* ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; | |
* | |
* CREATE TABLE IF NOT EXISTS `jobs_i18n` ( | |
* `id` int(11) NOT NULL AUTO_INCREMENT, | |
* `jobs_id` int(11) NOT NULL, | |
* `locale` varchar(7) NOT NULL, | |
* `key` varchar(127) NOT NULL, | |
* `value` varchar(127) NOT NULL, | |
* PRIMARY KEY (`id`), | |
* UNIQUE KEY `unique fileds` (`locale`,`key`,`jobs_id`) | |
* ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; | |
* | |
* | |
* | |
* the idea is that your key title will automaticaly replaced by the good locale. | |
* | |
* afterFind : your key title will be replaced by the key title in the _i18n table | |
* afterUpdate, your key title will be updated and your _i18n reference too | |
* afterInsert, your key will be created in all $supportedLocales. | |
* if $autofillEmptyFields set to true,all key will take the new value. | |
* if set to false, only $currentLocale will be inserted, the other stay empty | |
* afterDelete. if $useSoftDelete set to true, nothing happens, if set to false, all jobs_id will be removed | |
* | |
* You can use multiple keys per jobs_id. title, description, short_description, [...] as many as you want. | |
* | |
* thats it !! :) | |
*/ | |
use CodeIgniter\Database\BaseBuilder; | |
use Config\App; | |
use CodeIgniter\Model; | |
class MY_I18n_Model extends Model | |
{ | |
/** | |
* locale detection Accept-Language Header - fallback on \Config\App::$defaultLanguage | |
* | |
* @var string | |
*/ | |
private $currentLocale; | |
/** | |
* represent the i18n table_name | |
* | |
* @var string | |
*/ | |
protected $i18nTable; | |
/** | |
* new instance of the query builder | |
* | |
* @var BaseBuilder | |
*/ | |
protected $i18nBuilder; | |
/** | |
* list of keys to translate | |
* | |
* @var array | |
*/ | |
protected $i18nKeys = []; | |
/** | |
* Autofill empty value on insert ? | |
* | |
* @var boolean | |
*/ | |
protected $autofillEmptyFields = false; | |
public function __construct() | |
{ | |
parent::__construct(); | |
$this->searchI18nTable(); | |
} | |
/** | |
* Looking for an existing table | |
*/ | |
protected function searchI18nTable() | |
{ | |
if ($this->db->tableExists($this->i18nTable)) { | |
$this->currentLocale = service('request')->getLocale(); | |
$this->i18nBuilder = new BaseBuilder($this->i18nTable, $this->db); | |
$this->afterFind[] = 'i18nAfterFind'; | |
$this->afterInsert[] = 'i18nAfterInsert'; | |
$this->afterUpdate[] = 'i18nAfterUpdate'; | |
$this->afterDelete[] = 'i18nAfterDelete'; | |
} | |
} | |
/** | |
* after Selecting data if single record or multiples. | |
* | |
* @param array $vars The resulting row of data | |
* | |
* @return array The resulting row of data. | |
*/ | |
protected function i18nAfterFind($vars) | |
{ | |
$data_tmp = null; | |
if (!is_null($vars['data'])) { | |
if (isset($vars['id'])) { | |
$data_tmp = $this->joinI18n($vars['data']); | |
} | |
else | |
{ | |
$data_tmp = []; | |
foreach ($vars['data'] as $data) | |
{ | |
$data_tmp[] = $this->joinI18n($data); | |
} | |
} | |
} | |
$vars['data'] = $data_tmp; | |
return $vars; | |
} | |
/** | |
* after Selecting, data is parsed. | |
* | |
* @param array $data The resulting row of data | |
* | |
* @return array The resulting row of data. | |
*/ | |
protected function joinI18n($data) | |
{ | |
$i18n_query = $this->i18nBuilder | |
->where('locale', $this->currentLocale) | |
->where($this->table . '_id', $data['id']) | |
->get(); | |
foreach ($i18n_query->getResult() as $row) | |
{ | |
$data[$row->key] = $row->value; | |
} | |
return $data; | |
} | |
/** | |
* after Delete | |
* | |
* @param array $vars The resulting row of data | |
* | |
* @return array The resulting row of data. | |
*/ | |
protected function i18nAfterDelete($vars) | |
{ | |
if ($vars['purge'] === true) { | |
$this->i18nBuilder | |
->where($this->table . '_id', $vars['id']) | |
->delete(); | |
} | |
return $vars; | |
} | |
/** | |
* after Update | |
* | |
* @param array $vars The resulting row of data | |
* | |
* @return array The resulting row of data. | |
*/ | |
protected function i18nAfterUpdate($vars) | |
{ | |
// foreach keys | |
foreach($vars['data'] as $k => $v) | |
{ | |
// If my currentKey is in my $i18nKeys | |
if (in_array($k, $this->i18nKeys)) { | |
$this->i18nBuilder | |
->where('locale', $this->currentLocale) | |
->where($this->table . '_id', $vars['id']) | |
->where('key', $k) | |
->update(['value' => $v]); | |
} | |
} | |
return $vars; | |
} | |
/** | |
* after Insert | |
* | |
* @param array $vars The resulting row of data | |
* | |
* @return array The resulting row of data. | |
*/ | |
protected function i18nAfterInsert($vars) | |
{ | |
$app_config = new \Config\App(); | |
$relatedId = $this->db->insertID(); | |
// For all keys | |
foreach($vars['data'] as $k => $v) | |
{ | |
// If my currentKey is in my $i18nKeys | |
if (in_array($k, $this->i18nKeys)) | |
{ | |
// And for each locales | |
foreach($app_config->supportedLocales as $locale) | |
{ | |
// if autoFill == true | |
// Set very i18n keys with the same data | |
if ($this->autofillEmptyFields) | |
{ | |
$data = [ | |
$this->table . '_id' => $relatedId, | |
'locale' => $locale, | |
'key' => $k, | |
'value' => $v, | |
]; | |
} | |
// if autofill = false | |
// fill current key and let the others empty | |
else | |
{ | |
$data = [ | |
$this->table . '_id' => $relatedId, | |
'locale' => $locale, | |
'key' => $k, | |
]; | |
// select good locale | |
if ($locale == $this->currentLocale) | |
{ | |
$data['value'] = $v; | |
} | |
// other fields are empty | |
else | |
{ | |
$data['value'] = ''; | |
} | |
} | |
// insert | |
$this->i18nBuilder->insert($data); | |
} | |
} | |
} | |
return $vars; | |
} | |
} |
this is nice, but i think it would be better been a trait used in other model class
Yes of course a trait is possible, like the responseTrait witch help to handle REST HTTP Response.
Don't know what is better. Why using a Trait is better than extend a class ?
possible to use multiple Trait instead of 1 extend ?
Yes, multiple traits are fine:
https://www.php.net/manual/en/language.oop5.traits.php#language.oop5.traits.multiple
In general I decide on trait versus extension based on a) whether the functions are likely to be "replaced" and b) whether the developer using the functions will likely be extending other classes and interfaces, which can make mixing confusing or buggy.
From best I can tell in your case I'd agree with @chistel that this seems like a good use of a trait.
this is nice, but i think it would be better been a trait used in other model class