How to search on specific columns with TNTSearch in Laravel? - laravel

Below is my model code Product.php.
public $asYouType = true;
public function toSearchableArray()
{
$array = $this->toArray();
// Customize array...
return $array;
}
Controller code
$phones = Product::search($request['phone'])->get();
Now I want to search for products from my product table, but TNTSearch is searching all columns in my tables and gives me the result. However, I am working on an e-commerce site, and I want results by product title and then from the description column.
My table structure looks like the below image.

For indexing specific columns you should set custom array,
For instance:
public function toSearchableArray()
{
$array = [
//'title' => $this->title,
'description' => $this->description
];
return $array;
}
In above example we ignore the title field content to indexing and just index description field.

Related

Laravel pagination and model count returns duplicated query

Hello is there a way to count model count results without duplicating the query?
I am getting all users (with pagination) and at the top of the page, I want to count the User model and display how many users I have in total. The debugbar returns that I have duplicated the count(*) query and it does not make any problems but I'd like to know if there is a way to get both results without duplicating the query.
IMG OF QUERIES:
These are the functions that are "causing the issue":
public static function getUsers() {
return User::withoutTrashed()->select(['id', 'name', 'email', 'status', 'isAdmin', 'isMember'])->paginate(15);
}
public static function getUsersCount() {
return User::count();
}
And here is the provided data for the view:
$users = User::getUsers();
$usersCount = User::getUsersCount();
return view('dashboard.users.index', [
'users' => $users,
'usersCount' => $usersCount
]);
To get the total items returned call:
$paginator->total()
This needs to be one a LengthAwarePaginator: https://laravel.com/docs/9.x/pagination#paginator-instance-methods

how to save multiple dropdownlist yii2

I'm trying to save multiple data from a dropdownlist, I have 2 tables Asistencia and Mecanico in the table Asistencia i have this in the _form
<?php
echo $form->field($model, 'mecanico_id[]')
->dropDownList(ArrayHelper::map(Mecanico::find()->all(), 'id_mecanico', 'nombre'),
[
'multiple'=>'multiple',
'class'=>'chosen-select input-md required',
]
)->label("Mecanicos");
?>
i know if i want to save multiple data i have to change in controllers-> actionCreate/Update but i dont know how. Here is my actionCreate
public function actionCreate()
{
$model = new Asistencia();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id_asistencia]);
}
return $this->render('create', [
'model' => $model,
]);
}
I need sample controller code explaining how to save multiple items from a drop down list to the database, as well as update the list of saved items. Thanks.
here is my table of Asistencia
Asistencia table
Table of Mecanico
Mecanico table
and the relation of those 2 table
enter image description here
For example you have Product and Category many to many relation.
In your Product model,
Declare field:
public $categories_ids;
Put it in 'safe' in rules():
[['categories_ids'], 'safe']
3.Declare AfterSave function:
public function afterSave($insert, $changedAttributes) {
// If this is not a new record, unlink all records related through relationship 'categories'
if(!$this->isNewRecord) {
// We unlink all related records from the 'categories' relationship.
$this->unlinkAll('categories', true);
// NOTE: because this is a many to many relationship, we send 'true' as second parameter
// so the records in the pivot table are deleted. However on a one to many relationship
// if we send true, this method will delete the records on the related table. Because of this,
// send false on one to many relationships if you don't want the related records deleted.
}
foreach($this->categories_ids as $category_id) {
// Find and link every model from the array of ids we got from the user.
$category = Category::findOne($category_id);
$this->link('categories', $category);
}
parent::afterSave($insert, $changedAttributes);
}
Decare AfterFind function():
public function afterFind(){
parent::afterFind();
$this->categories_ids = ArrayHelper::getColumn($this->categories, 'id');
}
Declare relation:
public function getCategories() {
return $this->hasMany(Category::className(), ['id' => 'category_id'])->viaTable('product_category', ['product_id' => 'id']);
}
I hope it will help to you.

yii2 Validation not working

