Closed aryamaharta closed 7 years ago
It's working for me - what do you see in the developer tools? Any JavasScript errors?
@aryamaharta - also tested this and syntax seems fine, so I'll close the issue, as it doesn't seem to be a bug in the software. But please reply to get to the bottom of this.
Cheers!
Same problem here. We deployed the application from staging to production, same environment (aws server clones) the filters are called in staging environment but not at the production system. Everything else works fine. Any ideas?
Sorry @axelzuzek , no idea, no. There shouldn't be any difference between staging and production. Filters should work fine. So the AJAX request is sent&received but the filter is not applied? Can you check if the POST parameters have been sent in the AJAX request?
Yes I debuged this already, the params are present, also the fulltext search is working but non of the filters defined in the crudcontroller setup are called.
the filters seem to be set too:
public function search()
{
print_r($this->crud->filters());
>>>
Backpack\CRUD\PanelTraits\FiltersCollection Object
(
[items:protected] => Array
(
[0] => Backpack\CRUD\PanelTraits\CrudFilter Object
(
[name] => active
[type] => toggleArchive
[label] => Aktiv
[placeholder] =>
[values] =>
[options] => Array
(
[type] => toggleArchive
[name] => active
[label] => Aktiv
)
[currentValue] => true
[view] => crud::filters.toggleArchive
)
[1] => Backpack\CRUD\PanelTraits\CrudFilter Object
(
[name] => archived
[type] => toggleArchive
[label] => Archiviert
[placeholder] =>
[values] =>
[options] => Array
(
[type] => toggleArchive
[name] => archived
[label] => Archiviert
)
[currentValue] =>
[view] => crud::filters.toggleArchive
)
)
)
Hmm... Well them I'm pretty sure you make some mistake in your filtering code. In the closure, I mean.
You can see if that's the case by moving the code that actually does the filtering (whatever is inside the closure) outside the addFilter() method, with some manual data.
Ex:
$this->crud->addFilter([ // select2 filter
'name' => 'id_periode',
'type' => 'dropdown',
'label'=> 'Periode'
], function() {
return \App\Models\Periode::all()->pluck('periode', 'id')->toArray();
}, function($value) {
- $this->crud->addClause('where', 'id_periode', $value);
});
+ $this->crud->addClause('where', 'id_periode', '2');
The source of the problem: the https termination of the production system is done at the loadbalancer, the laravel server only gets http requests instead of https
The Filters Trait checks:
$route = $this->route;
switch ($this->request->url()) {
case url($this->route):
if ($this->request->getMethod() == 'POST' ||
$this->request->getMethod() == 'PATCH') {
return false;
}
return true;
break;
url($this->route.'/search') => https://domain/admin/ad/search $this->request->url() => http://domain/admin/ad/search
It might have something to do with TrustedProxies ?
Can you give it a look ?
Thanks
Thx that solved the problem for me:
Solution (working for Laravel >= 5.5)
1) Configure App\Http\Middleware\TrustProxies;
protected $proxies = '**';
protected $headers = Request::HEADER_X_FORWARDED_ALL;
(For older Laravel Versions see https://github.com/fideloper/TrustedProxy)
2)
AppServiceProvider
function boot()
Make sure that
\URL::forceScheme('https')
must NOT be set.
Glad you figured it out @axelzuzek . Thanks for the solution @pxpm .
Is there a way to do this while forcing URL::forceScheme('https') ?
Thanks, @axelzuzek! Worked for me with
protected $proxies = '**';
and SET(!!!)
\URL::forceScheme('https')
Laravel 5.6
Same problem here. We deployed the application from staging to production, same environment (aws server clones) the filters are called in staging environment but not at the production system. Everything else works fine. Any ideas?
Is there a way to do this while forcing URL::forceScheme('https') ?
We must have URL::forcmeScheme('https') acitve and we have the same problem with the filters as described.
The solution for us was to overwrite the Trait from Backpack. It works by adding an alias at the register-method of your AppServiceProvider (\App\Providers\AppServiceProvider.php. If you don't have this class you can create it with artisan).
/**
* Register any application services.
*
* @return void
*/
public function register()
{
$this->app->booting(function() {
$loader = AliasLoader::getInstance();
$loader->alias('Backpack\CRUD\PanelTraits\Filters', 'App\Vendor\Backpack\CRUD\PanelTraits\Filters');
});
}
Overwrite the trait with this functions:
/**
* Determine if the current CRUD action is a list operation (using standard or ajax DataTables).
* @return bool
*/
public function doingListOperation()
{
$route = $this->route;
switch ($this->removeProtocol($this->request->url())) {
case $this->removeProtocol(url($this->route)):
if ($this->request->getMethod() == 'POST' ||
$this->request->getMethod() == 'PATCH') {
return false;
}
return true;
break;
case $this->removeProtocol(url($this->route.'/search')):
return true;
break;
default:
return false;
break;
}
}
public function removeProtocol($url) {
$disallowed = array('http://', 'https://');
foreach($disallowed as $d) {
if(strpos($url, $d) === 0) {
return str_replace($d, '', $url);
}
}
return $url;
}
It removes the protocol from the urls. Now it works for any protocol.
Is there a way to do this while forcing URL::forceScheme('https') ?
We must have URL::forcmeScheme('https') acitve and we have the same problem with the filters as described.
The solution for us was to overwrite the Trait from Backpack. It works by adding an alias at the register-method of your AppServiceProvider (\App\Providers\AppServiceProvider.php. If you don't have this class you can create it with artisan).
/** * Register any application services. * * @return void */ public function register() { $this->app->booting(function() { $loader = AliasLoader::getInstance(); $loader->alias('Backpack\CRUD\PanelTraits\Filters', 'App\Vendor\Backpack\CRUD\PanelTraits\Filters'); }); }
Overwrite the trait with this functions:
/** * Determine if the current CRUD action is a list operation (using standard or ajax DataTables). * @return bool */ public function doingListOperation() { $route = $this->route; switch ($this->removeProtocol($this->request->url())) { case $this->removeProtocol(url($this->route)): if ($this->request->getMethod() == 'POST' || $this->request->getMethod() == 'PATCH') { return false; } return true; break; case $this->removeProtocol(url($this->route.'/search')): return true; break; default: return false; break; } } public function removeProtocol($url) { $disallowed = array('http://', 'https://'); foreach($disallowed as $d) { if(strpos($url, $d) === 0) { return str_replace($d, '', $url); } } return $url; }
It removes the protocol from the urls. Now it works for any protocol.
This worked for us, thanks!
This is by far the most annoying bug to fix in Backpack. I followed @aceArt-GmbH's example, but had to copy/paste the entire trait to make it work. I also reduced the trim method to a simple preg replace:
/**
* Strip http/s protocols from URL.
*
* @param string $url
*
* @return string
*/
public function removeProtocol(string $url) {
return preg_replace('%^https?://%i', '', $url);
}
We also had to copy/paste the entire code to make it work. I only posted the changes I made. It is not an optimal solution but it's one for now. Please let us know when it will be fixed in the core. I would like to remove that code. @FrittenKeeZ i like your function better :)
@FrittenKeeZ , @aceArt-GmbH , doesn't this fix it for you, in a more general way? https://github.com/Laravel-Backpack/CRUD/issues/701#issuecomment-402462045
As far as I understand this, the problem is that url()
is not outputting the right protocol for you guys. If so, this problem could happen elsewhere in your app too. Not just here.
@tabacitu the problem is that the proxy sends the request as http
, but the base URL does have https
, so when you do url('whatever')
it will have https
as protocol - so essentially you'll end up comparing https://mydomain.com/whatever
with http://mydomain.com/whatever
.
For it to work without the overrides, the base URL needs to be with http
, but that will break all links and assets requests through https
- so no, the comment you refer to won't fix it unfortunately.
I'm currently working on project using laravel backpack and try to use crud filter on the data. But the function that filtering data not being called after dropdown selected. Here is my
Is there something wrong with my code or am i missing something ?