How to change search model for using one field - search

I have CRUD generated bu Gii. By default, the search in app use one field for each table column. How should i change my search model, for make search in all columns via alone field?
That's my model:
class UserSearch extends User
{
/**
* #inheritdoc
*/
public function rules()
{
return [
[['id', 'status', 'created_at', 'updated_at'], 'integer'],
[['username', 'auth_key', 'password_hash', 'password_reset_token', 'email'], 'safe'],
];
}
/**
* #inheritdoc
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* #param array $params
*
* #return ActiveDataProvider
*/
public function search($params)
{
$query = User::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
$query->andFilterWhere([
'id' => $this->id,
'status' => $this->status,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
]);
$query->andFilterWhere(['like', 'username', $this->username])
->andFilterWhere(['like', 'auth_key', $this->auth_key])
->andFilterWhere(['like', 'password_hash', $this->password_hash])
->andFilterWhere(['like', 'password_reset_token', $this->password_reset_token])
->andFilterWhere(['like', 'email', $this->email]);
return $dataProvider;
}
}

This is how I do it:
public function search($params)
{
..............................
if($this->keyword) {
if(preg_match("/[A-Za-z]+/", $this->keyword) == true) {
$query->andFilterWhere(['like', 'LOWER(CONCAT(name, age, WHATEVERFIELDS)), ', strtolower($this->keyword)]);
} else {
$query->andFilterWhere(['id' => $this->keyword]);
}
}
keyword is not actually a column in the db it is just a variable I attached to the search model. If the keyword is numeric I consider it an ID, you can ignore this part if you want. Otherwise I concat some fields and search in the result. You can also not concat the fields and just add a condition for each field, up to you.
You can see the full file at: https://github.com/Mihai-P/yii2-core/blob/master/models/ContactSearch.php

Related

Kendo UI Angular 2 Grid initial default filter

I need to add a default filter into the DataSourceRequestState so that the database request automatically contains some initial filter value. I'm trying to filter by this.applicationName. Does anyone know how I can add a pre-filter to the grid?
export class ServerCertificationGrid implements OnInit {
public data: GridDataResult;
private filter: CompositeFilterDescriptor;
public state: DataSourceRequestState = {
skip: 0,
take: 20,
filter: filterBy(this.data, { // This also does not work.
logic: 'and',
filters: [
{ field: "name", operator: "contains", value: this.applicationName, ignoreCase: true }
]
})
};
#Input() public applicationName: string;
constructor(private dataService: DataService, private dialogService: DialogService) {
console.log(this.applicationName);
// This does not work because this.state.filter is null.
//let fd: FilterDescriptor = {
// field: "name",
// operator: "contains",
// value: this.applicationName,
// ignoreCase: true
//}
//this.state.filter.filters.push(fd);
this.dataService.getCertificationOverview(this.state)
.subscribe(r => {
console.log(r);
this.data = r;
});
}
Here is the DataService code this component is calling.
public getApplicationServers(state: DataSourceRequestState): Observable<DataResult> {
const queryStr = `${toDataSourceRequestString(state)}`; // Serialize the state
const hasGroups = state.group && state.group.length;
return this.http
.get(`${'api/BircCertificationForm'}?${queryStr}`) // Send the state to the server
.map(response => response.json())
.map(({ Data, Total, AggregateResults }) => // Process the response
(<GridDataResult>{
// If there are groups, convert them to a compatible format
data: hasGroups ? translateDataSourceResultGroups(Data) : Data,
total: Total,
// Convert the aggregates if such exist
//aggregateResult: translateAggregateResults(aggregateResults)
})
)
}
You can bind the filter input of the Grid component and provide an initial filter descriptor, like in the following demo:
Initial filter
<kendo-grid
[data]="gridData"
[pageSize]="state.take"
[skip]="state.skip"
[sort]="state.sort"
[filter]="state.filter"
[sortable]="true"
[pageable]="true"
[filterable]="true"
(dataStateChange)="dataStateChange($event)"
>
...
export class AppComponent {
public state: State = {
skip: 0,
take: 5,
// Initial filter descriptor
filter: {
logic: "and",
filters: [{ field: "ProductName", operator: "contains", value: "Chef" }]
}
};
The filter needs to have the "logic" and "filters" fields only, not to be the result of a filterBy() function call.

I can´t concatenate a label with string in symfony3

I can´t concatenate a label with string.
->add('originador', EntityType::class, array(
'label' => "app.label.x_originador".'*',
'class' => 'AppBundle:Usuario',
'em' => $options['entityManager'],
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u');
},
'placeholder' => '',
'required' => false,
))
In the part of 'label' => "app.label.x_originador".'*',
I need that the result be Originador*,because the label is for required value.
The result that I recieve is app.label.x_originador*
Please, help me to get
Originador* as result.
You can pass the translator service to your form type and translate then concatenate like this:
class MyFormType extends AbstractType
{
private $translator;
public function __construct(TranslatorInterface $translator)
{
$this->translator = $translator;
}
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('originador', EntityType::class, array(
'label' => $this->translator->trans('app.label.x_originador',[], 'domain').'*',
'class' => 'AppBundle:Usuario',
'em' => $options['entityManager'],
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u');
},
'placeholder' => '',
'required' => false,
));
}
}
juste replace "domain" with your translation domain.
EDIT: but yeah, the best solution is probably #ccKep's one

