Codeigniter like search in several tables - codeigniter

Hello stackoverflow community.
I want to make automatic search, based on article title, to show last news about it. These news can be in one or several tables, we dont know for use. Here it is my code:
$search = 'any article title';
$Linkearray = array('title' => $search);
$Linkearray2 = array('text' => $search);
$this->db->or_like($Linkearray);
$this->db->or_like($Linkearray2);
$this->db->from('table1', 'table2');
$query = $this->db->get();
Then i try to show results on page by next code:
foreach ($query->result_array() as $row):
echo $row['title'];
endforeach;
The problem is, that it shows search results only from table1.
If i rewrite a line of code into:
$this->db->from('table1, table2');
I get an error 1052. If anyone has an idea how to solve it, please share it :)
Thanks in advance!

And, here is solution:
$search = 'some word';
$Linkearray = array('table1.title' => $search,'table2.text' => $search);
$Linkearray2 = array('table2.title' => $search,'table2.text' => $search);
$this->db->or_like($Linkearray);
$this->db->or_like($Linkearray2);
$this->db->from('table1,table2');
$query = $this->db->get();
foreach ($query->result_array() as $row):
echo $row['title'];
endforeach;
This way - you will avoid 1052 error, and script will return data from both tables. Query generated in this case is:
SELECT *
FROM (`table1`, `table2`)
WHERE `table1`.`title` LIKE '%strokes%'
OR `table2`.`text` LIKE '%strokes%'
OR `table2`.`title` LIKE '%strokes%'
OR `table2`.`text` LIKE '%strokes%'
However, it will return some duplicated results... Better query, or php manipulation of results... to get desired output.

can you use php function to combine the outputs?
something like...
array_merge($this->db->from('table1'), $this->db->from(table2))

Related

Laravel where like on two strings

