Doctrine is converting string to hex value - utf-8

I am converting one database to another database through a script.
While running the script I am getting the following error:
SQLSTATE[HY000]: General error: 1366 Incorrect string value: '\xBFbangl...' for column 'country' at row 1
An exception is thrown where it shows that it tries to set country as "\xcf\xbb\xbf\x62\x61\x6e\x67\x6c\x61\x64\x65\x73\x68".
When I var_dump the value, it just shows as "Bangladesh".
Is there something I have to adjust in my php code?
I have tried this, but phpmyadmin is throwing an #1064 error stating a syntax error in the query.
UPDATE
The scripts is a command in Symfony3:
<?php
namespace My\Bundle\Command;
use My\AccommodationBundle\Entity\Visit;
use My\NewAccommodationBundleV2\Entity\Visit as Visit2;
use My\OtherBundle\Entity\Person;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class VisitConvertToNewFormatCommand extends ContainerAwareCommand
{
private $em;
protected function configure()
{
$this
->setName('accommodation:visit:convert')
->setDescription("Converting old structure to new structure'")
;
}
protected function getTimeStamp() {
$currentTime = new \DateTime('now');
return '['.$currentTime->format('Y-m-d H:i:s').'] ';
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln($this->getTimeStamp().$this->getDescription());
$this->em = $this->getContainer()->get('doctrine')->getManager();
$visits = $this->em->getRepository('MyOldAccommodationBundle:Visit')->findAll();
foreach ($visits as $visit) {
$visit2 = new Visit2();
$visit2->setArrivalDate($visit->getArrivalDate());
$visit2->setArrivalStatus($visit->getArrivalStatus());
$visit2->setArrivalTime($visit->getArrivalTime());
$visit2->setBookingType($visit->getBookingType());
$visit2->setCountry($visit->getCountry()); // <----
...
$this->em->persist($visit2);
$user = $visit->getUser();
if ($user != null) {
$person = new Person();
...
$person->setFirstName(trim(ucfirst(strtolower($user->getFirstName()))));
$person->setLastName(trim(ucfirst(strtolower($user->getLastName()))));
$person->setEmail(preg_replace('/\s+/', '', $user->getEmail()));
...
$this->em->persist($person);
}
}
}
}

\x62\x61\x6e\x67\x6c\x61\x64\x65\x73\x68 is Bangladesh; the \xcf\xbb\xbf before it makes no sense. In latin1 it is Ï»¿. It does not validly convert to utf8. CFBB is ϻ (GREEK SMALL LETTER SAN), but then bf is broken utf8.
I suggest it is coming from the source of the data.
var_dump probably showed nothing because of what device you were displaying it on.

Ok after days of trying this did the trick:
$country = iconv("UTF-8", "ISO-8859-1//IGNORE", $country);
I have no idea why it went wrong in the first place. if anybody knows, please share.

Related

problem with convert like function in oracle / doctrine

