Is it possible to have some sort of pagination within the URL in Concrete 5. I see many CMS's such as Wordpress and Drupal etc that have such a feature.
At the moment my blogs are the following:
/blog?ccm_paging_p_b348=2
and the way I want it to be is:
/blog/page/1 ... /blog/page/2 etc (or something similar)
Any tips or advice would be appreciated
Your only choice is to create a custom page type for your blog page and then a custom controller for that which handles the pagination.
Please see this page:
http://www.concrete5.org/documentation/developers/pages/mvc-approach
And particularly the "Page Types" section under "Controllers". It explains how to create your page type controllers. For them, you can create similar functions that you would for normal single pages, so you can paginate the results there according to the parameters you get from the URL.
This example is for 5.6 and earlier:
<?php
class BlogPageTypeController extends Controller {
public function view($page=1) {
$pageIndex = intval($page)-1;
if ($pageIndex < 0) {
$pageIndex = 0;
}
$pageList = new PageList();
$pageList->setItemsPerPage(25);
$this->set('pages', $pageList->getPage($pageIndex));
}
}
And then you would use the $pages variable in your view to go through the pages:
<?php foreach($pages as $page) : ?>
<h2><?php echo $page->getCollectionName()</h2>
<?php endforeach; ?>
Related
I would like to customize my template for Joomla 3.7 so that I can use the new feature of Joomla 3.7, Custom fields (com_fields), and display and format them via CSS in my template where I need to display them.
Can someone suggest me the PHP code I should use in the template to display field(s), some example please.
Thanks in advance.
For everyone getting late to the party. In case you want to use your custom form fields in a Module-Override (which really are the only way to modify j!-templates, so google 'joomla template override') you can use this handy snippet:
<?php
JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php');
$jcFields = FieldsHelper::getFields('com_content.article', $item, true);
$itemCustomFields = array();
foreach($jcFields as $field) {
$itemCustomFields[$field->name] = $field->rawvalue;
}
?>
Now you cna use your customfields like so: itemCustomFields['customFieldName1']
Haven't tested in article overrides. May soon, if so, this will get updated.
certainly not the right way to do it but I had the same need and I found a work around based on https://www.giudansky.com/news/12-coding/146-joomla-custom-fields
Copie default.php from /components/com_content/views/article/tmpl/default.php to
templates/YOUR_THEME/html/com_content/article/default.php
Add following code line 25 :
$myCustomFields = array();
foreach($this->item->jcfields as $field) {
$myCustomFields[$field->name] = $field->value;
}
$GLOBALS['myCustomFields'] = $myCustomFields;
Typically you put on a global var the content of fields attached to your article.
On your template page you can know retrieved value of your field.
just print_r($GLOBALS['myCustomFields']); to view the content of your array.
That will do the trick waiting for a better answer..
This is absolutely the wrong way to do this I think but I was tearing my hair out so i came up with this quick db query to return custom field values in the template. surely this violates some kind of joomla protocol?
obviously this assumes you can get $articleid into your template already which is the Current ID of your article.
I too am waiting on a better solution but hope this helps
$db =& JFactory::getDBO();
$sql = "select * from #__fields_values where `item_id` = $articleid";
$db->setQuery($sql);
$fieldslist = $db->loadObjectList();
echo $fieldslist[0]->value;
echo $fieldslist[1]->value;
echo $fieldslist[your field ID here]->value;
I found it was easiest to follow how com_fields does it in its rendering code. In Joomla!3.7+, you'll find it in [joomla_root]/components/com_fields/layouts/fields/render.php .
Here are the main parts you need to reproduce the formatting that Joomla has:
JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php');
<dl class="fields-container">
<?php foreach ($this->item->jcfields as $field) : ?>
<?php // If the value is empty do nothing ?>
<?php if (!isset($field->value) || $field->value == '') : ?>
<?php continue; ?>
<?php endif; ?>
<?php $class = $field->params->get('render_class'); ?>
<dd class="field-entry <?php echo $class; ?>">
<?php echo FieldsHelper::render($context, 'field.render', array('field' => $field)); ?>
</dd>
<?php endforeach; ?>
</dl>
This loops through all available tags for the component or article. The nice thing about this method is it still applies the render classes you include with the fields.
Make sure to set Automatic Display to Do not automatically display on your fields; otherwise you will see them twice on your page view.
If you want to just target specific fields to show, you can use the name of the field to target it. (The label and value pair is underneath.) See the field Joomla docs for more info.
I implemented this small function to get specific custom field values:
function getCustomFieldValue($field_name, $article_id, $default_value = '') {
// Load custom field list
$fields = FieldsHelper::getFields('com_content.article', $article_id, true);
$field_ids = array_column($fields, 'id', 'name');
$model = JModelLegacy::getInstance('Field', 'FieldsModel', array('ignore_request' => true));
// Return the value if the field exists, otherwise the default
return array_key_exists($field_name, $field_ids)
? $model->getFieldValue($field_ids[$field_name] , $article_id)
: $default_value;
}
Usage:
$some_field_value = getCustomFieldValue('some-field-name', $some_article_id);
Optimization: I placed the function into a helper class, implemented the variables $fields, $field_ids and $model static and checked if they are already loaded to prevent redundant loading of the same data.
I've been playing around with pagination using arrays in php.
I have an array of posts that I use to break the content of a page up into smaller chunks. It works and returns the content as I would like.
<?php
// let's paginate data from an array...
$posts = array(
// array of posts
"blog/posts/06-19-tues.php",
"blog/posts/06-16-sat.php",
"blog/posts/05-26-sat.php",
"blog/posts/05-23-wed.php",
"blog/posts/05-09-wed.php"
);
// how many records should be displayed on a page?
$records_per_page = 3;
// include the pagination class
require 'zebra/Zebra_Pagination.php';
// instantiate the pagination object
$pagination = new Zebra_Pagination();
// the number of total records is the number of records in the array
$pagination->records(count($posts));
// records per page
$pagination->records_per_page($records_per_page);
// here's the magick: we need to display *only* the records for the current page
$posts = array_slice(
$posts,
(($pagination->get_page() - 1) * $records_per_page),
$records_per_page
);
?>
<?php foreach ($posts as $index => $post):?>
<?php include $post; ?>
<?php endforeach?>
<?php
// render the pagination links
$pagination->render();
?>
My question is now how to link to the individual posts from elsewhere on the site. Since they will, ultimately move from page to page, linking directly to the static file won't work. At first, I had given each post a unique id and used that to link to the post but that won't work now since the link will change, dynamically.
I've looked at array_search() and it looks promising but I don't understand it's use enough to get it to produce a hyperlink.
I'm not sure I've phrased this question all that well. apologies if I don't make much sense.
If I understand you correctly, I think something like this will work:
if (isset($_REQUEST['page']) {
$found = array_search($_REQUEST['page'], $posts);
if ($found) {
$pagination->set_page(floor($found/$records_per_page)+1);
}
}
Then you can use a link like
$link = 'whatever';
I am using the php framework codeigniter.
I am attempting to create a here is an example:
animals/feline/lion
animals/feline/tiger
animals/feline/snow-leopard
animals/canine/wolf
animals/canine/coyote
Where both genus (feline) and species (lion) are both retrieved from a database and animals is a controller. I have models that place genus and species in their respective arrays. I also wish to have views for each step along the breadcrumb as follows:
animals
animals/feline
animals/canine
Any help would be greatly appreciated. I just looked at autocrumb and all it was as for displaying the breadcrumb control structure on the view, and not what I want.
I'd use URi routing., as another approach than __remap(), which is better, but I just wanted to give another choice
$route['animals/(:any)/(:any)'] = "animals/method/$1/$2";
In you animals controller you have
function method($genus,$species)
{
$data['breadcrumb'] = 'animals -> '.$genus.' -> '.$species.
$this->load->view('breadcrumb', $data);
$this->load->view('animals/'.$genus.'/'.$species);
}
view breadcrumb.php:
<div id="breadcrumb">
<?php echo $breadcrumb;?> <!-- Display: animals -> feline -> lion -->
</div>
View folder contains:
breadcrumb.php
animals /
feline /
feline.php
canine/
wolf.php
Is this what you were looking for?
EDIT after comments:
SO looks like we've mistaken what you wanted. If you're retrieving those variables from DB, then you could do like this:
function index()
{
$this->load->view('animals/index');
}
function genus($genus)
{
$data['genus_data'] = $this->your_model->load_genus_data($genus);
$this->load->view('animals/genus',$data);
}
function species($genus,$species)
{
$data['genus_data'] = $this->your_model->load_genus_data($genus);
$data['species_data'] = $this->your_model->load_species_data($species);
$this->load->view('animal/genusspecies',$data);
}
In your view genus.php (in folder animal):
<?php $genus_data->name;?> is an animal that...Here's a pic in its habitat.
In your view genusspecies.php (in folder animal):
<?php $species_data->name;?> is a species of genus <?php $genus_data->name;?>....
all those might be html snippets you load from database;
Your routing might look like this then:
$route['animal'] = "animal";
$route['animal/(:any)'] = "animal/genus/$1";
$route['animal/(:any)/(:any)'] = "animal/species/$1/$2";
If I were you, I'll go about this way. Do I got it better or am I still wrong somewhere?
Add a _remap() function to your animals controller
if($this->uri->segment(3) === FALSE)
{
$this->genus();
}
else
{
$this->species();
}
This assumes you have a method called genus() and a method called species()
_remap() docs:
http://codeigniter.com/user_guide/general/controllers.html#remapping
URI Library docs:
http://codeigniter.com/user_guide/libraries/uri.html
redirect('animals/' . $genus . '/' . $species);
in the controller i have :
$paginator = Zend_Paginator::factory($mdlPost->getPosts($this->moduleData->accordion, 'name ASC'));
if(isset($params['cities'])) {
$paginator->setCurrentPageNumber(intval($params['cities']));
}
$paginator->setItemCountPerPage(4);
$this->view->posts = $paginator;
in the view's i have some thing like this :
if ($this->posts != null) {?>
<div id="cities_accord" class="news">
<?php echo $this->partialLoop('partials/post-min.phtml', $this->posts); ?>
</div>
<?php echo $this->paginationControl($this->posts,
'Sliding',
'public/pagination_cont.phtml');
}
the partial/post-min.phtml
<?php
$color = array(1=>'spring',2=>'summer',3=>'autumn',4=>'winter');
?>
<div id='<?php echo $color[$this->partialCounter] ?>' class="accordion_post">
<?php
$link = Digitalus_Uri::get(false, false, array('openCity' =>
$this->id));//$color[$this->partialCounter]));
?>
<h1 class="accordion_post_title"><?php echo $this->title ?></h1>
<p><?php echo $this->teaser ?> <i>read more</i></p>
</div>
the pagination_cont.phtml taken from this link zend ( http://framework.zend.com/manual/en/zend.paginator.usage.html )
will show links that will pass params to the controller to fetch the corresponding whole page which is working alright for now
but i want to change this so that i will be able ajaxify the returned ( i.e. only a single paginated value rather than reloading the whole page ) results how can i do that using jquery and what should i change ..
** EDIT: it would be nice to have a fail-save ,if possible, for browsers(users) that disabled javascript to see the same thing by reloading the page (i.e. keeping the current status for if(javascript_not_enabled ))**
This is what I've done in the past.
First, setup the AjaxContext action helper to enable the html context on your controller action.
Add a .ajax.phtml view that just contains the section of markup that may be replaced via AJAX as well as the pagination control links. You can probably just copy this out of your normal view. Replace that section in your normal view with something like
<div id="reloadable-content">
<?php echo $this->render('controller/action.ajax.phtml') ?>
</div>
This will ensure that your initial and any non-AJAX requests will still include the right content. The <div> id is purely for referencing the loadable block in JavaScript.
Also make sure you include your JS file (using headScript) in the normal view only.
Now, in your JS file, unobtrusively add the appropriate event binding to the paginator links. As you'll be replacing the pagination control section in order to reflect the correct current page and other links, it's probably best to do this using the jQuery live binding. I'm also assuming you'll wrap the pagination control with some kind of identifiable element (<div class="pagination-control"> for example)
$('.pagination-control').find('a').live('click', function(e) {
var link = $(this);
$('#reloadable-content').load(link.attr('href'), { format: 'html' });
return false;
});
Keep in mind that in using this method, you will lose the ability to navigate the paged requests using the normal back / forward browser buttons. You will also lose the ability to bookmark pages directly (though you could always provide a permanent link to the current page as part of the AJAX loaded content).
You can use something like the jQuery history plugin if you're really concerned but that will require more client-side work.
Another caveat is that the above will only work with pagination links. If you want to use a form with dropdown page selection, you need to add another event handler for the submission.
GOT IT and big Thanks to #Phil Brown :
in the controller int() change the response type to json
class NewsController extends Zend_Controller_Action
{
public function init()
{
$contextSwitch = $this->_helper->getHelper('contextSwitch');
$contextSwitch->addActionContext('list', 'JSON')
->initContext();
}
// ...
}
public listAtcion() {
// .............
$paginator = Zend_Paginator::factory($mdlPost->getPosts($this->moduleData->accordion, 'name ASC'));
if(isset($params['cities'])) {
$paginator->setCurrentPageNumber(intval($params['cities']));
}
$paginator->setItemCountPerPage(4);
$post = array();
foreach($paginator as $post ) {
$post[] = $post;
}
$this->view->post = $paginator;
#TODO //add a check here for non-ajax requests (#improvment)
$this->view->posts = $paginator;
}
in one of the views (most probably in the pagination_cont.phtml) on the pagination controller add the ajax links
<?= $this->ajaxLink (
$this->url('cities'=>$this->page_num),array('id'=>'div_id','complete'=>'js_method(json_data)','method'=>post) ,array('format'=>'JSON'));
and add a JavaScript function of js_method(json_data) to modify the div with id = 'div_id' with a json data
function js_method(json_data) {
var content = parse.JSON(json_data);
$('#div_id').html('');
//fill it with the reposnse content some thing like $('#div_id').append(content);
}
I dont understand what the layout is, in the view. I asked a question previously on the subject of templating in PHP, but I still dont quite understand. I assume that you create a general layout for the site and then include each specific view within that layout.... I would like to know how to go about doing this. Also, are should the templates be made using just html, because I also looked at these things called helpers.... I'm just confused on the View part of the MVC, and the actual templates and how they're made. I learn best with examples, If you guys have any.
Also, a more important question, lets say I had a form that a user saw only if he was logged in, would I control that in the view, or in the controller?
So Would i do
in the controller
include 'header';
if(isset($_SESSION['userID'])){
include 'form';
}
include 'footer';
or
in the template
<html>
<?php if(isset($_SESSION['user_id'])): ?>
<form>....</form>
<?php endif;?>
</html>
EDIT
So, is there an include statement from within the layout to see the specific view template? how so?
a layout is whatever you have around your main content area. Usually on a normal website it would be any sidebar,header,footer. Most of MVC framework provide the layout to avoid to repeat those parts in all views.
You can imagine if like you have two view cascaded
you actual view is rendered, this content is saved
the layout view (all the items around the content) are rendered and your content is included in that output
for your login question actually your would have to do both
on the controller and the view
$this->view->isLogged = isset($_SESSION['userID']);
in the view
<?php if($isLogged): ?>
<form>....</form>
<?php endif;?>
I hesitate to answer this question only because of the religious fervor that surrounds it.
To get a really good understanding of the issues behind the general concepts see This Wiki Discussion Page This is the discussion page around the wiki MVC article.
Here is the rule of thumb I like to follow (BTW I use CodeIgniter and it kind of sounds like you are too):
The "view" should have virtually no logic. It should only be HTML (in the web world) with peppered PHP that simply echos variables. In your example you would break out the form into its own view and the controller would determine if was loaded or not.
I like to look at it this way: The view should have no concept of where the data comes from or where it is going. The model should be view agnostic. The controller meshes data from the model and provides it to the view - and it takes input from the view and filters it to the model.
Here is a quick and dirty (untested - but it should get the point across) example:
Theapp.php (The App controller)
class Theapp extends Controller
{
var $_authenticated;
var $_user;
var $_menu; // array of menus
function __construct()
{
session_start();
if (isset($_SESSION['authenticated']) && $_SESSION['authenticated'])
{
$this->_authenticated = $_SESSION['authenticated']; // or some such thing
$this->_user = $_SESSION['user'];
}
$this->_menu = array("Logout", "Help", "More");
parent::__construct();
$this->loadView("welcome"); // loads primary welcome view - but not necessarily a complete "html" page
}
function index()
{
if (!$this->_authenticated)
$this->loadView("loginform");
else
{
$viewData['menu'] = $this->_menu;
$viewData['user'] = $this->_user;
$this->loadView("menu", $viewData);
}
}
function login()
{
/* code to authenticate user */
}
function Logout() { /* code to process Logout menu selection */ }
function Help() { /* code to process Help menu selection */ }
function More() { /* code to process More menu selection */ }
}
welcome.php
<h1> Welcome to this quick and dirty app!</h1>
All sorts of good HTML, javascript, etc would be put in here!
loginform.php
<form action"/Theapp/login" method="post">
User: <input id='user' name='user'>
Pass: <input id='pass' name='pass' type='password'>
<input type='submit'>
</form>
menu.php
Hi <?= $user ?>!<br>
Here's your menu<br>
<? foreach ($menu as $option) { ?>
<div class='menuOption'><a href='/Theapp/<?=$option?>'><?=$option?></a></div>
<? } ?>
Hope this helps.
If your not using a framework, then a simple way to have a layout and a view can be like so:
<?php
function layout($layout_params) {
extract($layout_params);
# Remember: $layout_content must be echoed for the view to be seen.
ob_start();
include "layout_page.php";
$html = ob_get_contents();
ob_end_clean();
return $html;
}
function view($view_params) {
extract($view_params);
ob_start();
include "home_page.php";
$html = ob_get_contents();
ob_end_clean();
return $html;
}
#
# The variable $parameters is extracted and $params becomes a variable in the view as an array,
# $logged_in is also now avaiable in the view
#
$parameters = array("params" => array("name" => "joe"), "logged_in" => false);
$view_content = view($parameters); # => Returns the HTML content for home_page.php
# Now we need the layout content to include the view:
# The layout file will expect a variable called $layout_content to be the html view.
# So we need to set $layout_content to be $view_content
$parameters["layout_content"] = $view_content;
# We no longer need $view_content so we can unset the variable
unset($view_content);
# When $paramters is extracted it will have $layout_content as a variable:
$layout_content = layout_view($paramters); # => Returns the HTML content for the layout_page.php
# Now send the results to the browser
echo $layout_content;
?>