How to bulk "upsert" in bookshelf?

I need to import the data from a CSV file (around 20K rows) to my database. Some of the rows may already exist in the database, thus they only need to be updated, but the new rows must be inserted. If any of the operations fail, the transaction must be cancelled.
How can I do this? This is the code I was using:
var vehicle = {
id: row.id,
lastUpdate: moment(row.lastUpdate, 'DD/MM/YYYY - HH:mm').toDate(),
version: row.version,
color: row.color,
location: row.location,
status: row.status
};
Vehicle.forge({
id: row.id
})
.save(vehicle, { transacting: t, patch: true })
.then(model => {
console.log('*************' + vehicle.id);
})
.catch(Vehicle.NoRowsUpdatedError, err => {
// There are no rows for this chassis, so let's insert it
Vehicle.forge(vehicle)
.save(null, { transacting: t, method: 'insert' })
.then(model => {
console.log('++++++++++++++' + vehicle.id);
})
.catch(err => {
console.log(`INSERT ERROR: ${err.message}`);
t.rollback();
return res.json({ status: false, count: 0, error: err.message });
});
})
.catch(err => {
console.log(`UPDATE ERROR: ${err.message}`);
t.rollback();
return res.json({ status: false, count: 0, error: err.message });
});
This code is in a for loop, but it fails in the second iteration, probably because of concurrency between the promises.
I also tried to add a custom function to my model file, but it says that the function does not exist.
let bookshelf = require('./base');
var Vehicle,
Vehicles;
Vehicle = bookshelf.Model.extend({
tableName: 'vehicles',
/**
* Insert a model based on data
* #param {Object} data
* #param {Object} [options] Options for model.save
* #return {Promise(bookshelf.Model)}
*/
create: function (data, options) {
return this.forge(data).save(null, options);
},
/**
* Select a model based on a query
* #param {Object} [query]
* #param {Object} [options] Options for model.fetch
* #param {Boolean} [options.require=false]
* #return {Promise(bookshelf.Model)}
*/
findOne: function (query, options) {
options = extend({ require: true }, options);
return this.forge(query).fetch(options);
},
/**
* Select a model based on data and update if found, insert if not found
* #param {Object} selectData Data for select
* #param {Object} updateData Data for update
* #param {Object} [options] Options for model.save
*/
upsert: function (selectData, updateData, options) {
return this.findOne(selectData, extend(options, { require: false }))
.bind(this)
.then(function (model) {
return model
? model.save(
updateData,
extend({ patch: true, method: 'update' }, options)
)
: this.create(
extend(selectData, updateData),
extend(options, { method: 'insert' })
)
});
}
});
Vehicles = bookshelf.Collection.extend({
model: Vehicle
});
module.exports = {
Vehicle: bookshelf.model('Vehicle', Vehicle),
Vehicles: bookshelf.collection('Vehicles', Vehicles)
};
Instead of using bookshelf, you could utilize knex directly to do this. Just grab the instance of knex you pass to bookshelf, and you can use it like this:
knex.transaction((trx) => {
return Bluebird.map(vehicles, vehicle => {
const insert = knex('vehicles').insert(vehicle).toString();
delete vehicle.id;
const update = knex('vehicles').update(vehicle).toString();
const set = update.substring(18);
return trx.raw(`${insert} ON CONFLICT (id) DO UPDATE ${set}`);
});
});
We can utilize Knex's handy toString method to generate most of our raw query for us; in this way, we can do an upsert even though it's not directly supported by Knex. Bluebird's map function is perfect for cleanly handling an array of data like this and would let you await having to loop through it altogether.