In oracle there is a "convert" function to convert from one encoding to other. I wrote custom function for doctrine (converting column from ISO-8859-2 to UTF-8:
<?php
namespace AppBundle\DQL;
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\Lexer;
class ConvertFunction extends FunctionNode
{
public $stringPrimary;
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
{
return $sqlWalker->getConnection()->getDatabasePlatform()->getUpperExpression(
"CONVERT(".$sqlWalker->walkSimpleArithmeticExpression($this->stringPrimary).", 'EE8ISO8859P2', 'UTF8')"
);
}
public function parse(\Doctrine\ORM\Query\Parser $parser)
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->stringPrimary = $parser->StringPrimary();
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
}
when I use it, it doesn't search anything, but when I run sql in DB it works.
Does symfony / doctrine change a variable encoding ?
edit:
(my custom function is declared as convertToISO8859): When I run (in symfony):
select * from tables where convertToISO8859(name) = 'Jesień'
It return nothing, but in symfony profiler it shows properly sql:
select * from tables where upper(convert(name), 'EE8ISO8859P2', 'UTF8') = 'Jesień'

Magento2: Argument 1 [...] must be an instance of Magento\Framework\App\Helper\Context

First of all, I'm quite new to Magento 2, but I've used Magento 1.x for some time.
I've read a lot about how to solve DI-related problems, but I'm stuck on this one:
Exception #0 (Exception): Recoverable Error: Argument 1 passed to Cefar\AO\Helper\Ao::__construct() must be an instance of Magento\Framework\App\Helper\Context, instance of Magento\Framework\ObjectManager\ObjectManager given, called in .../vendor/magento/framework/ObjectManager/Factory/AbstractFactory.php on line 93 and defined in .../Cefar/AO/Helper/Ao.php on line 11
Many other answers have suggested deleting the var/di and var/generation folders, sometimes var/cache also. While this solves the problem, it occurs again once bin/magento setup:di:compile is run, which means the code cannot be used in a production environment.
I've checked that the Ao class does not instantiate any objects. It also doesn't try to re-make any objects that could be provided by the context given. Here's the code:
namespace Cefar\AO\Helper;
class Ao extends \Magento\Framework\App\Helper\AbstractHelper
{
const DEFAULT_GRID_COLS = 4;
protected $_session;
public function __construct(
\Magento\Framework\App\Helper\Context $context,
\Magento\Customer\Model\Session $session
)
{
parent::__construct($context);
$this->_session = $session;
}
public function getConfig($path)
{
return $this->scopeConfig->getValue($path);
}
public function isActive($url = null, $print = true) {
$active = ($url && strstr($_SERVER['REQUEST_URI'], $url) !== false);
if ($active && $print) {
echo "active";
} else {
return $active;
}
}
public function isLoggedIn()
{
return $this->_session->isLoggedIn();
}
public function limitWords($text = '', $limit = 10, $showDots = true)
{
$words = explode(' ', $text);
$limited = array_slice($words, 0, $limit);
$newText = implode(' ', $limited);
if (count($words) > $limit && $showDots) {
$newText .= '...';
}
return $newText;
}
public function getCurrentGrid()
{
return ($this->_getRequest()->getParam('grid'))
? $this->_getRequest()->getParam('grid')
: self::DEFAULT_GRID_COLS;
}
}
There's nothing particularly special here. I'm confused as to how this is even happening; every other defined class in the extension is getting its DI parameters correctly. Why is the ObjectManager apparatus providing an unwanted argument? The relevant call is given in the error report as:
.../vendor/magento/framework/ObjectManager/Factory/AbstractFactory.php(93): Cefar\AO\Helper\Ao->__construct(Object(Magento\Framework\ObjectManager\ObjectManager))
So it isn't even providing two arguments!
I've also read about providing type hints in a di.xml, but it doesn't seem to be relevant here as both types are part of the Magento libraries? I note that there is an entry for Magento\Framework\App\Helper\Context but not one for Magento\Customer\Model\Session... but that there are framework classes that use ID to import Magento\Customer\Model\Session already which work.
Long story short, this was because of a typo.
Sometimes when the helper was being included, it was being referred to as Cefar\AO\Helper\Ao, and other times, Cefar\AO\Helper\AO. Essentially, the ObjectManager was resolving both of these references to the same class, but it only had type hints for one of the names so it didn't know what to provide to the incorrect one.
A little help would have been nice, Magento! Maybe an error report that the requested class wasn't found? Still, at least this is finally over with.

How to create a slug from title and subtitle in Laravel 5

I want to create a slug. it should be a concatenation of title and subtitle.The following is my code and it's not working, i don't know where i went wrong?
public function setTitleAttribute($value)
{
$this->attributes['main_title'] = ucfirst($value);
$this->attributes['sub_title'] = $value;
if (! $this->exists) {
$this->attributes['slug'] = str_slug($this->attributes['main_title'].$this->attributes['sub_title']);
}
}
I need slug as a combination of main_title+sub_title
public function to_slug ($string) {
$table = array(
'Š'=>'S', 'ı'=>'i', 'ğ'=>'g', 'ü'=>'u', 'ş'=>'s', 'ö'=>'o', 'ç'=>'c', 'Ğ'=>'G', 'Ü'=>'U', 'Ş'=>'S',
'İ'=>'I', 'Ö'=>'O', 'Ç'=>'C',
'š'=>'s', 'Đ'=>'Dj', 'đ'=>'dj', 'Ž'=>'Z', 'ž'=>'z', 'Č'=>'C', 'č'=>'c', 'Ć'=>'C', 'ć'=>'c',
'À'=>'A', 'Á'=>'A', 'Â'=>'A', 'Ã'=>'A', 'Ä'=>'A', 'Å'=>'A', 'Æ'=>'A', 'Ç'=>'C', 'È'=>'E', 'É'=>'E',
'Ê'=>'E', 'Ë'=>'E', 'Ì'=>'I', 'Í'=>'I', 'Î'=>'I', 'Ï'=>'I', 'Ñ'=>'N', 'Ò'=>'O', 'Ó'=>'O', 'Ô'=>'O',
'Õ'=>'O', 'Ö'=>'O', 'Ø'=>'O', 'Ù'=>'U', 'Ú'=>'U', 'Û'=>'U', 'Ü'=>'U', 'Ý'=>'Y', 'Þ'=>'B', 'ß'=>'Ss',
'à'=>'a', 'á'=>'a', 'â'=>'a', 'ã'=>'a', 'ä'=>'a', 'å'=>'a', 'æ'=>'a', 'ç'=>'c', 'è'=>'e', 'é'=>'e',
'ê'=>'e', 'ë'=>'e', 'ì'=>'i', 'í'=>'i', 'î'=>'i', 'ï'=>'i', 'ð'=>'o', 'ñ'=>'n', 'ò'=>'o', 'ó'=>'o',
'ô'=>'o', 'õ'=>'o', 'ö'=>'o', 'ø'=>'o', 'ù'=>'u', 'ú'=>'u', 'û'=>'u', 'ý'=>'y', 'ý'=>'y', 'þ'=>'b',
'ÿ'=>'y', 'Ŕ'=>'R', 'ŕ'=>'r',
);
return preg_replace('/[^A-Za-z0-9-]+/', '-', strtr($string, $table) );
}
I'm using this code and its working for me.
It is also good for utf-8.
You can use a laravel package:
https://github.com/cviebrock/eloquent-sluggable
Or I use JavaScript when I sent the form:
https://github.com/madflow/jquery-slugify
I have replicated the exact condition like yours passing static data and its working perfectly in my machine.. try below solution.. do some dd and see whats the combination of the main_title and sub_title is resulting. Also check by removing that if condition once.
$this->attributes['main_title'] = ucfirst($value) . " ";
$this->attributes['sub_title'] = $value;
$slugToUse = $this->attributes['main_title'] . $this->attributes['sub_title'];
if (! $this->exists) {
$this->attributes['slug'] = str_slug($slugToUse);
}
}

Dynamically switching the error message on validation?

With the new validator object - is it possible to replace the validation error inside the validation rule triggered? to not only return the static error message but maybe some dynamically genereted one?
public function validateLength($data) {
...
$length = mb_strlen($data['name']);
$this->validator()->getField('name')->setRule('validateLength', array('message' => $length . 'chars'));
...
}
does not work, of course (too late I guess)
I want to actually return the lenght of the string (you used 111 chars from 100 allowed) for example - but for this I would need to be able to replace the message from inside the (custom) validation method
$this->validate['name']['validateLength']['message'] = $length . 'chars';
also never worked so far. it would always return the previous (static) error message from the $validate array
public function customValidator($data) {
....
if ($validates) {
return true;
} else {
return 'my new error message';
}
}
The following snippet should do the trick:
public function validateLength($data) {
...
$length = mb_strlen($data['name']);
$this->validator()->getField('name')->getRule('validateLength')->message = $length . 'chars';
...
}

Codeigniter change database config at runtime

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.

Resources