How can I SELECT from multiple tables in CodeIgniter - mysql

I have three tables: (to keep it simple I'll only show the relevant fields)
Articles (id, title, text, author)
Comments (id, article_id, text, author)
Users (user_id, user_type, first_name, last_name, email, password)
In the articles table, because an author can have multiple articles, I only store the author's user_id from the users table, and I do the same for the comments table.
My problem is when I run an ActiveRecord query in the articles_model to get all articles along with that articles associated comments, and then echo the author in my view with $row->author, I only get the author's user_id which is 1, 2, 3, etc etc.
How do I go into the users table (different table) in that same query and get the authors actual first_name and last_name and return that?
Here's my code:
Controller:
$data['articles'] = $this->getArticles();
$this->load->view('articles_view', $data);
function getArticles() {
$this->load->model('articles_model');
$articles = $this->articles_model->getAllArticles();
return $articles;
}
articles_model:
function getAllArticles() {
$this->db->where('id', $this->uri->segment(3));
$query = $this->db->get('articles');
return $query;
}
articles_view:
<?php foreach($articles->result() as $row) { ?>
<?php echo $row->author ?>
<?php echo $row->text ?>
<?php } ?>
I have a ton of other fields, but this is an extremely stripped down version for simplicity's sake.
If I echo the above $row->author, I'm only going to get the user_id. I need to get the user's name from the users table instead. Surely I don't have to do another separate function call and pass more information into the view. Any help here would be greatly appreciated and would actually open up a world for me :)

Try this (or just have an idea):
I assumed that user_id from your users table is foreign key of articles and comments table since you said that the authors and commentators user_id are stored in users table.
On your controller:
$data['articles'] = $this->getArticles();
$this->load->view('articles_view', $data);
function getArticles() {
$this->load->model('articles_model');
$articles = $this->articles_model->getArticlesById();
return $articles;
}
On your model:
// this will get the article of a certain author
function getArticlesById()
{
$this->db->where('id', $this->uri->segment(3));
$q = $this->db->get('articles');
if($q->num_rows() > 0)
{
$q = $q->row_array();
$result = $this->getCommentsAndAuthors($row);
return $result;
}
return 0;
}
// this will get the comments of each articles of the author and the author of the comments
function getCommentsAndAuthors($row)
{
$result = $data = array();
$this->db->select('c.*, u.firstname, u.lastname');
$this->db->from('users u');
$this->db->where('u.id', $row['user_id']);
$this->db->join('comments c', 'c.id = u.id');
$q = $this->db->get();
foreach($q->result_array() as $col)
{
$data[] = $col;
}
$result['article'] = $row;
$result['comments'] = $data;
return $result;
}
I'm not sure if its work but that's the idea.

I have found a solution that works well for me which I will post and try to explain.
My Controller is like this:
function fullArticle()
{
$data['article'] = $this->getArticleDetail();
$data['comments'] = $this->getNewsTrendsComments();
$this->load->view('inner_view', $data);
}
function getArticleDetail()
{
$this->load->model('articles_model');
$articles = $this->articles_model->getArticles();
return $articles;
}
function getComments()
{
$this->load->model('articles_model');
$comments = $this->articles_model->getComments();
return $comments;
}
articles_model:
function getArticles()
{
$this->db->where('id', $this->uri->segment(3));
$query = $this->db->get('articles');
return $query;
}
function getComments()
{
$this->db->select('*');
$this->db->from('comments w');
$this->db->where('article_id', $this->uri->segment(3));
$this->db->join('users wc','w.author = wc.user_id');
$data = $this->db->get();
return $data;
}
As you can see, the getComments function in my model was the key. It's the JOIN statement that handles what I was trying to accomplish. I know there are probably cleaner and more efficient ways to do this, by combining the two functions, but as a beginner I wanted to keep it easier to understand.
Hopefully this can help others.

Related

Is it possible to combine whereHas with 'or' queries?

I'm trying to implement a filter system where, among other attributes and relationships, items are categorized. However, the challenge appears when combining OR queries with other filters using the regular and clause. The result grabs rows which I do not want and adds the or when the condition for that fails, thus polluting the final results with unwanted data.
<?php
class ProductSearch {
public $builder;
private $smartBuild; // this is the property I'm using to disable the alternation when other search parameters are present to avoid polluting their result
function __construct( Builder $builder) {
$this->builder = $builder;
}
public function applyFilterToQuery(array $filters) {
$pollutants = ['subcategory', 'subcategory2', 'category'];
$this->smartBuild = empty(array_diff( array_keys($filters), $pollutants)); // [ui=>9, mm=>4], [mm]
foreach ($filters as $filterName => $value) {
// dd($filters, $filterName );
if (method_exists($this, $filterName) && !empty($value) )
$this->$filterName( $value);
}
return $this;
}
public function location( $value) {
$this->builder = $this->builder
->whereHas('store2', function($store) use ($value) {
$store->where('state', $value);
});
}
public function subcategory( $value) {
$name = Subcategories::where('id', $value)->pluck('name');
$this->builder = $this->builder->where('subcat_id', $value);
if ($name->isNotEmpty() && $this->smartBuild) {
$names = preg_split('/\W\s+/', $name[0]);
if (!$names) $names = $name;
foreach ($names as $value)
$this->builder = $this->builder->orWhere('name', 'like', "%$value%");
}
}
}
You may observe from the above that making a request for categories searches products matching the category name. But on attempting to combine that alternate match with legitimate AND queries (in location for instance, the result tends to include matching locations OR matching names.
The desired result is ((matching name OR matching category) AND matching location). Is this possible?
I had similar situation like this few days ago about User and Posts.
Needed a list of posts which user has commented or participated in and which user owns.
So I did following on User model
//Get user created post or if user has participated in the post
$queryString->where(function ($query) use ($user_id) {
return $query->whereHas('participants', function ($q) use ($user_id) {
$q->where('user_id', $user_id);
})->orWhere('id', $user_id);
});
Hope this helps.

JOIN works in SQL not in Drupal

I'm trying to make a module for Drupal 7.x. At a certain point I want to use a sql query (JOIN). When I try the query in MYSQL it works. But when I want to try it in Drupal, the array is empty.
So I guess there is a difference between the sql query and the drupal query (mayby the implemantion is different).
SQL Query
SELECT * FROM friends
INNER JOIN users
ON friends.uid=users.uid
Drupal implementation
function project_myfriends(){
// Use database API to retrieve tasks
$query = db_select('friends', 'f');
$query->join('users', 'u', 'f.uid = u.uid'); // JOIN
$query->fields('u', array('name'))
->execute();
return $query;
}
/**
* Implements hook_block_view().
*/
function project_block_view($delta = ''){
switch ($delta) {
case 'project':
$block['subject'] = t('My Friends');
// Use our custom function to retrieve data
$result = project_myfriends();
$items = array();
var_dump($result);
foreach($result as $friend){
$items[] = array(
'data' => $friend->name,
);
}
// No tasks
if (empty($items)) {
$block['content'] = t('No friends.');
}
else {
// Pass data trough theme function
$block['content'] = theme('item_list', array(
'items' => $items));
}
}
return $block;
}
Thx in advance
You forgot to fetch your result query:
$result = project_myfriends()->execute()->fetchAll();
var_dump($result);

Laravel 4 MySQL query to array?

I'm using Laravel 4 and I need to take entries from my database, put them into an array and use them in a foreach loop in my view.
I'm not getting any errors but I'm also not getting anything from the database.
I'm trying to edit this page of a Laravel bundle to get products from the database, rather than statically.
This is my query from my Model
return $products = \DB::select('select * from products', array('sku', 'name'));
Controller...
public function getIndex()
{
// Get the products.
//
$products = Products::all();
// Show the page.
//
return View::make('shpcart::home')->with('products', $products);
}
This is my view
<pre>
<?php
print_r($products);
?>
</pre>
This is the result
Array
(
)
This works to insert into the database:
DB::insert('insert into products (sku, name) values (?, ?)', array('WS004', 'Test'));
This...
$products = DB::table('products')->get();
foreach ($products as $product)
{
echo $product->sku;
}
returns the error
Invalid argument supplied for foreach()
You can see it here...
http://wilsonswan.co.uk/collection
Thanks in advance.
You should not return $products as such.
You should perhaps do something like:
public function index()
{
$products = Products::where('sku', '=', 'name')->get();
return View::make('view', compact('products'));
}
try this:
public function getIndex() {
$db = DB::table('products as p')
->where('p.sku', '=', 'WS004');
$products = $db->get();
return View::make('shpcart::home')
->with('products', $products);
}

In yii how to json_encoded multiple records

i am creating project in yii+extjs. I am having poll table with pollid and pollQuestion. Option table is having pollid and options. Now during publishing question i am retrieving question from poll table and options of that question from option table. and sending this data in json_encoded format. i had desgined function as-
public function actionCreate()
{
$model=new poll();
$model->pollId=4;
$record1=poll::model()->findByPk($model->pollId);
//$data = $record1->getAttributes();
$data= $record1->getAttributes(array('pollId','pollQuestion'));
foreach ($record1->polloptions as $option)
{
$data = array_merge($data, $option->with('pollId')- >getAttributes());
}
//echo $data;
echo CJSON::encode($data);
}
Option table is having multiple options for same question. But by above method it is displaying only last option inserted in option table instead of displaying all options of same question. So how to display all options of same question.Please help me....
May be you could try:
public function actionCreate()
{
$model=new poll();
$model->pollId=4;
$record1=poll::model()->findByPk($model->pollId);
//$data = $record1->getAttributes();
$data= $record1->getAttributes(array('pollId','pollQuestion'));
foreach ($record1->polloptions as $option)
{
$optionArray = $option->getAttributes()
//if the 2 arrays havn't the same indexes
//this way u keep the key indexes
$data = $data + $optionArray;
//if the 2 arrays could have the same indexes
$data = array_push($data, $optionArray);
}
//echo $data;
echo CJSON::encode($data);
}

Output query to csv, codeigniter

I currently have a report that give me the users ID number and their email address, But I would like to make this in a CSV file instead of tables and rows like I currently have.
Here is my controller
function View_Email_E()
{
$data = array();
if($query = $this->report_model->View_Email_English())
{
$data['records'] = $query;
}
$data['main_content'] = 'view_all_email_english';
$this->load->view('includes/template', $data);
}
Here is my model
function View_Email_English()
{
$query = $this->db->where(array('Dial_Up' => '0', 'Language' => 'English', 'Membership_Status' => 'Active'));
$query = $this->db->like('Email', '#');
$query = $this->db->get('Membership');
return $query->result();
}
For some reason my view is not being shown in code mode, but it is an auto generated table using these this snippet of code. Each row returns ID and Email from the database.
<?php if(isset($records)) : foreach($records as $row) : ?>
How can I make a CSV file with just ID and email fields?
Thanks
I think you can use the csv_from_result function in dbutil to do it. Try something like this:
$csvContent = $this->dbutil->csv_from_result($query);
if ( ! write_file('./path/to/file.csv', $csvContent)) {
echo 'Unable to write the file';
} else {
echo 'File written!';
}
http://codeigniter.com/user_guide/database/utilities.html#csv
Add
$this->db->select(array('ID','Email'));
To your View_Email_English function.