I'm a Symfony beginner & I'm trying to load my contact from the database using the Doctrine Query Builder as follows:
ContactRepository.php:
public function getcontactByLimit($offset, $limit)
{
$queryBuilder = $this->_em->createQueryBuilder()
->select('contact')
->from($this->_entityName, 'contact')
->setFirstResult( $offset )
->setMaxResults( $limit )
$query = $queryBuilder->getQuery();
$results = $query->getResult();
return $results;
}
DefaultController.php:
$contacts = $repository->getContactByLimit(0, 3);
Now I want to get all contacts I have in the database but just 3 by 3, what means I'm supposed to change the offset value at every loop (to 3 then 6 then 9...)
Have you any idea how to do it ?
It seems for me, that you want to load objects in parts to save memory.
For that, you can use an Iterator:
$query = $queryBuilder->getQuery();
$iterator = $query->iterate();
return $iterator;
And iterate in your Controller
foreach ($iterator as $row) {
}
What will happen, is that doctrine uses PDO and select your result but not read it out directly. There is a cursor on the ResultSet of the Database, which is moving on each iteration. So your PHP-Application will get each Row from Database one by one.
To get 3 by 3 packages, you could use the internal position:
$currentPackage = array();
foreach ($iterator as $position => $row) {
if($position % 3){
// do here something with your 3er package before unset
$currentPackage = array();
$entityManager->clear(); // clear doctrine, could free memory
}
$currentPackage[] = $row;
}
That what I did, & it works fine !
DefaultController.php:
$offset = 0;
$limit = 2;
$sizeData /= $limit;
for( $i = 0; $i < $sizeData; $i++)
{
$contacts = $repository->getListByLimit($offset, $limit);
$sender->setContacts($contacts);
$offset += $limit;
}
ContactRepository.php:
public function getListByLimit($offset, $limit)
{
$queryBuilder = $this->_em->createQueryBuilder()
->select('contact')
->from($this->_entityName, 'contact')
->setFirstResult( $offset )
->setMaxResults( $limit );
$query = $queryBuilder->getQuery();
$results = $query->getResult();
return $results;
Related
How I can use paginate() with this query?
$result = DB::select(DB::raw(" select a.user_id, a.user_email,
a.user_account_status, a.created_at, b.s_account_limit AS account_limit,
c.consumed_limit, ((b.s_account_limit*1024) - c.consumed_limit) AS
remaining_limit FROM upload_limits as b, users AS a JOIN user_upload_limits as
c WHERE (a.user_id=c.user_id) AND a.user_type='Simple'"));
You may use ->paginate() method or if you want to create a pagination manually, you would do something like:
$perPage = $request->input("per_page", 10);
$page = $request->input("page", 1);
$skip = $page * $perPage;
if($take < 1) { $take = 1; }
if($skip < 0) { $skip = 0; }
$basicQuery = DB::select(DB::raw(" select a.user_id, a.user_email, a.user_account_status, a.created_at, b.s_account_limit AS account_limit, c.consumed_limit, ((b.s_account_limit*1024) - c.consumed_limit) AS remaining_limit FROM upload_limits as b, users AS a JOIN user_upload_limits as c WHERE (a.user_id=c.user_id) AND a.user_type='Simple'"));
$totalCount = $basicQuery->count();
$results = $basicQuery
->take($perPage)
->skip($skip)
->get();
$paginator = new \Illuminate\Pagination\LengthAwarePaginator($results, $totalCount, $take, $page);
return $paginator;
You can also add a custom sort method that you pass in your array result of DB::raw along with your params:
public function sort($array_of_objects, $sort_by=null, $order, $page)
{
$collection = collect($array_of_objects);
if ($sort_by)
{
if ($order=='desc') {
$sorted = $collection->sortBy(function($role) use ($sort_by)
{
return $role->{$sort_by};
})->reverse();
} else if ($order=='asc') {
$sorted = $collection->sortBy(function($role) use ($sort_by)
{
return $role->{$sort_by};
});
}
} else {
$sorted = $collection;
}
$num_per_page = 20;
if (!$page) {
$page = 1;
}
$offset = ( $page - 1) * $num_per_page;
$sorted = $sorted->splice($offset, $num_per_page);
return new Paginator($sorted, count($array_of_objects), $num_per_page, $page);
}
First of all I'm wondering if this is even possible in Laravel?
I have this code:
$master_array = $_POST['master_search_array'];
$count = count($master_array);
$master_string = '';
for($i=0; $i<$count; $i++) {
if($master_array[$i] == "Dining"){
$master_string .= "where('dining', 'dining')";
}
if($master_array[$i] == "Party"){
$master_string .= "where('party','party')";
}
....ETC you get the point
}
$tours = DB::table('tours')->$master_string->get();
return $tours;
So at the end I should get something like this:
$tours = DB::table('tours')->where('dining', 'dining)->where('party','party')->get();
How can I do this in laravel, it gives me an error, no matter if I pass it as $master_string or {{$master_string}}.
There is no need for master string. Just use the query builder how it's meant to be used...
$master_array = $_POST['master_search_array'];
$count = count($master_array);
$query = DB::table('tours');
for($i=0; $i<$count; $i++) {
if($master_array[$i] == "Dining"){
$query->where('dining', 'dining');
}
if($master_array[$i] == "Party"){
$query->where('party', 'party');
}
}
$tours = $query->get();
return $tours;
Use the ability to add wheres to the query along the way.
DB::table('tour')->where(function($query) use ($master_array)
{
foreach($master_array as $k => $v) {
if($v == "Dining"){
$query->where('dining','dining');
}
if($v == "Party"){
$query->where('party','party');
}
}
})
->get();
I currently have a method inside my "car class" that display the car:
static function getCars(){
$autos = DB::query("SELECT * FROM automoviles");
$retorno = array();
foreach($autos as $a){
$automovil = automovil::fromDB($a->marca, $a->modelo, $a->version, $a->year, $a->usuario_id, $a->kilometraje, $a->info,
$a->hits, $a->cilindrada, $a->estado, $a->color, $a->categoria, $a->precio, $a->idAutomovil);
array_push($retorno, $automovil);
}
return $retorno;
}
In my index.php I call that function
foreach(car::getCars() as $a){
That allows me to display the info this way ( of course inside the foreach I have a huge code with the details I'll display.
Is there a way to implement a pagination to that thing so I can handle 8 cars per page, instead of showing all of them at the same page?
You can add a $limit and $page parameter on your function so that it will only return a maximum of $limit number of items starting from $limit * $page(or will call it the $offset). You also need to add a function to get the total number of rows you have for automoviles table.
static function getCars($page = 0, $limit = 8){
$offset = $limit * max(0, $page - 1);
//replace this with prepared statement
$autos = DB::query("SELECT * FROM automoviles LIMIT $offset, $limit");
$retorno = array();
foreach($autos as $a){
$automovil = automovil::fromDB($a->marca, $a->modelo, $a->version, $a->year, $a->usuario_id, $a->kilometraje, $a->info,
$a->hits, $a->cilindrada, $a->estado, $a->color, $a->categoria, $a->precio, $a->idAutomovil);
array_push($retorno, $automovil);
}
return $retorno;
}
static function getTotal()
{
//query to get total number of rows in automoviles table
}
In your index.php do this:
foreach(car::getCars((isset($_GET['page']) ? $_GET['page'] : 1)) as $a){
...
}
and add the pagination links.
$total = car::getTotal();
if($total > 8) {
for($i = 1; $i <= intval(ceil(1.0 * $total / $limit)); $i++) {
echo '' . $i . ';
}
}
I have a model a method in my Model as
public function selectWhereLimitOffset($table_name, $where = NULL, $limit, $offset)
{
if ($where) {
$this->db->where($where);
}
$this->db->order_by('post_id', "desc");
if($limit)
$this->db->limit($limit, $offset);
$result = $this->db->get($table_name);
return $result->result();
}
I'm calling this method from this function in my controller:
public function exams($page_id = NULL)
{
$offset = 0;
if($page_id == NULL)
$offset = 1;
else
$offset = ($page_id * 10);
$limit = 10;
$data['main_content'] = 'dashboard/exams';
$data['page_errors'] = FALSE;
$where = NULL;
$data['results_exam'] = $this->Fetch->selectWhereLimitOffset('exam', $where, $limit, $offset);
$data['results_count_total'] = $this->Fetch->getCount('exam');
$this->load->view('includes/template_su', $data);
}
Now the weird thing here is, the method selectWhereLimitOffset() works fine if called from other similar methods in my controller. But when called from this method exams(), it doesn't fetch the data from the table. A similar method that work perfectly fine is:
public function posts($page_id = NULL)
{
$offset = 0;
if($page_id == NULL)
$offset = 1;
else
$offset = ($page_id * 10);
$limit = 10;
$data['main_content'] = 'dashboard/posts';
$data['page_errors'] = FALSE;
$where = NULL;
$data['results_post'] = $this->Fetch->selectWhereLimitOffset('post', $where, $limit, $offset);
$data['results_count_total'] = $this->Fetch->getCount('post');
$this->load->view('includes/template_su', $data);
}
One more thing, the next statement:
$data['results_count_total'] = $this->Fetch->getCount('exam');
does return the count of rows from the table, so that proves that there's no issue with the table name. The table has only one row, if that might help.
The output of the data array is as follows:
Array
(
[main_content] => dashboard/exams
[page_errors] =>
[results_exam] => Array
(
)
[results_count_total] => 1
)
Please help.
Solved the problem. Just had to change the offset value from 1 to 0. Thats it.
Right away I would say, that I read this question Doctrine2 Paginator, but it doesn't give me enough information regarding the title of my question.
When I used Doctrine1 I was getting the result with such code for example:
$list = $this->query
->addSelect( 'SQL_CALC_FOUND_ROWS *' )
->offset( ( $this->currentPage - 1 ) * $this->perPage )
->limit( $this->perPage )
->execute( array(), \Doctrine_Core::HYDRATE_ARRAY_SHALLOW );
$totalRecords = SqlCalcFoundRowsEventListener::getFoundRowsCount();
$this->totalPages = ceil( $totalRecords / $this->perPage );
and it was great.
Now, when using Doctrine2 I'm confused on how should I get total amount of records with same query as limited result for current page.
Any help/advice would be greatly appreciated.
The paginator usage is as following:
$paginator = new \Doctrine\ORM\Tools\Pagination\Paginator($query);
$totalItems = count($paginator);
$pagesCount = ceil($totalItems / $pageSize);
// now get one page's items:
$paginator
->getQuery()
->setFirstResult($pageSize * ($currentPage-1)) // set the offset
->setMaxResults($pageSize); // set the limit
foreach ($paginator as $pageItem) {
echo "<li>" . $pageItem->getName() . "</li>";
}
Or some other loop:
for ($i=0; $i < $pagesCount; $i++) {
if ($currentPage == ($i+1)) {
$pagination1 .= '<li class="active">'.($i+1).'</li>';
}else{
$pagination1 .= '<li>'.($i+1).'</li>';
}
}