I need to validate a value from another table both of them field type decimal
if amount(model 1) moreover available(model2 DATA selected)
model 1
rule
public function rules()
{
return [
[['amount'], 'checkAvailable','skipOnEmpty' => false],
];
}
custom validation function
public function checkAvailable($attribute, $params)
{
$caid = $this->capex_budget_id;
$available = Capexbudget::find()
->select(['available'])
->where('id = :caid', [':caid' => $caid])
->all(); // select amount from Capexbudget where id = $caid
if ($this->amount > $available){
$this->addError('amount', 'not enough');
}
}
i can got a data available from Capexbudget where ID that i select
here are the query logs
but validation not working it not compare value between $this->amount and $available
what i missing please.
First of all, you're selecting all records matching your where conditions here:
$available = Capexbudget::find()
->select(['available'])
->where('id = :caid', [':caid' => $caid])
->all(); // HERE
You should change function all() to one(), to get one record.
Second thing is, if you're using all() or one(), that methods returns object, not value.
To make it work, you should change if statement to:
if ($this->amount > $available->available){ //here, compare to attribute `available`

Algolia search (Scout) with multiples fields

Let' say I want to create a phone book for a big company with multiples offices.
My database is composed by 3 tables:
- User
- City (represent the office's location)
- Role (a User can have multiple roles)
I'd like to create a form with 3 different fields to perform the query, how can I do that ?
For now I've got only 1 field and this is my main model User
```
public function city()
{
return $this->belongsTo(City::class);
}
public function roles()
{
return $this->belongsToMany(Role::class);
}
public function toSearchableArray()
{
$office = $this->city;
$array = [
'name' => $this->name,
'phone' => $this->phone,
'postal_code' => $office->postal_code,
'city' => $office->name,
];
return $array;
}
```
How would you do a research with Algolia and add filters to the query (City and Roles) ?
How should I store Roles ? Plain text ?
Thank you
Scout only support numbers in the where clause: https://laravel.com/docs/5.5/scout#where-clauses
I would recommend to also store the ID for offices and do search like:
User::search('')->where('office_id', 2)->get();
For Roles, because you have multiple values, you should store them as in an array.
You cannot use where on arrays, so you will need to leverage the callback parameter to add a filter entry in the options array.
User::search('', function ($algolia, $query, $options) {
$options = array_merge($options, [
'filters' => 'roles:engineer'
]);
return $algolia->search($query, $options);
})->get();
You can find Algolia's doc about filtering here: https://www.algolia.com/doc/guides/searching/filtering/
Please let me know if that worked for you.

How to set form data for a Joomla subform?

I'm trying to create a Joomla (3.x) component and struggling with using subforms. There doesn't seem to be much documentation for using subforms besides e.g. https://docs.joomla.org/Subform_form_field_type
For my component I have one parent table and some associated database rows from a child table.
The idea is to display an edit form for that parent table using Joomla's XML syntax for forms and in that edit form also display a subform with multiple items (the associated rows from the child table).
I would like to be able to modify the parent table fields but also in one go the associated child table rows (of course one could just edit each row associated to the parent table individually but I'm guessing that would be a terrible user experience). Or am I approaching this thing the wrong way?
Now, I know how to implement/show a subform and also know how to show the parent table fields and populate those fields with the right data. But how do I populate or refer to the subform using the parent form?
I have this function inside my component model (which inherits from JModelAdmin).
protected function loadFormData()
{
$data = JFactory::getApplication()->getUserState('com_mycomp.edit.parent.data', array());
if (empty($data))
{
$data = $this->getItem();
// how to refer to subform fields inside $data?
}
return $data;
}
I know if a field is called name or title I can just change the $data object after $this->getItem(), e.g. $this->set('name', 'John Doe').
Let's say the field of type subform has a name attribute of books and I wanted to insert one or more rows, how would I refer to it? I've tried dot syntax in various forms, e.g.: $data->set('books.1.childfield') or $data->set('books.pages1.childfield'). But it doesn't seem to refer to the right form.
There is of course getForm function in the same model file, however I do not think a subform should be loaded independently of the containing parent form?
public function getForm($data = array(), $loadData = true)
{
$app = JFactory::getApplication();
$form = $this->loadForm('com_mycomp.parent', 'parent', array('control' => 'jform', 'load_data' => $loadData));
if (empty($form))
{
return false;
}
return $form;
}
EDIT:
Already answered my own question.
Never mind. I figured it out after taking a break for some time and trying again (inspecting the form inputs again and taking a deep breath).
This is the format used:
$data->set('nameofsubformfield',
[
'nameofsubformfield0' => [
'fieldwithinsubform' => 'value-of-field-within-subform'
]
]);
This seems to work! I'm using this within getItem function now. Just have to loop and put loop counter in place of the zero after nameofsubformfield. See code below for some context (function resides in parent model).
public function getItem($pk = null)
{
$data = parent::getItem((int)$pk);
if (empty($data))
{
return false;
}
$childModel = JModelLegacy::getInstance('child', 'MycompModel');
$rowChildren = $childModel->getChildrenByParentID((int)$data->get('id'));
$childArray = [];
for ($i = 0; $i < count($rowChildren); $i++)
{
$childArray['children'. $i] = [
'name' => $rowChildren[$i]['name']
];
}
$data->set('children', $childArray);
return $data;
}

Resources