Yii2 searchmodel related model

As you can see I've gridview (from model called umumiy). And via id_nomi I'm showing nomi.rus (which means rus column from nomi model):
The issue here is I'm trying to make search from Nomi model via umumiy gridview. I'm trying to get values (with nomi.rus) via ajax. This is what I tried:
$model = new UmumiyModel();
$searchModel = new UmumiyModelSearch();
if (Yii::$app->request->isAjax){
$data = Yii::$app->request->post();
$searchModel->nomi->rus = $data['dori_nomi']; // search input value
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->renderPartial('sotish', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'model' => $model,
]);
}
What am I doing wrong???
You can use a public member in NomiSearch model to store text value from "Id Nomi" input field of gridview.
So, in NomiSearch model:
class NomiSearch extends Nomi
{
public $nomiText;
public function rules()
{
return [
// ...
[['nomiText'], 'safe'],
];
}
public function search($params)
{
$query = Nomi::find();
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
]);
if($this->nomiText!=null)
{
$query->andWhere(['IN', 'id_nomi', (new \yii\db\Query())->select('id')->from('nomi')->where(['like', 'nomi', $this->nomiText])]);
}
return $dataProvider;
}
}
Finally, in index view:
GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
[
'label' => 'Id Nomi',
'attribute' => 'nomiText',
'value' => function($data) {
return $data->nomi->rus;
},
],

create crud doesnt work in yii2

i make a simple CRUD in yii2 backend from table name "Guru",i already make models with the same table and make the CRUD but when i try to Create new data from the Create function,the data doesnt saved in database at all,i already make the code similar with the frontend and change the namespace but it didnt work at all in backend.
here is my backend "Guru" models code
<?php
namespace backend\models;
use Yii;
class Guru extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'guru';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['nip', 'nama_guru', 'ttl', 'jenis_kelamin', 'alamat', 'telp', 'agama', 'jabatan', 'user', 'pass', 'role', 'tgl_create', 'update_create', 'mapel'], 'required'],
[['jenis_kelamin'], 'string'],
[['mapel'], 'integer'],
[['nip', 'telp', 'jabatan', 'user', 'pass'], 'string', 'max' => 20],
[['nama_guru', 'ttl'], 'string', 'max' => 30],
[['alamat'], 'string', 'max' => 50],
[['agama', 'role', 'tgl_create', 'update_create'], 'string', 'max' => 10]
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
//'id_guru' => 'Id Guru',
'nip' => 'NIP',
'nama_guru' => 'Nama Guru',
'ttl' => 'Tempat Tanggal Lahir',
'jenis_kelamin' => 'Jenis Kelamin',
'alamat' => 'Alamat',
'telp' => 'No Telpon',
'agama' => 'Agama',
'jabatan' => 'Jabatan',
'user' => 'User',
'pass' => 'Pass',
'role' => 'Role',
'tgl_create' => 'Tgl Create',
'update_create' => 'Update Create',
'mapel' => 'Mata Pelajaran',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getJadwalGuru() {
return $this->hasMany(Jadwal::className(), ['id_mapel'=>'mapel']);
}
public function getJadwal() {
return $this->hasMany(Jadwal::className(), ['nip'=>'id_guru']);
}
}
and this is my Controller code
namespace backend\controllers;
use Yii;
use backend\models\Guru;
use backend\models\GuruSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
public function actionCreate()
{
$model = new Guru();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id_guru]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
i really dont know why it doesnt work when the other CRUD in backend and frontend is work.i'm new to this framework,please kindly help me.
Could be a validation problem,
you have a lot of required field and if one is missing the model is not saved.
For evaluate this situation try using save(false ) false mean without model validation. in this way :
public function actionCreate()
{
$model = new Guru();
if ($model->load(Yii::$app->request->post()) && $model->save(false)) {
return $this->redirect(['view', 'id' => $model->id_guru]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
If with the param false the model is saved check selectively (by commenting) the rule that create problem with validation.

Resources