Laravel 8 whereHas and whereBetween has no effect - eloquent

Having this code:
$resultCards = Posts::with('subcategory')->whereHas('subcategory', function($q) use ($main_categories,$sub_categories) {
$q->whereIn('id', $sub_categories);
$q->orWhereHas('category', function($query) use ($main_categories) {
$query->whereIn('id', $main_categories);
});
})
This works and fetches the relevant records correctly.
Now I want to filter the result like this:
$resultCards->whereBetween('price', [0,3500]);
$results = $resultCards->paginate(5);
This doesnt change the result. It does work if I remove one of the whereHas. Any way around this?

I was actually overcomplicating things. This works:
$resultCards = Posts::with('subcategory')->whereHas('subcategory', function($q) use ($main_categories) {
$q->whereHas('category', function($query) use ($main_categories) {
$query->whereIn('id', $main_categories);
});
});

Related

Check Eloquent wasChanged on hasMany/belongsTo Model relationship

I want to check the wasChanged() status of my child/detail models, just as I do with the parent/header model in the hasMany(parent) :: belongsTo (child) relationship.
I've got code that looks like this:
$parent = Parent::updateOrCreate([ ... ], [ ... ]);
if ($parent->wasChanged()) {
// do something useful
}
foreach ($contents as $child) {
$parent->children()->updateOrCreate([ keys ],[ data ]);
// Now I want to check if the Child model named Contents was changed.
// if ($parents->children()->wasChanged()) { ... // does not work
}
How can I accomplish this?
Not sure what $contents does, but, you could always do something like this to accomplish the idea of what you want done:
$parent = Parent::updateOrCreate([ keys ],[ data ]);
$parent->load('children');
if ($parent->wasChanged()) {
// do something useful
}
$parent->children()->updateOrCreate([ keys ],[ data ]);
foreach($parent->children() as $child) {
if ($child->wasChanged()) {
// do something useful
}
}
I'm not even sure this is a correct answer, but what I ended up doing and seems to be working is adding save() calls after each createOrUpdate() call. The Laravel documentation suggests this is not how it is supposed to work, but it's hard to argue with empirical evidence.
$parent = Parent::updateOrCreate([ keys ],[ data ]);
if ($header->wasChanged() || $header->wasRecentlyCreated) {
// Do interesting work
}
$parent->save();
foreach ($myInterestingData as $newChildData) {
$child = $header->children()
->updateOrCreate( ... keys/values from $newChildData ...);
if ($child->wasChanged() || $child->wasRecentlyCreated) {
// Do boring work
}
$child->save();
}

GroceryCRUD hide soft deleted records

By overriding the delete function of GroceryCRUD as below, we can easily soft-delete a record.
public function user() {
$crud = new grocery_CRUD();
$crud->set_table('cms_user');
$crud->set_subject('User List');
$crud->required_fields('user_name');
$crud->columns('user_name','email','real_name','active');
$crud->change_field_type('active', 'true_false');
$crud->callback_delete(array($this,'delete_user'));
$output = $crud->render();
$this->_example_output($output);
}
public function delete_user($primary_key) {
return $this->db->update(
'cms_user',
array('deleted' => '1'),
array('id' => $primary_key)
);
}
My question is, How do I hide the soft-deleted records in the Main View ??
Thank you.
The answer was easy... after some googling it is obvious I can use the where clause
$crud->where('deleted', '0');
Thank you all... works like a charm

Assign mongo selectors in find() dynamically

I have the following problem: I have an interface where a user can filter stuff out based on several inputs. There are 5 inputs. When an input is filled out I want to add it's value to the helper returning the collection. The problem I can't solve is how to do this dynamically. Sometimes the user might fill out one input, sometimes three, sometimes all 5. Within the find() method you can only write down meteor's syntax:
mongoSelector: fieldName,
This means you can only hardcode stuff within find(). But just adding all 5 selectors doesn't work, since if one of the values is empty, the find searches for an empty string instead of nothing.
I thought of doing conditionals or variables but both don't work within find because of the required syntax. What could I do to solve this?
var visitorName;
var visitorAge;
Session.set('visitorName', visitorName);
Session.set('visitorAge', visitorAgee);
Template.web.helpers({
visitors: function() {
return Visitors.find({ visitor_name: Session.get('visitorName'), visitor_age: Session.get('visitorAge') });
}
});
Template.web.events({
"change #visitor_name": function (event, template) {
visitorName = $(event.currentTarget).val();
}
});
Template.web.events({
"click #reset_filter": function (event, template) {
return Visitors.find();
$(input).val('');
}
});
http://jsfiddle.net/m5qxoh3b/
This one works
Template.web.helpers({
visitors: function() {
var query = {};
var visitorName = (Session.get('visitorName') || "").trim();
if (visitorName) {
query["visitor_name"] = visitorName;
}
//same thing for other fields
return Visitors.find(query);
}
});
Template.web.events({
"change #visitor_name": function (event, template) {
var visitorName = $(event.currentTarget).val();
Session.set('visitorName', visitorName);
}
});

