Yii2 - Connect to database inside Controller Action - mysql

Greetings,
Facts:
Database named -> acastro
Table called -> contacto
Fields in table are -> id, nome, email
I making an Yii2 application, and need to connect a highcharts chart to a table field in my database.
How can i inside an action called actionAdmin connect to my database and then count the number of id's in my Contacto table stored inside acastro database.
In the old Yii1.xx i used to establish connection this way:
public function actionAdmin() {
$sql = Yii::app()->db->createCommand('
SELECT count(*) as total
FROM contacto
')->queryAll();
$total = array();
for ($i = 0; $i < sizeof($sql); $i++){
$total[] = (int) $sql[$i]["total"];
}
$this->render('admin', array('total' => $total));
}
}
The problem is that this syntax no longer works in Yii2, and i've tried the sintaxe explained in Yii2 api guide but it always give's me error of undefined variable. Here is the code that i'm using to connect acording to Yii2 api guide:
use yii\db\Command;
$total = $connection->createCommand('SELECT count (*) FROM contacto')->queryAll();
What am i doing wrong ? Any solutions ?
Many thanks in advance.

I am not very sure that it will solve ur problem.
But in yii2 this the syntax
use app\models\Contacto; //look your Contacto Model namespace
$query = (new Query())->from('contacto');
$count = $query->count('column_name');
I hope this will help

The easiest syntax in Yii2 is:
$count=(new \yii\db\Query)->from('TBL_NAME')->count('*');
It just returns the count. For example: 500

Related

Create a record into many2many table using Web service API in odoo 8

I need to create a record in mail_vote table(many2many) with fields message_id and user_id Using Web service API. I found a document here: https://www.odoo.com/documentation/8.0/reference/orm.html#openerp.models.Model.write . But i don't know how to use that in my code. Any solution please.
Below i am posting the code snippet for associating (6,0,[ids])] the Many2many record in product.attribute.line.
In Php here i have used ripcord for this task.
$existing_prodid = 59;
$existing_attribute_id = 2;
$existing_value_id = 4;
$product_attribute_line = $models->execute($db, $uid, $password,
'product.attribute.line','create',
array('product_tmpl_id' => $existing_prodid;,
'attribute_id'=>$existing_attribute_id,
'value_ids'=>array(array(6,0,array($existing_value_id)))
))
Here the product.attribute.line have have Many2many relation with product.attribute.value
So this is how i associated a records for value_ids ['value_ids'=>array(array(6,0,array($existing_value_id)))].
In python i have used xmlrpclib for this task.
attibute_line = models.execute_kw(dbname, uid, password,
'product.attribute.line', 'create',
[{'product_tmpl_id':59,'attribute_id':2,'value_ids':[(6,0,[4])]}] )
I hope this may help in your case

I'm getting the wrong data when using doctrine in symfony

