Cakephp 3 - Remove empty post from pagination - pagination

I'm working on multi language website.
In the English version of the website all works properly, because I entered translations.
$blogPosts = $this->BlogPosts->find('all')->where(['BlogPosts.active' => 1]);
$this->set('blogPosts',$this->paginate($blogPosts));
If I changed the language of website I would like to remove all the posts whose translation of the title is not entered.
I tried this, but it does not work:
$blogPosts = $this->BlogPosts->find('all')->where(['BlogPosts.active' => 1,'BlogPosts.title IS NOT' => null]);
$this->set('blogPosts',$this->paginate($blogPosts));
Still printed posts without titles.
How to solve this problem?

Try this conditions:
public function index()
{
$this->paginate['conditions'] = ['BlogPosts.active' => true , 'BlogPosts.title IS NOT' => null, 'BlogPosts.title !=' => ' '];
$this->paginate['order'] = ['BlogPosts.id' => 'desc'];
$this->paginate['limit'] = 4;
$blogPosts = $this->paginate($this->BlogPosts);
$this->set(compact('blogPosts'));
$this->set('_serialize', ['blogPosts']);
}
Query:
SELECT *
FROM blogPosts BlogPosts
WHERE (
BlogPosts.active = 1
AND BlogPosts.title IS NOT NULL
AND BlogPosts.title != ''
)
ORDER BY BlogPosts.id desc
LIMIT 4 OFFSET 0

I think faced with simmilar issue before. The pagination didn't worked as I excepted when I set order, limit together with custom where condition.
Try this:
$this->paginate['order'] = ['BlogPosts.id' => 'desc'];
$this->paginate['limit'] = 4;
$query = $this->BlogPost->find()
->select(['id', 'title', 'active'])
->where(['BlogPost.active' => true, 'BlogPost.title IS NOT' => null, 'BlogPost.id !=' => ''])
$data = $this->paginate($query);
$this->set('BlogPost', $data);

Related

Prestashop hiding category description because of pagination

I've noticed something weird about our prestashop store - the category description that's displayed on page 1 disappears when the customer switches to any other page.
https://vipkoszulka.pl/91-pielegniarka
https://vipkoszulka.pl/91-pielegniarka?page=2
(below the products, above the footer. the div contains category title as well)
Furthermore, if you go from page 1 to any other page and then back to page 1, the category description is gone as well. The div that's supposed to contain all the info (#js-product-list-bottom) is just empty.
Can someone point me out which controller is responsible for this? I found part of the script that's responsible for pagination in ProductListingFrontController.php:
ProductSearchQuery $query,
ProductSearchResult $result
) {
$pagination = new Pagination();
$pagination
->setPage($query->getPage())
->setPagesCount(
(int) ceil($result->getTotalProductsCount() / $query->getResultsPerPage())
)
;
$totalItems = $result->getTotalProductsCount();
$itemsShownFrom = ($query->getResultsPerPage() * ($query->getPage() - 1)) + 1;
$itemsShownTo = $query->getResultsPerPage() * $query->getPage();
$pages = array_map(function ($link) {
$link['url'] = $this->updateQueryString(array(
'page' => $link['page'] > 1 ? $link['page'] : null,
));
return $link;
}, $pagination->buildLinks());
//Filter next/previous link on first/last page
$pages = array_filter($pages, function ($page) use ($pagination) {
if ('previous' === $page['type'] && 1 === $pagination->getPage()) {
return false;
}
if ('next' === $page['type'] && $pagination->getPagesCount() === $pagination->getPage()) {
return false;
}
return true;
});
return array(
'total_items' => $totalItems,
'items_shown_from' => $itemsShownFrom,
'items_shown_to' => ($itemsShownTo <= $totalItems) ? $itemsShownTo : $totalItems,
'current_page' => $pagination->getPage(),
'pages_count' => $pagination->getPagesCount(),
'pages' => $pages,
// Compare to 3 because there are the next and previous links
'should_be_displayed' => (count($pagination->buildLinks()) > 3),
);
}
But it only deals with products, not the description itself.
This is not really an issue. As long as you don't have a description on the second page, it's ok from the SEO perspective. The most important is to have a description available on the first page when you visit the page directly.

Elastic Search-Search string having spaces and special characters in it using C#