I would like to improve my search function.
Lets say for example the user types in "Letter contract" and in my database i have saved the following string "Letter employment contract". Using the following code will not return anything:
Letter::where('title', 'LIKE', '%' . $search . '%)->get()
Since the search is not looking into "Letter" alone and "Contract" alone in the context.
Anyways i can fix this?
Update
I tried the following code sample but still didn't get anywhere
$searchValues = preg_split('/\s+/', $this->attributes['q'], -1, PREG_SPLIT_NO_EMPTY);
$model = $model->whereTranslationLike('title', "%{$this->attributes['q']}%");
foreach ($searchValues as $value) {
$model->orWhereTranslationLike('title', "%{$value}%");
}
A very naive (but simple) solution would be first to split the search string into individual words, then adding them to the query individually.
$words = explode(' ', $search);
$query = Letter::query();
foreach ($words as $word) {
$query->where('title', 'LIKE', "%{$word}%");
}
$letters = $query->get();
This implementation doesn't scale very well, but it should get you thinking in the right direction.
There is no issue with your first code but for me, if I wanted to do like you, my code will be like so
$letters = Letter::where("title", "LIKE", "%{$search}%")->get()
I wish this syntax helps you.

Filter the collections and remove a collection eloquent laravel

I want to remove a filtered collection from a collections like I have this returned collections.
$products = items::where('item_id',$request->item_id)->with('product_reviews')->with('product_reviews.profile')->get();
foreach($products->product_reviews as $r):
if($r->status==='unapproved'):
//remove this from 'products' collections because its not approved yet
$this->remove($this);
endif;
endforeach;
but this
$this->remove($this);
does not work, neither a valid syntax to remove the collection, I just don't know how to remove the filtered collection e.g. if column status contains 'unapproved'. Any ideas, help please?
You can add a condition in your relation. This is not tested but most likely will solve your problem.
items::where('item_id',$request->item_id)->with([
'product_reviews' => function ($query) {
$query->where('status', 'approved')->with('profile');
}
])->get();
Hmm.. a little bit strange since the other 2 solutions should work for your case.
Have you tried to filter and pass the objects to other array and show them inside your view? Like:
$productWithReviews = items::where('item_id',$request->item_id)->with('product_reviews')->get();
$products = [];
foreach($productWithReviews->product_reviews as $r):
if($r->status!=='unapproved'):
$products[] = $r;
endif;
endforeach;

Laravel-4 Pagination in Query Builder with form inputs

Got a question if anyone can help out.
I have a query that has a collection of parameters and displays some results.
DB::table()
->join()
->where()
->orderby()
->select()
->get();
But the wheres are generated by a form input in the view. Basically this is a bunch of filters to get a table of results. I want to paginate that. if I change the get() to paginate(), and call $result->links() in the template, it does indeeed paginate and generates a bunch of results for me, however the problem is that when you move away from page 1, the links are just a _GET parameter and all the filter input does not get applied.
Is there a way I can have the pagination AND filters going at the same time? What is the laravel way of handling that? Or would I have to build some way of handling filters and pages? Any tips on that?
Cheers!
* Solution *
The solution was to make the form use GET method and persist the old filters to the Pagination using ->appends() method. Below is the modified code to do that if anyone else is looking.
$results = $query->paginate($this->report->inputs->per_page);
$query = array_except( Input::query(), Paginator::getPageName() );
$results->appends($query);
Yes, here's how I do it:
$orderBy = Input::get('orderBy', 'created_at');
$order = Input::get('order', 'DESC');
$limit = Input::get('limit', 100);
$name = Input::get('name', '');
$result = DB::table()
->where('name', 'LIKE', '%' . $name . '%')
->orderBy($orderBy, $order)
->paginate($limit);

Yii2 : Active Record add Not In condition

What is the active Record way of adding IN condition to an active Query
in yii 1.x you could use CDbCriteria like this
$cr = new CDbCriteria();
$cr->addNotInCondition('attribute', $array);
There seem to be no equivalent API call in yii2 active record implementation, how to do this via active record ?
Well all query operands seems now merged within in yii\db\QueryInterface::Where() per documentation
an In condition can now be added using something like
$query = MyModel::find()->where(['attribute'=>$array]);
for a not In condition it is slightly different format
$query = MyModel::find()->where(['not in','attribute',$array]);
$query = MyModel::findAll(['not in ','attribute',$array]);
http://www.yiiframework.com/doc-2.0/guide-db-active-record.html
For numbers:
$query = MyModel::find()->where('NOT IN('.implode(',', $array).')');
For strings
$deleteContracts = Contract::find()
->where([
'session_id' => $session_id,
'status' => Contract::STATUS_COMPLETED
])
->andWhere(['not in', 'contract_id', $contracts])
->all();
For me the only working solution was :
$query = MyModel::find()->where('`your-attribute` NOT IN(' . implode(',', $array) . ')')->all();

Many-to-many in laravel combine with where

I have many to many relationship between the models KSMschema and NORM
$normen = Ksmheader::find(15)->norms;
foreach($norms as $item){
echo $item->number;
}
Now i get a list of norms. This is one example:
[{"id":18,"certificaten_id":5,"nummer":"1.2.3","text":"Text van nog een norm.","created_at":"2014-02-14 15:14:05","updated_at":"2014-02-14 15:14:20","deleted_at":null,"pivot":{"ksmheader_id":9,"norm_id":18}}
But now i also need to sort them on a second column 'column_id'
$normen = Ksmheader::find(15)->normen->where('certificates_id', '=', 6);
This does not seem to work. What am i doing wrong?
Please check that you are using the correct function to get the norms :
Ksmheader::find(15)->norms->where('certificates_id', '=', 6);
What error/exception do you get if you try the above code?
Thanx all for you suggestions. I just found the answer myself.
For anyone who wants to know:
I first added the () after 'normen'. Just as deczo suggested.
Then i added a ->get()
normen = Ksmheader::find($ksmSchemaRow->ksmheader_id)->normen()->where('certificaten_id', '=', 5)->get();
foreach($normen as $item){
echo $item->nummer;
//echo 'NAME';
echo '/';
}
I added get() now i get the results i want.

Resources