I'm trying to build a SQL query using doctrine. Here's my code snippet:
/**
* #Route("/db", name="user_skill_testing")
*/
public function dbTest()
{
//all skills for user
$userName = "Jelle";
$user = $this->getDoctrine()
->getRepository('AppBundle:User')
->findOneByFirstname($userName);
echo "userId: ".$user->getId()."<br />";
$userSkills = $this->getDoctrine()
->getRepository('AppBundle:Userskill')->findById($user->getId());
$proficiencies = array();
foreach ($userSkills as $userSkill) {
array_push($proficiencies, $userSkill);
echo $userSkill->getId();
echo "-";
echo $userSkill->getProficiency()->getId();
echo "<br />";
}
var_dump($userSkills);
$html = "<html><body>".$user->getFirstname()."<br /><br />"."</body></html>";
return new Response($html);
}
It returns the following webpage(screenshot):
When I look at the queries it ran...:
...and rerun them...:
...I get a very different result. :(
I have no idea why, can anyone help me out?
thank you!
Edit: using this code to build the query reproduces the same result.
The problem lies with your PK on UserSkill. When doctrine Hydrates, it will assume entities with the same primary key, are the same entity, ignoring rows with the same PK if one has already been hydrated.
Since your Userskill::$id is not unique, only the first one will be hydrated, subsequent rows with the same id, will get a reference to the same entity.
To solve this, you need to create a compound key, consisting of the id and the proficiencyId.
In you use-case though, this will make things unpractical. So I would just replace your manual id on Userskill with an actual one-to-many relation from Userto Userskill...
Having MySql generate the many-to-many relationship helped doctrine generate the correct entities.

How is slug being created in Sylius?

I want to create new product in Sylius. I just tested:
$user = $this->getUser();
$repository = $this->container->get('sylius.repository.product');
$manager = $this->container->get('sylius.manager.product'); // Alias for appropriate doctrine manager service.
$product = $repository->createNew();
$product
->setName('Test product')
->setDescription('Des Product 2')
->setPrice(90)
->setUser($user)
;
$manager->persist($product);
$manager->flush(); // Save changes in database.
But it trigger an exception of slug. When I try $product->getSlug(), that returns empty. I don't know how does slug created in Sylius and where is the code for that?
It's a gedmo:slug, check ProductBundle\Resources\config\doctrine\model\ProductTranslation.orm.xml
Make sure you have a default locale configured and add this to your code:
$product->setCurrentLocale($locale);
$product->setFallbackLocale($locale);
Products are translatable, and I think this is what you're missing.
Check how a product is created in Sylius\Bundle\FixturesBundle\DataFixtures\ORM\LoadProductsData line 404.

Import of 50K+ Records in MySQL Gives General error: 1390 Prepared statement contains too many placeholders

Has anyone ever come across this error: General error: 1390 Prepared statement contains too many placeholders
I just did an import via SequelPro of over 50,000 records and now when I go to view these records in my view (Laravel 4) I get General error: 1390 Prepared statement contains too many placeholders.
The below index() method in my AdminNotesController.php file is what is generating the query and rendering the view.
public function index()
{
$created_at_value = Input::get('created_at_value');
$note_types_value = Input::get('note_types_value');
$contact_names_value = Input::get('contact_names_value');
$user_names_value = Input::get('user_names_value');
$account_managers_value = Input::get('account_managers_value');
if (is_null($created_at_value)) $created_at_value = DB::table('notes')->lists('created_at');
if (is_null($note_types_value)) $note_types_value = DB::table('note_types')->lists('type');
if (is_null($contact_names_value)) $contact_names_value = DB::table('contacts')->select(DB::raw('CONCAT(first_name," ",last_name) as cname'))->lists('cname');
if (is_null($user_names_value)) $user_names_value = DB::table('users')->select(DB::raw('CONCAT(first_name," ",last_name) as uname'))->lists('uname');
// In the view, there is a dropdown box, that allows the user to select the amount of records to show per page. Retrieve that value or set a default.
$perPage = Input::get('perPage', 10);
// This code retrieves the order from the session that has been selected by the user by clicking on a table column title. The value is placed in the session via the getOrder() method and is used later in the Eloquent query and joins.
$order = Session::get('account.order', 'company_name.asc');
$order = explode('.', $order);
$notes_query = Note::leftJoin('note_types', 'note_types.id', '=', 'notes.note_type_id')
->leftJoin('users', 'users.id', '=', 'notes.user_id')
->leftJoin('contacts', 'contacts.id', '=', 'notes.contact_id')
->orderBy($order[0], $order[1])
->select(array('notes.*', DB::raw('notes.id as nid')));
if (!empty($created_at_value)) $notes_query = $notes_query->whereIn('notes.created_at', $created_at_value);
$notes = $notes_query->whereIn('note_types.type', $note_types_value)
->whereIn(DB::raw('CONCAT(contacts.first_name," ",contacts.last_name)'), $contact_names_value)
->whereIn(DB::raw('CONCAT(users.first_name," ",users.last_name)'), $user_names_value)
->paginate($perPage)->appends(array('created_at_value' => Input::get('created_at_value'), 'note_types_value' => Input::get('note_types_value'), 'contact_names_value' => Input::get('contact_names_value'), 'user_names_value' => Input::get('user_names_value')));
$notes_trash = Note::onlyTrashed()
->leftJoin('note_types', 'note_types.id', '=', 'notes.note_type_id')
->leftJoin('users', 'users.id', '=', 'notes.user_id')
->leftJoin('contacts', 'contacts.id', '=', 'notes.contact_id')
->orderBy($order[0], $order[1])
->select(array('notes.*', DB::raw('notes.id as nid')))
->get();
$this->layout->content = View::make('admin.notes.index', array(
'notes' => $notes,
'created_at' => DB::table('notes')->lists('created_at', 'created_at'),
'note_types' => DB::table('note_types')->lists('type', 'type'),
'contacts' => DB::table('contacts')->select(DB::raw('CONCAT(first_name," ",last_name) as cname'))->lists('cname', 'cname'),
'accounts' => Account::lists('company_name', 'company_name'),
'users' => DB::table('users')->select(DB::raw('CONCAT(first_name," ",last_name) as uname'))->lists('uname', 'uname'),
'notes_trash' => $notes_trash,
'perPage' => $perPage
));
}
Any advice would be appreciated. Thanks.
Solved this issue by using array_chunk function.
Here is the solution below:
foreach (array_chunk($data,1000) as $t)
{
DB::table('table_name')->insert($t);
}
There is limit 65,535 (2^16-1) place holders in MariaDB 5.5 which is supposed to have identical behaviour as MySQL 5.5.
Not sure if relevant, I tested it on PHP 5.5.12 using MySQLi / MySQLND.
This error only happens when both of the following conditions are met:
You are using the MySQL Native Driver (mysqlnd) and not the MySQL client library (libmysqlclient)
You are not emulating prepares.
If you change either one of these factors, this error will not occur. However keep in mind that doing both of these is recommended either for performance or security issues, so I would not recommend this solution for anything but more of a one-time or temporary problem you are having. To prevent this error from occurring, the fix is as simple as:
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
While I think #The Disintegrator is correct about the placeholders being limited. I would not run 1 query per record.
I have a query that worked fine until I added one more column and now I have 72k placeholders and I get this error. However, that 72k is made up of 9000 rows with 8 columns. Running this query 1 record at a time would take days. (I'm trying to import AdWords data into a DB and it would literally take more than 24 hours to import a days worth of data if I did it 1 record at a time. I tried that first.)
What I would recommend is something of a hack. First either dynamically determine the max number of placeholders you want to allow - i.e. 60k to be safe. Use this number to determine, based on the number of columns, how many complete records you can import/return at once. Create the full array of data for you query. Use a array_chunk and a foreach loop to grab everything you want in the minimum number of queries. Like this:
$maxRecords = 1000;
$sql = 'SELECT * FROM ...';
$qMarks = array_fill(0, $maxInsert, '(?, ...)');
$tmp = $sql . $implode(', ', $qMarks);
foreach (array_chunk($data, $maxRecords) AS $junk=>$dataArray) {
if (count($dataArray) < $maxRecords)) { break; }
// Do your PDO stuff here using $tmp as you SQL statement with all those placeholders - the ?s
}
// Now insert all the leftovers with basically the same code as above except accounting for
// the fact that you have fewer than $maxRecords now.
Using Laravel model, copy all 11000 records from sqlite database to mysql database in few seconds. Chunk data array to 500 records:
public function handle(): void
{
$smodel = new Src_model();
$smodel->setTable($this->argument('fromtable'));
$smodel->setConnection('default'); // sqlite database
$src = $smodel::all()->toArray();
$dmodel = new Dst_model();
$dmodel->setTable($this->argument('totable'));
$dmodel->timestamps = false;
$stack = $dmodel->getFields();
$fields = array_shift($stack);
$condb = DB::connection('mysql');
$condb->beginTransaction();
$dmodel::query()->truncate();
$dmodel->fillable($stack);
$srcarr=array_chunk($src,500);
$isOK=true;
foreach($srcarr as $item) {
if (!$dmodel->query()->insert($item)) $isOK=false;
}
if ($isOK) {
$this->notify("Przenieśliśmy tabelę z tabeli : {$this->argument('fromtable')} do tabeli: {$this->argument('totable')}", 'Będzie świeża jak nigdy!');
$condb->commit();
}
else $condb->rollBack();
}
You can do it with array_chunk function, like this:
foreach(array_chunk($data, 1000) as $key => $smallerArray) {
foreach ($smallerArray as $index => $value) {
$temp[$index] = $value
}
DB::table('table_name')->insert(temp);
}
My Fix for above issue:
On my side when i got this error I fixed it by reducing the the bulk insertion chunk size from 1000 to 800 and it worked for me.
Actually there were too many fields in my table and most them contains the details descriptions of size like a complete page text. when i go for there bulk insertion the service caused crashed and through the above error.
I think the number of placeholders is limited to 65536 per query (at least in older mysql versions).
I really can't discern what this piece of code is generating. But if it's a gigantic query, There's your problem.
You should generate one query per record to import and put those into a transaction.

Translate an SQL query using ISNULL into Datamapper ORM for Codeigniter

I have 3 mySQL tables: user, section and user_section (a joining table).
The SQL below:
SELECT id, description,
NOT ISNULL(
(SELECT user_id
FROM user_section
WHERE user_section.section_id = section.id
AND user_id=5)) AS user_in_section
FROM section
WHERE site_id = 3
nicely produces the following results:
id description user_in_section
3 section1 1
8 section2 0
9 section3 1
I have a form in my view to edit users and the sections they belong to. I'm writing the checkboxes out like so ($user_sections contains the above data):
<div class="checkboxes">
<?php foreach ($users_sections as $row) { ?>
<label class="checkbox"><input <?= ($row->checked>0?'checked':'') ?> type="checkbox" name="section[]" value="<?= $row->id ?>" /> <?= $row->description ?></label></br>
<?php } ?>
</div>
My questions are:
Is there a better way to write the sql query? Or is what I have good / the only way to get the data I want?
I want to use Datamapper ORM to write the query. I have this so far...
$section
->select('sections.id, description')
->select_func('NOT ISNULL', array('(SELECT id FROM sections_site_users where sections_site_users.site_section_id=sections.id and sections_site_users.site_user_id='.$user_id.')'), 'checked')
->where('site_id', $site_id)
->get();
The NOT before the ISNULL is being escaped with single quotes preventing the query from being correct sql. How can I write this properly in Datamapper?
Any suggestions for improvement greatly appreciated. Thanks in advance.
EDIT:
I have found a solution that works - here is my Datamapper code:
$sections = new Section();
$sections
->where('site_id', $site_id)
->get();
foreach ($sections as $s)
{
$s2 = new Section();
$s2
->where('id', $s->id)
->where_related('user', 'id', $user_id)
->get();
$s->checked = ($s2->exists() ? 1 : 0);
}
which produces the same data as the sql at the top of my answer. It does however use more database queries (I was hoping to do it in one database query).
Can anyone confirm for me that I've done the best thing here?
Thanks!
Yes! Simply:
$user = new User();
$sections = $user->section->where('id', $site_id)->get_iterated();
foreach($sections as $section)
{
// $section->id
// $section->description
}
But you have to set your relation properly!
ie:
Class user:
public $has_many = array('section);
Class section:
public $has_many = array('user');
Join table should be : users_sections
User table : users
section table : sections
Edit:
You want the section that have a specific user for a given site. You have a n relationship between sites and users. So you'll end loading the User first, then get his section:
$user = new User($user_id);
if ($user->result_count())
{
$sections = $user->section->where_related_site('id', $site_id)->get_iterated();
}
This should be fine. Sorry I didn't understand all at first.
A short description of your model would have help :)