In joomla 2.5 is there any built in function to fetch all article from the specific category.
I don't want to use custom query to fetch article from the database.
I would use the articles model
JLoader::import('joomla.application.component.model');
JModelLegacy::addIncludePath(JPATH_SITE.'/components/com_content/models', 'ContentModel');
$model = JModelLegacy::getInstance('Articles', 'ContentModel');
$model->getState();
$model->setState('list.limit', 10);
$articles = $model->getItems();
I'm not sure how're you're setting up your slider however to answer your actual question:
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('*')
->from($db->quoteName('#__content'))
->where($db->quoteName('catid') . ' = 2');
$db->setQuery($query);
$rows = $db->loadObjectList();
foreach ( $rows as $row ) {
echo $row->introtext;
}
There is a built in function to get articles using the route.php I believe which is what the likes of Accordions use and so on, however for the most simple method, use the above.
Note: Don't forget to change the catid value from 2 to whatever suits your needs.
Hope this helps
I create small function to get category and return all articles with custom fields
function getArticlesByCategory($categoryId, $limit = "")
{
if (is_int($limit) && !empty($limit)) {
$limit = "LIMIT $limit";
}
$articles = JFactory::getDBO()->setQuery('
SELECT
C.*,
CONCAT(
"{",
GROUP_CONCAT(CONCAT(\'"\',F.name,\'"\', ":",\'"\',V.value,\'"\')),
"}"
) AS \'additional_fields\'
FROM
#__content AS C
LEFT JOIN #__fields_values AS V
ON
V.item_id = C.id
LEFT JOIN #__fields AS F
ON
F.id = V.field_id
WHERE
C.catid = \'' . $categoryId . '\' AND F.context = "com_content.article"
GROUP BY
C.id ' . $limit
)->loadObjectList();
if($articles){
foreach ($articles as $article) {
$article->additional_fields = json_decode($article->additional_fields);
}
}
return $articles;
}
Usage
$categoryId = 9;
$limit = 4;
getArticlesByCategory(9,2);
Tested on Joomla! 3.8.11
I don't like solutions like this one, but Joomla! made me do it.
Check this out: /modules/mod_articles_category for a full-fledged (and fairly slow) implementation. You might want to make it simpler:
select introtext, params from #__content where catid=%s AND state=1 AND ...
(you might want to add some checks on publish_up fields etc, but if you're happy with managing published/unpublished and don't use publish_up / down you don't need to do this).
Make sure you implement the module correctly to leverage Joomla cache, even if this query is fast it's best to avoid repeating it adlib. Read this for more details on module's cache
If you are creating a module, you may just create a module that has a type Article Category. Then, on the right side, click on the Filtering Options and there, select the category you want to show.
Related
I have applied the method Additional Translation Approach in the database design.
With such structure of the tables, the code becomes more complex for per query.
My PHP code in models:
<?php
// SHOW ALL RECORDS
$this->db->select('m.id, m.title, m.content');
$table = 'blog';
if (MULTILINGUAL) {
$this->db->from($table.' AS m');
$this->db->select('t.title, t.content');
$this->db->join($table.'_translation AS t', 'm.id = t.parent_id', 'left');
$this->db->where('t.language_id', LANGUAGE);
$query = $this->db->get();
} else $query = $this->db->get($table.' AS m');
?>
So I want to change it's code...
When MULTILINGUAL is true, and with per query has column fields is title, content,...
$table = 'blog';
$this->db->select('id, title, content');
$query = $this->db->get($table);
it will automatically use the method JOIN with a table have suffix _translation (as my code above).
Otherwise, queries should be run as a normal query.
How can I do modified db class but don't affects core system of Codeigniter?
PHP code (using Codeigniter):
// Query 1:
$this->db->select('id, title, content');
$query = $this->db->get('blog');
// Query 2:
$this->db->select('id, title, content');
$this->db->where('id', 1);
$query = $this->db->get('blog');
Produces $this->db->last_query():
if (MULTILINGUAL) {
// Query 1:
// SELECT t.title, t.content FROM blog AS m LEFT JOIN blog_translation AS t ON m.id = t.parent_id WHERE t.language_id = 1
// Query 2:
// SELECT t.title, t.content FROM blog AS m LEFT JOIN blog_translation AS t ON m.id = t.parent_id WHERE t.language_id = 1 WHERE m.id = 1
else {
// Query 1:
// SELECT title, content FROM blog
// Query 2:
// SELECT title, content FROM blog WHERE id = 1
}
I want it to be completely automatic.
I think that could change the db class to solve this problem, but direct intervention into the core system is unstable (within core update)...
I truly appreciate your help in resolving my problem!
This might help you to work around I don't know how you were using that config file but can achieve that functionality as
function your_function($multilingual = false) {
$table = 'blog';
if ($multilingual === true) {
$this->db->select('t.title, t.content');
$this->db->join($table . '_translation AS t', 'm.id = t.parent_id', 'left');
$this->db->where('t.language_id', LANGUAGE);
$query = $this->db->get($table . ' AS m')->result_array();
} else {
$this->db->select('m.id, m.title, m.content');
$query = $this->db->get($table . ' AS m')->result_array();
}
return $query;
}
You could create a view and just call : $this->db->where('t.language_id', LANGUAGE); , but I don't know really if this is a better solution.
I'm new to mysql.
I wanted to develop a simple tagging system for my blog and came across this "Toxi" Solution of making 3 tables.
So, I have 3 tables:
`blog` containing `id` and `title`.
`blog_tags` containing `id` and `tags_id` and `blog_id`.
`tags` containing `id` and `name`.
tags_id is connected to Internal Relation to id in tags table.
Similarly, blog_id is connected to Internal Relation to id in blog table.
So, when in my function (where I get the array of all tags pertaining to a single blog) I execute a query for example (passing blog id as the parameter in the function),
$result = mysql_query("SELECT tags_id FROM blog_tags WHERE blog_id = '".$id."'");
$tags = array();
if($result === FALSE) {
die(mysql_error()); // TODO: better error handling
}
while($row = mysql_fetch_assoc($result)) {
$tags[] = I don't know what should come over here?
}
return $tags;
Or is there any other way to execute queries in this Toxi implementation?
UPDATED You need a simple JOIN. Your query should look like
SELECT bt.tags_id, t.name
FROM blog_tags bt JOIN tags t
ON bt.tags_id = t.id
WHERE bt.blog_id = n -- < n is an id of a blog
Here is SQLFiddle demo.
Now php is pretty straightforward
$sql = "SELECT bt.tags_id, t.name
FROM blog_tags bt JOIN tags t
ON bt.tags_id = t.id
WHERE bt.blog_id = $id";
$result = mysql_query($sql);
if($result === FALSE) {
die(mysql_error()); // TODO: better error handling
}
$tags = array();
while($row = mysql_fetch_assoc($result)) {
$tags[] = $row['name'];
}
...
On a side note: switch to PDO or mysqli. mysql_* extension is deprecated. In PDO you can use a syntactic sugar fetchAll(). And more importantly learn to use prepared statements. Right now your code is vulnerable to sql-injections.
I am trying to create an archives page for my blog, which is also still being built. I have three different MySQL tables I need to pull data from and 1 of them is unrelated from the other 2. I found a similar post here but seeing as how I am not very experienced with PHP I am not able to figure out how to convert that to what I need. I know this can easily be done by executing three different queries, but that will put an unnecessary load on the server and slow down page load times and everything else.
The 2 related categories are "blogs" and "categories" while the third is for a different application built into the blog called the "Brain Link"
Here are the two queries for the related tables:
$blogQuery = mysqli_query($link, "SELECT * FROM pub_blogs ORDER BY id DESC") or die ("Could not access DB: " . mysqli_error($link));
$row = mysqli_fetch_assoc($blogQuery);
$blogID = $link->real_escape_string($row['id']);
$title = $link->real_escape_string($row['title']);
$date = $link->real_escape_string($row['date']);
$category = $link->real_escape_string($row['category']);
$content = $link->real_escape_string($row['content']);
$blogID = stripslashes($blogID);
$title = stripslashes($title);
$date = stripslashes($date);
$category = stripslashes($category);
$content = stripslashes($content);
$catQuery = mysqli_query($link, "SELECT * FROM categories ORDER BY id DESC") or die ("Could not access DB: " . mysqli_error($link));
$row = mysqli_fetch_assoc($catQuery);
$catID = $link->real_escape_string($row['id']);
$catName = $link->real_escape_string($row['name']);
$description = $link->real_escape_string($row['descriptions']);
$catID = stripslashes($catID);
$catName = stripslashes($catName);
$description = stripslashes($description);
and here is the third unrelated query:
$brainQuery = mysqli_query($link, "SELECT * FROM brain_links ORDER BY id DESC") or die ("Could not access DB: " . mysqli_error($link));
$row = mysqli_fetch_assoc($brainQuery);
$brainID = $link->real_escape_string($row['id']);
$site_name = $link->real_escape_string($row['site_name']);
$site_url = $link->real_escape_string($row['site_url']);
$post_date = $link->real_escape_string($row['post_date']);
Is it possible to get data from all three of these with one query? If not can someone point me in the direction of somewhere that will tell me how to join the two related ones?
The blog table saves the category ID under the 'category' column to identify which category it belongs to
I appreciate any help or suggestions!
This will bring the data from two tables. How ever, from the third tables data can't be get
SELECT
*
FROM pub_blogs
LEFT JOIN categories on categories.id = pub_blogs .category
ORDER BY id DESC
Ajnd for the third table you can not get it because you can not make a link to any other table. If you change your table structure you can do it.
No you cant get data from 3 rd table using same query .
Mysql wants a mapping between two tables .
You can join the blog and category but not the brain links
For the first two tables do :
select * , c.id , c.name , c.descriptions from pub_blogs p join categories c on c.id = p.category order by id desc ;
For the third table as there is no mapping you cant join it .
Happy Coding :)
I'm building a simple web app at the moment that I'll one day open source. As it stands at the moment, the nav is generated on every page load (which will change to be cached one day) but for the moment, it's being made with the code below. Using PHP 5.2.6 and MySQLi 5.0.7.7, how more efficient can the code below be? I think joins might help, but I'm after advice. Any tips would be greatly appreciated.
<?php
$navQuery = $mysqli->query("SELECT id,slug,name FROM categories WHERE live=1 ORDER BY name ASC") or die(mysqli_error($mysqli));
while($nav = $navQuery->fetch_object()) {
echo '<li>';
echo ''. $nav->name .'';
echo '<ul>';
$subNavQuery = $mysqli->query("SELECT id,name FROM snippets WHERE category='$nav->id' ORDER BY name ASC") or die(mysqli_error($mysqli));
while($subNav = $subNavQuery->fetch_object()) {
echo '<li>';
echo ''. $subNav->name .'';
echo '</li>';
}
echo '</ul>';
echo '</li>';
}
?>
You can run this query:
SELECT c.id AS cid, c.slug AS cslug, c.name AS cname,
s.id AS sid, s.name AS sname
FROM categories AS c
LEFT JOIN snippets AS s ON s.category = c.id
WHERE c.live=1
ORDER BY c.name, s.name
Then iterate thru the results to create the proper heading like:
// last category ID
$lastcid = 0;
while ($r = $navQuery->fetch_object ()) {
if ($r->cid != $lastcid) {
// new category
// let's close the last open category (if any)
if ($lastcid)
printf ('</li></ul>');
// save current category
$lastcid = $r->cid;
// display category
printf ('<li>%s', $r->cslug, $r->cname);
// display first snippet
printf ('<li>%s</li>', $r->cslug, $r->sname, $r->sname);
} else {
// category already processed, just display snippet
// display snippet
printf ('<li>%s</a>', $r->cslug, $r->sname, $r->sname);
}
}
// let's close the last open category (if any)
if ($lastcid)
printf ('</li></ul>');
Note that I used printf but you should use your own function instead which wraps around printf, but runs htmlspecialchars thru the parameters (except the first of course).
Disclaimer: I do not necessarily encourage such use of <ul>s.
This code is just here to show the basic idea of processing hierarchical data got with one query.
First off, you shouldn't query your database in your view. That would be mixing your business logic and your presentation logic. Just assign the query results to a variable in your controller and iterate through it.
As for the query, yup a join can do that in 1 query.
SELECT * -- Make sure you only select the fields you want. Might need to use aliases to avoid conflict
FROM snippets S LEFT JOIN categiries C ON S.category = C.id
WHERE live = 1
ORDER BY S.category, C.name
This will get you an initial result set. But this won't give you the data nicely ordered like you expect. You'll need to use a bit of PHP to group it into some arrays that you can use in your loops.
Something along the lines of
$categories = array();
foreach ($results as $result) {
$snippet = array();
//assign all the snippet related data into this var
if (isset($categories[$result['snippets.category']])) {
$categories[$result['snippets.category']]['snippet'][] = $snippet;
} else {
$category = array();
//assign all the category related data into this var;
$categories[$result['snippets.category']]['snippet'] = array($snippet);
$categories[$result['snippets.category']]['category'] = $category;
}
}
This should give you an array of categories which have all the related snippets in an array. You can simply loop through this array to reproduce your list.
I'd try this one:
SELECT
c.slug,c.name,s.name
FROM
categories c
LEFT JOIN snippets s
ON s.category = c.id
WHERE live=1 ORDER BY c.name, s.name
I didnt test it, though. Also check the indexes using the EXPLAIN statement so MySQL doesnt do a full scan of the table.
With these results, you can loop the results in PHP and check when the category name changes, and build your output as you wish.
Besides a single combined query you can use two separate ones.
You have a basic tree-structure here with branch elements (categories table) and leaf elements (snippets table). The shortcoming of the single-query solution is that you get owner brach-element repeatedly for every single leaf element. This is redundant information and depending on the number of leafs and the amount of information you query from each branch element can produce large amount of additional traffic.
The two-query solution looks like:
$navQuery = $mysqli->query ("SELECT id, slug, name FROM categories WHERE live=1 ORDER BY name")
or die (mysqli_error ($mysqli));
$subNavQuery = $mysqli->query ("SELECT c.id AS cid, s.id, s.name FROM categories AS c LEFT JOIN snippets AS s ON s.category=c.id WHERE c.live=1 ORDER BY c.name, s.name")
or die (mysqli_error ($mysqli));
$sub = $subNavQuery->fetch_object (); // pre-reading one record
while ($nav = $navQuery->fetch_object ()) {
echo '<li>';
echo ''. $nav->name .'';
echo '<ul>';
while ($sub->cid == $nav->id) {
echo '<li>';
echo ''. $sub->name .'';
echo '</li>';
$sub = $subNavQuery->fetch_object ();
}
echo '</ul>';
}
It should print completely the same code as your example
$navQuery = $mysqli->query("SELECT t1.id AS cat_id,t1.slug,t1.name AS cat_name,t2.id,t2.name
FROM categories AS t1
LEFT JOIN snippets AS t2 ON t1.id = t2.category
WHERE t1.live=1
ORDER BY t1.name ASC, t2.name ASC") or die(mysqli_error($mysqli));
$current = false;
while($nav = $navQuery->fetch_object()) {
if ($current != $nav->cat_id) {
if ($current) echo '</ul>';
echo ''. $nav->cat_name .'<ul>';
$current = $nav->cat_id;
}
if ($nav->id) { //check for empty category
echo '<li>'. $nav->name .'</li>';
}
}
//last category
if ($current) echo '</ul>';
I'm pretty sure this is not possible in Zend Framework (I have searched the Web, the documentation and issue tracker) but I just want to make sure so I'm asking here.
$select = $this->select();
$select->union($select1, $select2);
That doesn't work of course. To explain what I need. I need to use UNION() to merge 2 tables in a SELECT query, I know I could just do:
$select = "$select1 UNION $select2";
The problem is that would return a string and I need to get a select object so I can use it with Zend_Paginator.
I have already solved the issue by modifying my database architecture but I'm just curious if there is some workaround for this.
Here's what I've done to make a union:
$select = $this->select();
//common select from both sides of the union goes here
$select1 = clone($select);
//select1 specifics here
$select2 = clone($select);
//select 2 specifics here
$db = $this->getAdapter();
$pageselect = $db->select()->union(array("($select1)", "($select2)"));
Remember Db_Select's __toString will print out the SQL generated by that select, to help you debug.
Zend_Db_Select has a union method so I'd have thought it is possible, if you can build your query using a select object. I haven't used Zend_Db_Select (or the table subclass) with union but I'd imagine you can do something like
$select = $this->select()
->where('blah')
->union($sql);
a complete example:
public function getReservationById($id)
{
if(!$id) return null;
$sql = $this->table->select();
$sql->union(array(
$this->table->select()->where('id=?', $id),
$this->tableFinished->select()->where('id=?', $id),
$this->tableCanceled->select()->where('id=?', $id),
$this->tableTrashed->select()->where('id=?', $id)
));
echo $sql->__toString();
}
and the generated query:
SELECT reservations.* FROM reservations WHERE (id='5658') UNION SELECT res_finished.* FROM res_finished WHERE (id='5658') UNION SELECT res_cancel.* FROM res_cancel WHERE (id='5658') UNION SELECT res_trash.* FROM res_trash WHERE (id='5658')
This practical example shows a function that returns a rowset of either latest or if a available favourite blog entries of a specific year (artwork blog):
public function fetchBestOf($year)
{
$selectLatest = $this->select()->where('isHidden = 0')
->where('YEAR(dateCreated) = ' . $year)
->where('isHighlight = 0');
$selectHighlights = $this->select()->where('isHidden = 0')
->where('YEAR(dateCreated) = ' . $year)
->where('isHighlight = 1');
$selectUnion = $this->select()->union(array($selectLatest, $selectHighlights), Zend_Db_Select::SQL_UNION_ALL)
->order('isHighlight DESC')
->order('dateCreated DESC')
->order('workID DESC')
->limit('5');
$rowset = $this->fetchAll($selectUnion);
return $rowset;
}
The best way Zend suggest is like follows....
$sql = $this->_db->select()
->union(array($select1, $select2,$select3))
->order('by_someorder');
echo $sql->__toString();
$stmt = $db->query($sql);
$result = $stmt->fetchAll();
echo will show the query
Here $select1, $select2, $select3 can be different select queries with same
number of columns...
This is how it works for me:
$select1 = $this->select();
$select2 = $this->select();
After getting the necessary data in both queries the UNION syntax goes like this:
$select = $this->select()->union(array('('.$select1.')', '('.$select2.')'));