I am creating a web-service backend for a mobile app I am developing. (I am an experience Obj-C developer, not a web-designer!) Essentially I would like to use Codeigniter and Phil Sturgeon's RESTful API Server https://github.com/philsturgeon/codeigniter-restserver however, I'm having some trouble getting it all setup and working.
I have MySQL database that is setup with data in it. And I need some help writing a CodeIgniter PHP model and controller that returns JSON data of what is inside that database. All of the tutorials and forum post's i have found deal with hardcoded data in the controler, not a MySQL database. I would ideally like to have the URL formatted like this http://api.mysite.com/v1/search?id=1&name=foo&city=bar , I could potentially have 50+ parameters to pass in the url.
Using Phil's code, I have come up with this as my controller:
public function index_get()
{
if (!$this->get('id'))
{
$this->response(NULL, 400);
}
$data = $this->grid_m->get_id($this->get('id'));
if ($data)
{
$this->response($data, 200);
}
else
{
$this->response(NULL, 404);
}
}
That only gets me one search term: id?=# .. I need to know how to get multiple search terms
Here is my Codeigniter model:
<?php
class Grid_m extends CI_Model
{
function get_all()
{
$query = $this->db->get('grid');
if ($query->num_rows() > 0)
{
return $query->result();
}
return FALSE;;
}
This just returns EVERYTHING in my MySQL database regardless of what id or url term I pass it in the URL.
I'm a big noob when it comes to developing my own custom API so any suggestions on how to fix my controller and database model would be a huge help!
Thanks for the help!
-brian
This is old question but if somebody go here and still need help, try these code:
In your controller:
public function index_get()
{
$where = '';
if ($this->get('id')) // search by id when id passed by
{
$where .= 'id = '.$this->get('id');
}
if ($this->get('name')) // add search by name when name passed by
{
$where .= (empty($where)? '' : ' or ')."name like '%".$this->get('name')."%'";
}
if ($this->get('city')) // add search by city when city passed by
{
$where .= (empty($where)? '' : ' or ')."city like '%".$this->get('city')."%'";
}
// you can add as many as search terms
if ( ! empty($where))
{
$data = $this->grid_m->get_searched($where);
if ($data)
{
$this->response($data, 200);
}
else
{
$this->response(NULL, 404);
}
}
else
{
$this->response(NULL, 404);
}
}
In your model, create get_searched function:
class Grid_m extends CI_Model
{
function get_searched($where = NULL)
{
if ( ! is_null($where))
{
$this->db->where($where);
$query = $this->db->get('grid');
if ($query->num_rows() > 0)
{
return $query->result();
}
}
return FALSE;
}
}
User Codeigniter's Active record to build proper query, you can build any type of query using methods of active record, refer following example I have just added one condition in it you can add more conditions as per your need.
<?php
class Grid_m extends CI_Model
{
function get_all()
{
$this->db->select('col1, col2, col3')->where('id', 5);
$query = $this->db->get('grid');
if ($query->num_rows() > 0)
{
return $query->result();
}
return FALSE;;
}
}
Please check you query
$query = $this->db->get_where('grid', array('id' => $id));
Related
I'm trying to cover all my bases in the event my MYSQL database returns any errors (no rows, no connection, no table, etc...) when I'm making a query using CodeIgniter 3.
I have a helper function that returns the latitude and longitude based on a zip code provided. It will always only return a single row (granted the record exits). Here's my helper function as of now:
if (!function_exists('get_coordinates_from_zipcode')) {
//gets latitude and longitude coordinates from supplied zipcode. Returns array
function get_coordinates_from_zipcode($zipcode) {
$ci =& get_instance();
$ci->load->database();
$query = $ci->db->get_where('Geo', array('zip =' => $zipcode))->row_array();
if (!$query) {
return FALSE;
} else {
return $query;
}
}
//* Fields returned from geolocation database *//
/* -zip
-lat
-lng
// Returns false on error or no records
*/
}
And here is my View I'm using (passing $data['array'] array to it from my Controller):
<?php if ($array == FALSE || !$array) : ?>
<?php echo "No data returned"; ?>
<?php else : ?>
<?php echo $array['zip'] . ' is located at ' . $array['lat'] . ' and ' . $array['lng']; ?>
<?php endif; ?>
This works well if there are no rows, but I want to handle any other issues, such as more than one row (highly unlikely to happen), or if there's a problem connecting to the database or table.
I've tried this in my Helper
if ($ci->db->error()) {
return $ci->db->error(); //
} else {
return $query;
}
When I do this, and purposely use an invalid zip code to pass the error to the view, $ci->db->error() always returns array(2) { ["code"]=> int(0) ["message"]=> string(0) "" } and is empty. And of course I get errors that Undefined index: lat and Undefined index: lng
Should I be passing the $ci-db->error() array to the view and acting on it there?
I just want to make sure all my bases are covered. In my mind I should be handling errors in the Helper function but the error() always seems to be empty even when there's an error (such as no rows, or no db connectivity, or no table by that name.
I feel like
if (!$query) {
return FALSE;
} else {
return $query;
}
inside my helper function won't cover all problems I could potentially have connecting to the database.
Why don't you just do the following:
if (!function_exists('get_coordinates_from_zipcode')) {
//gets latitude and longitude coordinates from supplied zipcode. Returns array
function get_coordinates_from_zipcode($zipcode) {
$ci =& get_instance();
$ci->load->database();
if ($ci->db->conn_id === false) {
return false; // connection couldn't be established
}
$query = $ci->db->get_where('Geo', array('zip =' => $zipcode));
if ($query && $query->num_rows() == 1) {
return $query->row_array();
}
return false;
}
//* Fields returned from geolocation database *//
/* -zip
-lat
-lng
// Returns false on error or no records
*/
}
This way:
You test that query didn't return a FALSE result
You test that you are only getting 1 row
You make sure you have established a connection to the db (seems a bit overkill)
Please note: you should always check the value of num_rows() before attempting to access the result array/object. If there are no rows, then you will get undefined indexes when attempting to access the array.
i don't understand the purpose of your helper here - If you dont use a model and if you bypass the controller here why do you even use Codeigniter at first ?
Now your question
if its possible i would create a model where you handle all the errors and try to throw them via Exceptions
a possible approach
Model
class Geo_model extends CI_Model
{
public function __construct()
{
$this->load->database();
}
public function get_coordinates_from_zipcode($zipcode = false)
{
if (!$zipcode) throw new InvalidArgumentException('Zipcode should be set');
$query = $this->db
->select('*')
->from('Geo')
->where('zip', $zipcode)
->get();
$arrError = $this->db->error();
if (isset($arrError['message']) && !empty($arrError['message'])) throw new RuntimeException($arrError['message']);
if ($query->num_rows() != 1) throw new RuntimeException('Query - Number of rows should be 1');
return $query->row_array();
}
}
controller
class Geo extends CI_Controller
{
public function coordinatesfromzipcode($zipcode)
{
$this->load->model('Geo_model');
try
{
$row = $this->Geo_model->get_coordinates_from_zipcode($zipcode);
//load your coordinates view
}
catch (Excepetion $e)
{
//load an error view or something like that...
echo $e->getMessage();
}
}
}
I am new to Codeigniter and I am trying to figure out a way to use pagination and also filter some data. I have pagination setup to show all records in a table. I want to be able to filter those records using a specific column in the table. The column is an int. My controller is clients and the method is index so going to http://localhost/clients will produce a list of clients in a table. When I go to another page to display more results the URL changes to something like http://localhost/clients/50 depending on what page I am on. Now, I have one argument for my controller method which is $client_status, which again is an int. Since CI is using the second segment of the URL for pagination, how to I pass the argument for filtering by client status? Here is what the code looks like:
public function index($client_status = false) {
if(!$client_status) {
$data['clients'] = $this->clients_model->list_clients($config["per_page"], $page);
} else {
$data['clients'] = $this->clients_model->list_clients($config["per_page"], $page, $client_status);
}
And my model:
public function list_clients($limit, $start, $client_status = false) {
if(!$client_status) {
$this->db->limit($limit, $start);
$this->db->select('*');
$this->db->from('clients');
$this->db->join('client_status', 'clients.client_status_id = client_status.client_status_id');
$query = $this->db->get();
if($query->num_rows() > 0) {
return $query->result();
} else {
return false;
}
} else {
$this->db->limit($limit, $start);
$this->db->select('*');
$this->db->from('clients');
$this->db->join('client_status', 'clients.client_status_id = client_status.client_status_id');
$this->db->where(array('clients.client_status_id' => $client_status));
$query = $this->db->get();
if($query->num_rows() > 0) {
return $query->result();
} else {
return false;
}
}
}
To do this you will have to pass your parameters into the query string. In your config for the pagination class make sure to set these following parameters
$config = array(
'page_query_string' => TRUE,
'query_string_segment' => 'page', // the query string param for the page numbers
'reuse_query_string' => TRUE,
)
With the config your URL's would be similar to
http://example.com/clients?param=value&page=2
I need to call a function from view to echo a value. I use following code,
Controller (test_controller)
public function displayCategory()
{
$this->load->model('Model_test');
$data['categories'] = $this->Model_test->getCategories();
$this->load->view('test_view', $data);
}
public function display($id)
{
$this->load->model('Model_test');
$name= $this->Model_test->getName($id);
return $name;
}
Model (Model_test)
function getCategories() {
$query = $this->db->query("SELECT * FROM category");
if ($query->num_rows() > 0) {
return $query->result();
} else {
return NULL;
}
}
function getName($userId) {
$query = $this->db->query("SELECT name FROM user where id = '$userId' ");
if ($query->num_rows() > 0) {
return $query->row()->name;
} else {
return NULL;
}
}
View
<div id="body">
<?php
foreach ($categories as $object) {
$temp = $this->test_controller->display($object->id);
echo $object->title . " ". $object->no . $temp . '<br/>';
}
?>
</div>
but some error when running the code.
error Message: Undefined property: CI_Loader::$test_controller in view
I am not sure if you use CodeIgniter 2 or 3.
Anyway, basically you don't want to use anything inside View files except perhaps helper function(s) or some kind of "presenter" layer (that should be called inside controller I guess).
Solution using Join
Go and read this manual page and search for join. There you can learn about implementation of SQL join directive.
You want to modify this (getCategories()) function so it returns data that you require
function getCategories() {
$this->db->select('category.title, category.no, user.name as username')
->from('category')
->join('user', 'user.id = category.id');
$query = $this->db->get();
if ($query->num_rows() > 0) {
return $query->result();
} else {
return NULL;
}
}
and in view you can get your username like this
foreach ($categories as $object) {
echo $object->title . " ". $object->no . $object->username . '<br/>';
}
I am not 100% sure so please post comments I will edit this answer later.
Solution "breaking rules"
https://stackoverflow.com/a/24320884/1564365
general notes
Also consider naming your tables using plural so categories, users...
Also it is a bad practise to use "category.id as user.id" (storing user id inside category table in "id" field) instead you shold use either a pivot table or in case of 1:1 relation field "user_id".
i'm in mid of creating my own cms . And now i want to show which one of the category has parent but i don't know how, so please help me.
my category table
idkategori | namakategori | parentid
1 Programming 0
2 PHP 1
Or i need relationship table for my categories?
My Controller so far.
function tampilmenu()
{
$sql = "select * from fc_kategori";
$data['kategori'] = $this->bymodel->tampildata($sql);
$sql1 = "select parentid from fc_kategori";
$data['parent'] = $this->bymodel->tampildata($sql1);
$id=array();
foreach ($data['parent'] as $paren)
{
$id[]=$paren->parentid;
}
foreach ($data['kategori'] as $cat)
if(in_array($cat->parentid,$id))
{
$have ='Yes';
}
else
{
$have ='No';
}
echo $cat->idkategori.$have;
}
}
my model
function tampildata ($sql)
{
$query = $this->db->query($sql);
return $query->result();
}
Please don't laugh on me.
Kindly follow:
1) Since you are using a MVC framework, never write queries inside the controller (queries should always be written in models).
2) Never use raw queries, since CI provides you what is called as Active Record.
3) Also never pass direct queries anywhere you'll possibly code in whichever language. Always pass data and make do that function to compute and query process.
4) Remember, in CI Models are only used for database functionalities, Views are only used for your HTML markups and Controllers acts as the mediator between models and views.
Your code:
Controller -
public function tampilmenu()
{
$categories = $this->bymodel->get_category_having_parent();
echo "<pre>"; print_r($categories);
// this will return object having all categories that are parents
}
Model -
public function get_category_having_parent()
{
$parent_ids = array();
$ps = $this->get("parentid");
foreach($ps as $p)
{
$parent_ids[] = $p->parentid;
}
$this->db->where_in("id", $parent_ids);
$query = $this->db->get("fc_kategori");
return $query->result();
}
public function get($column="*")
{
$this->db->select($column);
$query = $this->db->get("fc_kategori");
return $query->result();
}
I am trying to display jobs won by a certain provider. What I did was to create function get_approved_job_proposals in my model. Then, I created function manage_job_contracts in my controller, but I never got to successfully run it.
Here's my code in model:
public function get_approved_job_proposals($status)
{
$this->db->select('*')->from('job_proposal')->where('status', $status);
$this->db->where("status" == "Awarded");
$query = $this->db->get();
return $query->result_array();
}
and this is what I have in my controller:
public function manage_job_contracts()
{
$this->validateRole('client');
$this->load->model('job_model');
$data['my_preference'] = $this->job_model->get_approved_job_proposals($status);
$data['job'] = $this->job_model->get_job($id);
$this->load->view('client/manage_job_contracts', $data);
}
Kindly help me fix this issue.
This is wrong:
$this->db->where("status" == "Awarded");
Correct:
$this->db->where("status", "Awarded");
Check documentation: http://ellislab.com/codeigniter/user-guide/database/active_record.html