I am looking for ElasticSearch nest query which will provide exact match on string having spaces in it using C#.
for example - I want to search for a word like 'XYZ Company Solutions'. I tried querystring query but it gives me all the records irrespective of search result. Also i read on the post and found that we have to add some mappings for the field. I tried 'Not_Analyzed' analyzer on the field but still it does not worked.
Here is my code of C#
var indexDefinition = new RootObjectMapping
{
Properties = new Dictionary<PropertyNameMarker, IElasticType>(),
Name = elastic_newindexname
};
var notAnalyzedField = new StringMapping
{
Index = FieldIndexOption.NotAnalyzed
};
indexDefinition.Properties.Add("Name", notAnalyzedField);
objElasticClient.DeleteIndex(d => d.Index(elastic_newindexname));
var reindex = objElasticClient.Reindex<dynamic>(r => r.FromIndex(elastic_oldindexname).ToIndex(elastic_newindexname).Query(q => q.MatchAll()).Scroll("10s").CreateIndex(i => i.AddMapping<dynamic>(m => m.InitializeUsing(indexDefinition))));
ReindexObserver<dynamic> o = new ReindexObserver<dynamic>(onError: e => { });
reindex.Subscribe(o);**
**ISearchResponse<dynamic> ivals = objElasticClient.Search<dynamic>(s => s.Index(elastic_newindexname).AllTypes().Query(q => q.Term("Name","XYZ Company Solutions")));** //this gives 0 records
**ISearchResponse<dynamic> ivals1 = objElasticClient.Search<dynamic>(s => s.Index(elastic_newindexname).AllTypes().Query(q => q.Term(u => u.OnField("Name").Value("XYZ Company Solutions"))));** //this gives 0 records
**ISearchResponse<dynamic> ivals = objElasticClient.Search<dynamic>(s => s.Index(elastic_newindexname).AllTypes().Query(#"Name = 'XYZ Company Solutions'"));** //this gives all records having fields value starting with "XYZ"
If anyone have complete example or steps in C# then can you please share with me?
Have you tried the match_phrase query?
The query DSL the request is the following:
"query": {
"match_phrase": {
"title": "XYZ Company Solutions"
}
}
In C# try the following:
_client.Search<T>(s => s
.Index(IndexName)
.Types(typeof (T))
.Query(q => q.MatchPhrase(m => m
.OnField(f => f.Name)
.Query("XYZ Company Solutions"))));
Check the official documentation for more information:
http://www.elastic.co/guide/en/elasticsearch/guide/master/phrase-matching.html#phrase-matching
Please refer the below code ,I think this will meet your requirements.
Here I have created and mapped index with dynamic template and then did the XDCR.
Now all string fields will be not_analysed.
IIndicesOperationResponse result = null;
if (!objElasticClient.IndexExists(elastic_indexname).Exists)
{
result = objElasticClient.CreateIndex(elastic_indexname, c => c.AddMapping<dynamic>(m => m.Type("_default_").DynamicTemplates(t => t
.Add(f => f.Name("string_fields").Match("*").MatchMappingType("string").Mapping(ma => ma
.String(s => s.Index(FieldIndexOption.NotAnalyzed)))))));
}
Thanks
Mukesh Raghuwanshi
It looks like you just need to refresh the new index following the re-indexing operation.
Using your code example (and your first term query), I was seeing the same result -- 0 hits.
Adding the following Refresh call after the reindex.Subscribe() call results in a single hit being returned:
objElasticClient.Refresh(new RefreshRequest() { });

Phalcon: find() + Paginator

I have a MySQL database and a table within it. The mission is to set a method, which will receive 2 parameters(?user_id=...&action_id...) and search for records matching these two fields or one of them, if only one was set(?user_id=...), then paginate them and send them to the action view. I've just started to learn Phalcon a week ago, have done some research here and there, read the docs and still don't realize how i can do this.
What i've done so far:
public function searchAction()
{
$userID = $this->request->get("user_id", "int", 0);
$actionID = $this->request->get("action_id", "int", 0);
$currentPage = 1;
$currentPage = (int) $_GET["page"];
$parameters = array(
'user_id' => $userID,
'action_id' => $actionID
);
$o = History::find($parameters);
$paginator = new Paginator(array(
"data" => $o,
"limit" => 10,
"page" => $currentPage
));
$page = $paginator->getPaginate();
$this->view->setVar("page", $page);
}
Pagination is working somehow but the search is not, why?
First parameter in the method find() or findFirst() must be a string to set conditions to the query.
In your case, you can search like that:
$o = History::find('user_id = "'.$userID.'" AND action_id = "'.$action_id.'"');
But, if you want add more parameters, then you need to pass array and the first element must contain search conditions:
$o = History::find(array(
'user_id = "'.$userID.'" AND action_id = "'.$action_id.'"',
'limit' => 10,
'order' => 'user_id ASC'
));
Referring to official documentation http://docs.phalconphp.com/en/latest/reference/models.html#binding-parameters
$conditions = "user_id = ?1 AND action_id = ?2";
$parameters = array(1 => userID, 2 => $actionID);
$o = History::find(array(
$conditions,
"bind" => $parameters
));
Index of parameters array must match number of placeholder in conditions string.

How to implement a pagination for a search module in Zend Framework 2?

I have a module Search in my ZF2 application. The user fills in a search form out and gets a list of courses.
Now I'm adding the pagination to the module. The paginator is basically working: I can retrieve data over it and the pagination is displayed correctly (pagelinks 1-7 for 70 found courses with the dafault setting 10 items per page).
But it's still not usable. When I click on a pagelink, the form POST data is lost. I know -- it cannot work the way, how I implemented it (see the code below). But I have no idea, how to do it correctly, in order to eep checking the form data and nonetheless be able to use pagination.
That is my code:
Table class Search\Model\CourseTable
class CourseTable {
...
// without pagination
// public function findAllByCriteria(CourseSearchInput $input) {
// with pagination
public function findAllByCriteria(CourseSearchInput $input, $pageNumber) {
...
$select = new Select();
$where = new Where();
$having = new Having();
...
// without pagination
// $resultSet = $this->tableGateway->selectWith($select);
// return $resultSet;
// with pagination
$adapter = new \MyNamespqce\Paginator\Adapter\DbSelect($select, $this->tableGateway->getAdapter());
$paginator = new \Zend\Paginator\Paginator($adapter);
$paginator->setCurrentPageNumber($pageNumber);
return $paginator;
}
...
}
Search\Controller\SearchController
class SearchController extends AbstractActionController {
public function searchCoursesAction() {
$form = $this->getServiceLocator()->get('Search\Form\CourseSearchForm');
$request = $this->getRequest();
if ($request->isPost()) {
$courseSearchInput = new CourseSearchInput();
$form->setInputFilter($courseSearchInput->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$courseSearchInput->exchangeArray($form->getData());
// without pagination
// $courses = $this->getCourseTable()->findAllByCriteria($courseSearchInput);
// with pagination
$page = $this->params()->fromRoute('page');
$paginator = $this->getCourseTable()->findAllByCriteria($courseSearchInput, $page);
} else {
$paginator = null;
}
} else {
$paginator = null;
}
return new ViewModel(array(
'form' => $form,
// without pagination
// 'courses' => $courses,
// with pagination
'paginator' => $paginator,
'cities' => ...
));
}
...
}
How to get it working?
I also have the same problem, and I have solved it. But this is not good way. May be the idea will help you.
I solved it as follow: (Search pagination for Zend tutorial album module)
I build two action in controller named "search" and "index".
Whenever the search form submitted, it always post the value to search action. Search action build the url with search parameters, and redirect to index to disply search result.
And when the pagination links clicked, then posted values are passed through url. So whenever index action ask for search parameters, it always get the values in same format.
I defined route as follows:
'album' => array(
'type' => 'segment',
'options' => array(
'route' => '/album[/:action][/:id][/page/:page][/order_by/:order_by][/:order][/search_by/:search_by]',
'constraints' => array(
'action' => '(?!\bpage\b)(?!\border_by\b)(?!\bsearch_by\b)[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
'page' => '[0-9]+',
'order_by' => '[a-zA-Z][a-zA-Z0-9_-]*',
'order' => 'ASC|DESC',
),
'defaults' => array(
'controller' => 'Album\Controller\Album',
'action' => 'index',
),
),
),
There is a parameter named "search_by", which will keep all search parameters as a json string. This is the point, which is not good I know, but have not find any other way yet.
"Search" action build this string as -
public function searchAction()
{
$request = $this->getRequest();
$url = 'index';
if ($request->isPost()) {
$formdata = (array) $request->getPost();
$search_data = array();
foreach ($formdata as $key => $value) {
if ($key != 'submit') {
if (!empty($value)) {
$search_data[$key] = $value;
}
}
}
if (!empty($search_data)) {
$search_by = json_encode($search_data);
$url .= '/search_by/' . $search_by;
}
}
$this->redirect()->toUrl($url);
}
And next index action decode the string, do necessary action, and also send the json string to view.
public function indexAction() {
$searchform = new AlbumSearchForm();
$searchform->get('submit')->setValue('Search');
$select = new Select();
$order_by = $this->params()->fromRoute('order_by') ?
$this->params()->fromRoute('order_by') : 'id';
$order = $this->params()->fromRoute('order') ?
$this->params()->fromRoute('order') : Select::ORDER_ASCENDING;
$page = $this->params()->fromRoute('page') ? (int) $this->params()->fromRoute('page') : 1;
$select->order($order_by . ' ' . $order);
$search_by = $this->params()->fromRoute('search_by') ?
$this->params()->fromRoute('search_by') : '';
$where = new \Zend\Db\Sql\Where();
$formdata = array();
if (!empty($search_by)) {
$formdata = (array) json_decode($search_by);
if (!empty($formdata['artist'])) {
$where->addPredicate(
new \Zend\Db\Sql\Predicate\Like('artist', '%' . $formdata['artist'] . '%')
);
}
if (!empty($formdata['title'])) {
$where->addPredicate(
new \Zend\Db\Sql\Predicate\Like('title', '%' . $formdata['title'] . '%')
);
}
}
if (!empty($where)) {
$select->where($where);
}
$album = $this->getAlbumTable()->fetchAll($select);
$totalRecord = $album->count();
$itemsPerPage = 2;
$album->current();
$paginator = new Paginator(new paginatorIterator($album));
$paginator->setCurrentPageNumber($page)
->setItemCountPerPage($itemsPerPage)
->setPageRange(7);
$searchform->setData($formdata);
return new ViewModel(array(
'search_by' => $search_by,
'order_by' => $order_by,
'order' => $order,
'page' => $page,
'paginator' => $paginator,
'pageAction' => 'album',
'form' => $searchform,
'totalRecord' => $totalRecord
));
}
All the sorting and paging url contain that string.
If you know all the searching paarameters before, then you can define that at route, and pass like the same way without json string. As I have to build a common search, I have build a single string.
Source code for "Album search" is available in git hub at https://github.com/tahmina8765/zf2_search_with_pagination_example.
Live Demo: http://zf2pagination.lifencolor.com/public/album
#Sam & #automatix in the question comments are both right. My suggestion (though I'm looking for a simpler alternative) is to construct a segment route, which covers all of the options that you're likely to need and start with a standard form POST request.
Then, after the request is validated, pass the form data to the paginationControl helper as follows:
$resultsView = new ViewModel(array(
'paginator' => $paginator,
'routeParams' => array_filter($form->getData())
));
Then, in your view template, set the route parameters in the paginationControl view helper:
<?php echo $this->paginationControl($paginator, 'Sliding', 'paginator/default',
array('routeParams' => $routeParams)
) ?>
I've used array_filter here because it's a really simple way of removing any element from the form data that's null, empty or so on. That way you don't pass in extra data that you don't need.

Infinitescroll to finish after a certain number of posts

I am using Paul Irish's infinitescroll with masonry js on a wordpress site. It is a site with a lot of content. I want infintescroll to stop adding new content when it reaches post number 40 and to give the "No additional items" message at that point. I tried to customize the wordpress loop to only return 40 posts but that did not seem to work.
I thought that maybe one of the options in infinitecroll might do the trick but the infintescroll documentation is very sparse. For example, there is an infinitescroll option in the "loading" init section called "finished: undefined" Is it possible to change that parameter to stop the scrolling after a certain number of content items?
Is there some other obvious way to control when infinitescroll stops loading new content?
Any assistance would be greatly appreciated.
In the Administration -> Settings -> Reading you can set Blog pages show at most to 40.
With code:
Two ways I've done Masonry by numbers like your question I've had success with the following:
limit posts_per_page in your query arguments
$args = array(
'posts_per_page' => 40,
'offset' => 5,
'orderby' => 'post_date',
'order' => 'DESC',
'exclude' => 'none',
'post_type' => 'post',
'post_status' => 'publish',
'suppress_filters' => true
);
$posts = new WP_Query( $args );
if ( $posts -> have_posts()) {
while ( $posts -> have_posts() ) : $posts->the_post(); {
//do stuff with the posts returned here
}
}
or by incrementing:
$counts = 0 ;
$posts = new WP_Query( $args );
if ( $posts -> have_posts()) {
while ( $posts -> have_posts() ) : $posts->the_post(); {
//do stuff with the posts returned here
$counts = ++;
if($counts == 40) { return }
}
}

Resources