I am using http://datatables.net/and https://github.com/yajra/laravel-datatables-oracle. When I try search I get a popup with an "Ajax error" I seemed to have narrowed it down to being an issue when ever there is a join in the query.
Here is method used for the Ajax request (removed fields for simplicity):
$leads = Lead::leftJoin('lead_status', 'leads.status', '=', 'lead_status.id')
->select('leads.id', 'leads.email', 'lead_status.status');
This works fine as I said it is only when I try search do I get the error, I don't get it when sorting or paging through results.
When there is no join in the query then I don't get any issues.
Been on this for a while now and not sure what to do..
When using a join statement, you have to specify in js the fully qualified name of field. You should use table.column pattern. See example code below:
$('#posts-table').DataTable({
processing: true,
serverSide: true,
ajax: 'joins-data',
columns: [
{data: 'id', name: 'posts.id'},
{data: 'title', name: 'posts.title'},
{data: 'name', name: 'users.name'},
{data: 'created_at', name: 'posts.created_at'},
{data: 'updated_at', name: 'posts.updated_at'}
]
});
And on your controller
public function getJoinsData()
{
$posts = Post::join('users', 'posts.user_id', '=', 'users.id')
->select(['posts.id', 'posts.title', 'users.name', 'users.email', 'posts.created_at', 'posts.updated_at']);
return Datatables::of($posts)
->editColumn('title', '{!! str_limit($title, 60) !!}')
->editColumn('name', function ($model) {
return \HTML::mailto($model->email, $model->name);
})
->make(true);
}
Related
I have a model Article (id, title, content, created_at).
I can do:
$articles = Article::orderBy('created_at','DESC')->skip($start)->take($length)
->get(['id', 'title', 'content', 'created_at']);
But I want to get 2 random additional articles for each article . How can I do it?
For example:
{
{
id: 1,
title: 'title1'
content: 'qwqwqwqwqwqwqwq',
created_at: '2022-11-25 14:04:35',
related: {
id: 77,
title: 'title77'
content: 'fhhhfh',
created_at: '2022-11-26 17:04:57',
},
{
id: 15,
title: 'title15'
content: 'kkkkkkkk',
created_at: '2022-11-27 15:04:45',
},
},
...
}
Since get() method of Eloquent's Builder returns a collection (Check here), You can use map() method to add random items you mentioned.
Article::orderBy('created_at','DESC')->skip($start)->take($length)
->get(['id', 'title', 'content', 'created_at'])->map(function ($articles){
$articles['related'] = Article::inRandomOrder()->take(2)->get();
return $articles;
});
You can just simple assign the related articles in a loop:
foreach ($articles as $article) {
$article->related = $articles->whereNotIn('id', [$article->id])->random(2)->values();
}
If you want to load the related articles by relationship, you can create a column named related_id in article table and set default value to 1
Then, create a relationship on Article model:
public function related(){
return $this->hasMany(Article::class, 'related_id', 'related_id');
}
Then, you can load the related articles by using with function (remember to add related_id to the array of get function):
$articles = Article::orderBy('created_at','DESC')->with(['related' => function($query){
$query->inRandomOrder()->take(2);
}])->skip($start)->take($length)->get(['id', 'title', 'content', 'created_at', 'related_id']);
I'm using Yajra datatables with serverside true, but page load very slow (afraid because of distinct count). I tried solution here by removing ->get() and it load faster but this causing another problem, where the input searching (smart: true) return error, not functioning. Anyone can help?
Here is my code:
$links = Link::with('owner')
->withCount(['clicks as uniqueClicks' => function($q) {
$q->select(DB::raw('count(distinct(ip_address))'));
}])
->where('account_id', $account_id)
->orderBy('created_at','desc')
->get();
return Datatables::of($links)->make();
Is it possible to optimize this code? maybe change from select raw distinct to groupBy? or do this more on eloquent way?
My mistake for not stating the full errors and in the error mentioned about laravel relationship column not found.
Here is the documentation https://yajrabox.com/docs/laravel-datatables/master/relationships
columns: [
// columns according to JSON
{ data: '' },
{ data: 'title' },
{ data: 'user_name', name: 'user.manage.name' }, <-- name = relationship column
{ data: 'link' },
{ data: 'created_at', "searchable": false },
{ data: 'action' }
],
So removing the ->get() do make your page load faster.
$links = Link::with('owner')
->withCount(['clicks as uniqueClicks' => function($q) {
$q->select(DB::raw('count(distinct(ip_address))'));
}])
->where('account_id', $account_id)
->orderBy('created_at','desc');
return Datatables::of($links)->make();
I have a users table, roles and users_roles as a join / pivot table. I am tryin to create a query to retrive all the users that HAVE NOT these roles: interventor, editor, chief
At the moment this is my query but I am not getting the desiered results, because users with these roles still coming.
$users = TableRegistry::getTableLocator()->get('Users');
$allUsers = $users->find('all', ['order' => ['Users.id ASC']])->select([
'id',
'name',
'surname',
])
->contain('Roles', function (Query $q) {
return $q
->select(['slug'])
->notMatching('Users.Roles', function ($q) {
return $q->where(['Roles.slug NOT IN' => ['interventor', 'editor', 'chief']]);
});
});
Thank you
Ok I found asolution.
Just adding an innerJoin to the query.
->innerJoinWith('Roles')->where(['Roles.slug NOT IN' => ['interventor', 'editor', 'chief']]);
I have two model News and Category in one to many relationship.
News.php
public function newsCategory()
{
return $this->belongsTo(Category::class, 'category');
}
Now I'm trying to get all the news with a specific category as follows
$news = News::select('id', 'heading', 'body', 'image', 'category', 'created_at')
->with(['newsCategory' => function ($query) {
$query->where('title', 'international');
}])->get();
dd($t->toArray());
But its printing all the news, as follows
Laravel version : 7.30
Doc ref: https://laravel.com/docs/7.x/eloquent-relationships#constraining-eager-loads
Use whereHas
$news = News::select('id', 'heading', 'body', 'image', 'category', 'created_at')
->with(['newsCategory'])
->whereHas('newsCategory',function ( $query){
$query->where('title', 'international');
})
->get();
Ref: https://laravel.com/docs/7.x/eloquent-relationships#querying-relationship-existence
I'm using Laravel datatables on a website.
Data is loaded through AJAX. On my frontend code I select which columns the table needs:
var dataTable = $('#products-table').DataTable({
serverSide: true,
ajax: {
'url': '{!! route('myroute') !!}',
},
columns: [
{data: 'brand_model', orderable: false},
{data: 'status', className: 'dt-body-center', orderable: false},
{data: 'sale_price', className: 'dt-body-right'},
{data: 'image_url', orderable: false, className: 'table-image'},
{data: 'actions', orderable: false, className: 'table-actions'}
],
order: [[1, "desc"]]
});
On the backend, I'm currently building the response as follows:
$products = $user->products(); // Eloquent relationship
return DataTables::of($products)
->editColumn('status', function ($product) { ... })
->addColumn('actions', function ($product) { ... })
...
->make(true);
Everything is displayed correctly, but I analyzed the ajax response and I noticed that every column and even the user relationship of every product is returned. Basically, for each row in the table I return a whole bunch of useless data that should not be available on the frontend.
Is there a way to force the datatable builder to only include those fields and not everything else?
The only thing I could do is to only select the desired fields in the eloquent query:
$products = $user->products()->select(['status', 'image_url', ... ]);
But this solution is not feasible, because I need most of the fields and relationships to build the additional columns (i.e. actions). The field should be filtered after the required columns are built.
While an automatic solution would be perfect, I would also consider a manual solution (where I have to manually specify which fields to include in the response)
You can use the package's default method only:
return Datatables::of($products)->->only([
'col1',
'col2'
])
Only the specified columns in this method will be sent in the response.