YII Console Application (CConsoleCommand) - yii

Good time! There is a project on Yii, you need to organize operations for CRONu through console applications. Once a month, the script adds a record to the table.
class ZpEduCommand extends CConsoleCommand {
public function run($args) {
$command = Yii::app()->db->createCommand('INSERT INTO `text`(`ID`, `datee`, `ggg`) VALUES ("123123","2014-12-01 00:00:00","123")');
$command->execute();
}
All works well. If so put the date, nothing is added.
$command = Yii::app()->db->createCommand('INSERT INTO `text`(`ID`, `datee`, `ggg`) VALUES ("123123","' . date('Y-m-d H:i:s') . '","123")');
$command->execute();

Make sure that ID is not primary key in table because primary key should be unique but in your example they are the same.
Also better use query builder for operations with database:
$command = Yii::app()->db->createCommand();
$command->insert('text', array(
'datee'=>date('Y-m-d H:i:s'),
'ggg'=>'123',
));

Related

Laravel ,php -artisan suffixe had to my table when i seed it

I have 2 small issues with the "php artisan db:seed" command.
WHen i run the command, i have this error message :
"SQLSTATE[42S02] Base table or view not found : 1146 La table
"bootstrap_template_commerciauxes" n'existe pas ..."
The problem is : my table name is commerciaux, and not commerciauxes.
I checked all my file, my model is Commerciaux.php, my factory CommerciauxFactory.
So ... what kind of sorcely is it ? I'am missing something ?
Secondly, the SQL request from db:seed add some columns i dont want to :
SQLSTATE[42S02]: Base table or view not found: 1146 La table 'bootstrap_template.commerciauxes' n'existe pas (SQL: insert into commerciauxes (nom, prenom, ville, updated_at, created_at) values (Dr. Luis Champlin PhD, Dr. Luella Leuschke, Leathaberg, 2022-06-03 21:42:44, 2022-06-03 21:42:44))
Here is my Commerciaux model :
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Commerciaux extends Model
{
use HasFactory;
protected $fillable = [
'nom',
'prenom',
'ville',
'nbre_commande',
];
}
My CommerciauxFactory (in case)
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
class CommerciauxFactory extends Factory
{
/**
* Define the model's default state.
*
* #return array
*/
public function definition()
{
return [
'nom' => $this->faker->name(),
'prenom' => $this->faker->name(),
'ville' => $this->faker->city(),
];
}
}
Thanks you very much for your time, i wanted to try this nice tool but i get blocked since 2 days on thoses mistakes.
To answer your issues:
Laravel by default treats table names as plural due to default conversion and I would advise keeping it that way. If you want to define your own table name then, In your model Class you can define following for your name of table:
protected $table = 'commerciaux';
Also, in your migration's Up function, set your table name like following:
public function up()
{
Schema::create('commerciaux', function (Blueprint $table) {
//Your table columns and structure
});
}
Regarding the additional columns, those are laravel timestamps that keep a track of the timestamps of the record when it was created (created_at) and updated(updated_at) last time. In this case, I would also suggest keeping these fields as they keep a track of record creation and last modifying timestamps.
If you don't want these fields in your table then in your model you can define the following code to exclude the timestamps:
public $timestamps = false;
Other than that, you can also remove following line from your migration:
table->timestamps();
EDIT: Before running migration again, try the roll back command so the created base table and migration records can get deleted from the migrations table.

TYPO3 Extbase Querybuilder add 'AND 1<>1' at the end of constraints

I've create a M:N relation in TYPO3 Extbase.
With following code I've added the contraints to QueryBuilder.
foreach ($selectedFeatures as $value) {
$constraints[] = $query->contains('features', $value);
}
$query->matching(
$query->logicalAnd(
$constraints
)
);
It works fine till 4 Features. After this the QueryBuilder add at the end of the constraints 'AND 1<>1'.
And this is the reason why I've got no result.
Does anybody know what this could be? Each item in '$selectedFeatures' are objects from 'Feature' model. That's I've checked and this is correct.
This happens in Typo3DbQueryParser when the second operand is null. So you‘ll have to find out why and under which circumstances $value, i.e. one of your $selectedFeatures, happens to be null.

Insert SQL statement error

Hi Im trying to insert data into a database using an insert statement. So basically, the user inputs data into a form and then once the submit button is clicked its meant to get the property_id of the table Property.
My code is this:
<?php
$id = intval($_GET['id']);
$query = mysql_query('SELECT * FROM review WHERE property_id="'.$id.'"');
if(isset($_POST['submit']))
{
$review = mysqli_real_escape_string($mysqli, $_POST['review']);
if(mysqli_query($mysqli, "INSERT INTO review(review) VALUES ('$review')"))
{
?>
<script>alert('Successfully Updated ');</script>
<?php
}
else
{
?>
<script>alert('Error...');</script>
<?php
}
}
?>
At the top of the page is my other code which is as followed:
<?php
include_once '../db/dbconnect.php';
$id = intval($_GET['id']);
$sql = 'SELECT* FROM property WHERE property_id="'.$id.'"';
$result = mysqli_query($mysqli, $sql);
$row=mysqli_fetch_array($result);
?>
The code above basically displays all the data for that individual property. Any help would be great.
There are several errors in your code:
$id = intval($_GET['id']);
$query = mysql_query('SELECT * FROM review WHERE property_id="'.$id.'"');
The mysql_* functions are deprecated in PHP 5, and totally removed in PHP 7. Don't use them!
Moreover, it's not possible to use mysql_* and mysqli_* functions together.
Yet another error: you are executing a SELECT query, but you never fetch the results!
Note: you don't need to concatenate $id. It makes the code harder to read with plenty of useless single and double quotes, and increases the likeliness of a typo. Just enclose the variables in a double-quoted string.
You are casting $id to an int value. If the field property_id is an integer, there is no need to put single quotes around $id in the query.
Updated snippet:
$id = intval($_GET['id']);
$query = mysqli_query($mysqli, "SELECT * FROM review WHERE property_id=$id") or die(mysqli_error($mysqli));
while($r = $query->fetch_assoc()) {
// do something here with the current record $r
}
Your code:
if(mysqli_query($mysqli, "INSERT INTO review(review) VALUES ('$review')"))
[...]
<script>alert('Error...');</script>
When developing, you should display (or write to a log file) the MySQL error message from each failing query. It will make debugging much easier:
<script>alert('Error: <?= mysqli_error($mysqli) ?>');</script>

CRUD very slow with conditions, is there any other faster way?

im having problem with CRUd now that i filled the database. CRUD is taking ages to show, becouse it takes condition from M:M tables.
Tables:
Table USER. has many labels (hasMany)
Table LABLE, has many users (hasMany)
Intermidiate Table UserLabel, has two hasOne
I want to show all users from some label with CRUD like this:
MODEL USER:
class Model_User extends Model_Table {
public $table ='user';
function init(){
parent::init();
$this->addField('fbid')->mandatory('Facebook id required');
...
$this->hasOne('Application');
$this->hasMany('UserLabel');
$this->addExpression('ratio')->set(function($model,$select){
return $select->expr('ROUND(([f2] / [f1]) * 100,0)')
->setCustom('f1',$model->getElement('sends'))
->setCustom('f2',$model->getElement('clicked'));
});
$this->addHook('beforeSave',function($m){
$m['updated']=$m->dsql()->expr('now()');
});
}
MODEL LABEL:
class Model_Label extends Model_Table {
public $table ='label';
function init(){
parent::init();
$this->addField('name')->mandatory('Name required');
$this->addFIeld('application_id')->refModel('Model_Application')->defaultValue($this->api->recall('app'))->system(true);
$this->addField('active')->type('boolean')->defaultValue('true')->system(true);
$this->addField('created')->type('timestamp')->defaultValue($this->dsql()->expr('now()'))->system(true);
$this->addField('updated')->type('timestamp')->system(true);
$this->hasMany('UserLabel');
$m = $this->add("Model_UserLabel");
$this->addExpression("users", $m->dsql()
->field($m->dsql()->expr("count(*)"), "all users")
->where("label_id", $this->getField("id"))
);
MODEL USER LABEL
class Model_UserLabel extends Model_Table {
public $table ='userlabel';
function init(){
parent::init();
$this->hasOne('User');
$this->hasOne('Label');
}
}
CODE FOR CRUD
$c = $this->add('CRUD');
$c->setModel('User', array('name', 'gender','country','city'));
$c->model->addCondition('id','in',
$this->add('Model_UserLabel')->addCondition('label_id', $_GET['l'])->dsql()->field('user_id')
);
Is there any better way to do this?
ps. I tested this solution, it is a lot faster but still very slow at around > 5.000 users:
//get all users
$records = $this->api->db->dsql()->option('distinct')->table('user')->join('userlabel.user_id')->field('user.id')->where('userlabel.label_id',$_GET['l'])->do_getAll();
foreach($records as $record){
$users .= ','.$record['id'];
}
//create CRUD
$c = $this->add('CRUD');
$c->setModel('User', array('name', 'gender','country','city','sends','clicked','ratio'));
$c->model->addCondition("application_id", $this->api->recall('app'));
$c->model->addCondition('id','in',
'('.$users.')'
);
Source code express more than words, so you better add your model definition source code (maybe not full) in your question.
What should be one row in your CRUD/Grid? I guess it's not 1 user = 1 row, but 1 user_label should be one row in grid. So you should set UserLabel model as model for your grid.
And then define some additional fields in Model_UserLabel by joining them from user and/or label tables directly like this:
class Model_UserLabel extends SQL_Model {
function init() {
parent::init();
// ...
// fields from user table
$join_u = $this->join('user', 'user_id');
$join_u->addField('username'); // this adds fields in current model from joined table
$join_u->addField('email');
// fields from label table
$join_l = $this->join('label', 'label_id');
$join_l->addField('name');
}
}
Note: source code above is untested and put here only as example.
EDIT:
Try this solution - almost the same as I wrote earlier above:
MODEL USER LABEL
class Model_UserLabel extends Model_Table {
public $table ='userlabel';
function init(){
parent::init();
$this->hasOne('User');
$this->hasOne('Label');
// join user table and add fields to this model from joined user table
$j = $this->join('user', 'user_id');
$j->addField('name');
$j->addField('gender');
$j->addField('country');
$j->addField('city');
}
}
CODE FOR CRUD
$m = $this->add('Model_UserLabel'); // UserLabel here not User
$m->addCondition('label_id', $_GET['l']); // and then this is simple
$c = $this->add('CRUD');
$c->setModel($m, array('name', 'gender','country','city'));
Try this solution and as (almost) always - code is untested.
EDIT:
Please try this version - is it working faster? That's basically your P.S. example, but you shouldn't extract all user IDs, join them and then create huge select with a lot of 'in'.
Faster result should be if you could do all with just one DB request without any additional processing of data.
// parameters
$app_id = $this->api->recall('app);
$label_id = $_GET['l'];
// prepare model for grid
$m = $this->add('Model_User'); // default User model
$m->_dsql()->option('distinct') // add join to userlabel table + conditions
->join('userlabel.user_id')
->where('userlabel.label_id', $label_id)
->where($m->getField('application_id'), $app_id);
// create CRUD and set it's model. All conditions already set on model above
$c = $this->add('CRUD');
$c->setModel($m, array('name', 'gender','country','city','sends','clicked','ratio'));
NOTE: Source code above as often - untested :)

Preserve Order of IN in ORM Order

I'm trying to do a query where I preserve the order of the ids in a IN statement. I can't seem to do it with either the Model Manage Query Builder or the standard ORM 'order' array parameter. Am I missing something? I keep getting:
UNEXPECTED TOKEN IDENTIFIER(, NEAR TO 'id`enter code here`,17743,16688,16650
Here's my model manager:
$query = $this->modelsManager->createQuery('SELECT * FROM Projects WHERE id IN ('.implode(',', array_keys($finalIterations)).')
ORDER BY FIELD(id,'.implode(',', array_keys($finalIterations)).'');
It's pretty obvious PhQL doesn't like the FIELD key word. Is there a way for me to do what I'm trying to do with PhQL? It seems I will not be able to do what I need to.
Unfortunately as previously said, this is missing a feature in Phalcon.
Have a look at this function, I've put it into my ModelBase abstract class which is parent class of all my models. It uses PhQL variable binding, so it's safe for handling direct user input.
You could have reimplemented custom \Phalcon\Mvc\Model\Criteria but this solution seems to be easier to work with, at least for me.
ModelBase abstract
public function appendCustomOrder( \Phalcon\Mvc\Model\CriteriaInterface &$criteria, $orderField, array &$orderValues = [] ) {
if(!empty($orderValues)) {
$queryKeys = $bindParams = [];
foreach($orderValues as $key => $id) {
$queryKey = 'pho'.$key;
$queryKeys[] = ':'.$queryKey.':';
$bindParams[$queryKey] = $id;
}
// TODO: add support for multiple orderBy fields
$criteria->orderBy('FIELD('.$orderField.','.implode(',',$queryKeys).')');
// there's no 'addBind' function, need to merge old parameters with new ones
$criteria->bind( array_merge( (array) #$criteria->getParams()['bind'], $bindParams ) );
}
}
Controller usage
$projectIDs = [17743, 16688, 16650];
$projectsModel = new Projects();
$criteria = $projectsModel->query->inWhere( 'id', $projectIDs );
$projectsModel->appendCustomOrder( $criteria, 'id', $projectIDs );
$projectsData = $criteria->execute();
This will generate valid PhQL syntax similar to this one:
SELECT `projects`.`id` AS `id`, `projects`.`title` AS `title`
FROM `projects`
WHERE `projects`.`id` IN (:phi0, :phi1, :phi2)
ORDER BY FIELD(`projects`.`id`, :pho0, :pho1, :pho2)