How I can get search form value in Drupal 7

I've tried to implement a new module that catches the keys written in the default search form and displays other results than the default search result page. With these other results I will make an external query, which is put in a special block.
Any idea on how to do this?
I've tried to use a custom module making a "hook_alter_form " with no success.
In other words :
I have a function like this:
function my_function_name_form_alter(&$form,&$form_state,$form_id){
switch($form_id){
case 'search-block-form':
//Here i want to catch the text that i wrote in the search box
break;
}
}
Thank u!
You can alter the search query in order to show other results:
function mymodule_query_alter(QueryAlterableInterface $query){
$is_search = FALSE;
foreach ($query->getTables() as $table) {
if ($table['table'] == 'search_index') {
$is_search = TRUE;
}
}
if ($is_search) {
global $language;
$db_or = db_or();
$db_or->condition('n.type', 'event', '=');
$db_or->condition('n.type', 'real_sitio', '=');
$query->condition($db_or);
$query->condition('n.language' , $language->language, '=');
}
}
This is a bit performance killer so there's a patch for drupal at http://drupal.org/node/1435834 that adds a hook for making the alter directly in the search query:
So finally it would look like:
function mymodule_search_query_search_node_alter(&$query) {
$query->condition('n.type', 'article', '=');
}

StandardAnalyzer seems to not being involved when indexing data, NHibernate.Search

Im building a search function for an application with Lucene.NET and NHibernate.Search. To index the existing data I am using this method:
public void SynchronizeIndexForAllUsers()
{
var fullTextSession = Search.CreateFullTextSession(m_session);
var users = GetAll();
foreach (var user in users)
{
if (!user.IsDeleted)
{
fullTextSession.Index(user);
}
}
}
Where I have marked the fields I want to index with following attribute:
[Field(Index.Tokenized, Store = Store.Yes, Analyzer = typeof(StandardAnalyzer))]
public virtual string FirstName
{
get { return m_firstName; }
set { m_firstName = value; }
}
But when I then inspect the indicies in Luke the fields still have uppercases, commas etc. which should have been removed by the StandardAnalyzer.
Does anyone have know what I am doing wrong?
I had similiar problem to yours, but I've been trying to use WhitespaceAnalyzer. Setting it in Field attribute didn't work for me either.
I've ended up setting it globally. I am using FluentNHibernate for configuration and it looks like that:
this._sessionFactory =
Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005
.ConnectionString(cs => cs
// cut
.ShowSql()
)
.Mappings(m => m.FluentMappings
// cut
)
.ExposeConfiguration(cfg =>
{
// important part: lucene.net and nhibernate.search
cfg.SetProperty("hibernate.search.default.directory_provider", typeof(NHibernate.Search.Store.FSDirectoryProvider).AssemblyQualifiedName);
cfg.SetProperty("hibernate.search.default.indexBase", #"~\Lucene");
cfg.SetProperty("hibernate.search.indexing_strategy", "event");
cfg.SetProperty(NHibernate.Search.Environment.AnalyzerClass, typeof(WhitespaceAnalyzer).AssemblyQualifiedName);
cfg.SetListener(NHibernate.Event.ListenerType.PostUpdate, new FullTextIndexEventListener());
cfg.SetListener(NHibernate.Event.ListenerType.PostInsert, new FullTextIndexEventListener());
cfg.SetListener(NHibernate.Event.ListenerType.PostDelete, new FullTextIndexCollectionEventListener());
})
.BuildSessionFactory();
Take a look at NHibernate.Search.Environment.AnalyzerClass. Funny thing is that it won't work for generic fulltext queries (i think that Lucene will use StandardAnalyzer), but that's another story :).
Hope this helps.