The question might sound a little bit confusing but I don't know how to explain it better in one sentence.
This describes basically what the problem is:
I have a Users table which can contain 2 types of users. I know how I can separate by role. But here's the thing, users with role 1(editor_in_chief) have different attributes than users with role 2(reviewer).
My idea was to create a table named 'reviewer_attributes' and 'editor_in_chief_attributes' and create a one-to-one relation with this table to hold the attributes for the users table.
Maybe you have a better idea, that would be great as well. But for this scenario, I would like to know if it is possible to make a call to the database and to get these users' properties from the other table as properties of the User object.
When using a DB call using relations laravel will give me something like this:
user {
id: 1,
name: "Name",
reviewer_attributes: {
attribute_1: 'attribute_1',
attribute_2: 'attribute_2',
attribute_3: 'attribute_3',
}
}
But this is what I want to object to obtain look like:
user {
id: 1,
name: "Name",
attribute_1: 'attribute_1',
attribute_2: 'attribute_2',
attribute_3: 'attribute_3',
}
I want to achieve this by a single database call instead of setting the properties after the call.
I find this a very interesting topic, I hope you could help!
If I got your problem right, you may call somthing like this:
DB::table('users')
->join('reviewer_attributes', 'users.id', '=', 'reviewer_attributes.user_id')
->find($id);
you may add select to get specific attributes of each table:
DB::table('users')
->join('reviewer_attributes', 'users.id', '=', 'reviewer_attributes.user_id')
->select('users.id', 'users.name', 'reviewer_attributes.*')
->find($id);
Update: You can also use collections to restructure your results returned by Eloquent:
$result = User::with('reviewerAttributes')->find($id);
$result = $result->get('reviewer_attributes')
->merge($result->forget('reviewer_attributes')->all())
->all();
You need export model to Json?
If so, override toArray method
public function toArray()
{
$arr = parent::toArray();
$reviewer_attributes = $this->getReviewerAttributesSomeHow();
return array_merge($arr, $reviewer_attributes);
}
I am new to code igniter data mapper. I have a table called user, and I am trying to retrieve data from the database table and show them to the user.
Here is what I have in the model:
$u=new User();
$results=$u->get_by_user_id($id);
//$results here will be set to huge bunch of none sense data( which also includes the row that I am looking for as well)
if ($u->exists())
{
foreach ($results->all as $row){
$data['user']['first_name']=($row->user_first); //this where I am stuck ..
$data['user']['last_name']=($row->user_last);//this is also where I am stuck..
}
I don't know how to treat results to get a required fields I am looking for and store them in the $data I am passing to the user to view.
Thanks!
When you call get_by_x() on the model, the fields will be populated with data and you can access them like this:
$u = new User();
$u->get_by_user_id($id);
if($u->exists())
{
// you can access the table columns as object fields
$data['user']['first'] = $u->first;
$data['user']['last'] = $u->last;
}
else
{
$data['error'] = 'No such user!';
}
Have a look at the documentation which is really helpful: see Get and Get By.
Also, DataMapper expects all tables to have an id column: see Table Naming Rules. If your column is named id you should then call $u->get_by_id($id) instead of $u->get_by_user_id($id).
In my CakePHP application, I have a model like this:
class Duck extends AppModel {
var $name = 'Duck';
function get_table_name() {
$tbl_name = //compute default table name for this model
}
}
I would like to write the function get_table_name() that outputs the default table name for the model. For the example above, it should output ducks.
EDIT:
Several people have pointed out the use of $this->table.
I did small testing and found out the following:
In the question as I have put above, $this->table indeed contains the table name.
However, actually, my code looked more like this:
class Duck extends Bird {
var $name = 'Duck';
function get_table_name(){
$tbl_name = //comput default table name for this model
}
}
class Bird extends AppModel {
}
In this case $this->table is empty string.
I went with this approach because I wanted to share some code between two of my models. Looks like this is not a good way to share code between models which need some common functionality.
You're looking for the Inflector class.
Inflector::tableize($this->name)
(tableize calls two Inflector methods to generate the table name: underscore() and pluralize())
Edit:
According to the source code, $this->table should contain the name of the table that CakePHP will use for the model, but in my experience this isn't always set. I'm not sure why.
To get the name of the table that the model is currently using, you can use: $this->table. If you don't manually change the model's table conventions, this may be the most useful in the case of CakePHP ever changing its conventions to use table names using something other than Inflector.
CakePHP's Inflector
function get_table_name() {
$tbl_name = Inflector::pluralize($this->name);
}
OR the tableize method
function get_table_name() {
$tbl_name = Inflector::tableize($this->name);
}
Edit
This also addresses the apparent "ghost" issue with $this->table in the Model.
Digging around in the __construct for Model I discovered two things:
Cake uses Inflector::tableize() to get the table name. This alone is enough to warrant using tableize over pluralize. You'll get consistent results.
$this->table is not set by the Model::__construct() unless $this->useTable === false AND $this->table === false.
It appears that if you know you haven't set $this->useTable to false you should be able to use this over $this->table. Admittedly though I only briefly scanned the source and I haven't really dug deep enough to say why $this->table isn't working sometimes.
To get the full table name for a model you have to take the table prefix into account.
$table = empty($this->table) ? Inflector::tableize($this->name) : $this->table;
$fullTableName = $this->tablePrefix . $table;
I used to use inflector to get the table name from model's name
$tableName = Inflector::pluralize(Inflector::underscore($model));
but this is not really universal, using useTable looks better, by default it will contain table's name by convention, and if you have a table that does not match the conventions, then you should manually specify it by useTable. So, in both cases the result will be correct
$this->User->useTable
I'm building a site with CodeIgniter, and my I have a model called Blog_model.
Within Blog_model, there are methods to pull a list of posts for a specific topic, for example, getPopularPosts().
getPopularPosts() queries the posts table for a list of posts with a topic_id matching the one specified and sorts them by popularity. So, that's one query against the entire table of posts (let's assume this will be very large eventually) to find all posts with topic_id x.
Then, foreach result as an individual post id, it creates a new Post object. The Post class constructs a post by setting the field id.
To return the contents of a Post, I assign $post->getPost();, which queries the posts table again to return the entire row for the given id.
This organization (AFAIK) follows a nice object oriented principle. But now, for every posts (again, let's assume thousands, millions, whatever...), I have to first query for a list of ids and then again to get each post's content. If I'm returning 30 posts, that means 31 separate queries.
Alternatively, I could break the object oriented pattern and pull * for each post in posts where topic_id = x. Then, I have one query that returns all 30 posts, but now I don't feel so object oriented.
What to do?
There is no reason to have that many queries. You're basically just looking for X number of posts that are from a particular topic ID... you should return this as one object and then iterate through the result in PHP because it is significantly faster to do it that way once you get to the point of having millions of rows
You should go about it more like this:
class blog_model extends CI_Model {
function __construct(){
parent::__construct();
}
function getPopularPosts($cat_id){
/* Using method chaining here since you sound like you
really want to utilize everything OO CI has to offer */
$posts = $this->db->select('id, title, post_info')
->where('topic_id', $topic_id)
->get('posts');
if($posts->num_rows() > 0){
return $posts;
}else{
return FALSE;
}
}
}
Then your controller would look like this:
class blog extends CI_Controller {
function __construct() {
parent::__construct();
}
function blog_posts($popular_post_id) {
$this->load->model('blog_model');
$posts = $this->blog_model->getPopularPosts($popular_post_id);
if(!empty($posts){
foreach($posts as $post){
echo $post->id;
echo $post->title;
echo $post->post_info;
}
}else{
echo 'There are no posts';
}
}
}
There is no benefit (and actually a big problem) with generating a ton of queries in the fashion that you currently have it set up, vs generating one object from the query and iterating through each of the rows in the controller and doing whatever you need with the data.
If I do getLastInsertId() immediately after a save(), it works, but otherwise it does not. This is demonstrated in my controller:
function designpage() {
//to create a form Untitled
$this->Form->saveField('name','Untitled Form');
echo $this->Form->getLastInsertId(); //here it works
}
function insertformname() {
echo $this->Form->getLastInsertId(); //this doesnt echo at all
}
Please suggest a way to get the functionality I want.
CakePHP has two methods for getting the last inserted id: Model::getLastInsertID() and Model::getInsertID().
Actually these methods are identical so it really doesn't matter which method you use.
echo $this->ModelName->getInsertID();
echo $this->ModelName->getLastInsertID();
This methods can be found in cake/libs/model/model.php on line 2768
Just use:
$this->Model->id;
In Cake, the last insert id is automatically saved in the id property of the model. So if you just inserted a user via the User model, the last insert id could be accessed via $User->id
id - Value of the primary key ID of
the record that this model is
currently pointing to. Automatically
set after database insertions.
Read more about model properties in the CakePHP API Docs: http://api.cakephp.org/2.5/class-AppModel.html
Edit: I just realized that Model::getLastInsertID() is essentially the same thing as Model->id
After looking at your code more closely, it's hard to tell exactly what you're doing with the different functions and where they exist in the grand scheme of things. This may actually be more of a scope issue. Are you trying to access the last insert id in two different requests?
Can you explain the flow of your application and how it relates to your problem?
You'll need to do an insert (or update, I believe) in order for getLastInsertId() to return a value. Could you paste more code?
If you're calling that function from another controller function, you might also be able to use $this->Form->id to get the value that you want.
Try using this code in your model class (perhaps in AppModel):
function get_sql_insert_id() {
$db =& ConnectionManager::getDataSource($this->useDbConfig);
return $db->lastInsertId();
}
Caveat emptor: MySql's LAST_INSERT_ID() function only works on tables with an AUTO_INCREMENT field (otherwise it only returns 0). If your primary key does not have the AUTO_INCREMENT attribute, that might be the cause of your problems.
this is best way to find out last inserted id.
$this->ModelName->getInsertID();
other way is using
$this->ModelName->find('first',array('order'=>'id DESC'))
There are several methods to get last inserted primary key id while using save method
$this->loadModel('Model');
$this->Model->save($this->data);
This will return last inserted id of the model current model
$this->Model->getLastInsertId();
$this->Model-> getInsertID();
This will return last inserted id of model with given model name
$this->Model->id;
This will return last inserted id of last loaded model
$this->id;
Try to use this code. try to set it to a variable so you can use it in other functions. :)
$variable = $this->ModelName->getLastInsertId();
in PHP native, try this.
$variable = mysqli_insert_id();
This will return last inserted id of last loaded model
$this->id;
This will return last inserted id of model with given model name
$this->Model->id;
This will return last inserted id of the model current model
CakePHP has two methods for getting the last inserted id:
Model::getLastInsertID() and Model::getInsertID().
echo $this->ModelName->getInsertID();
echo $this->ModelName->getLastInsertID();
Below are the options:
echo $this->Registration->id;
echo $this->Registration->getInsertID();
echo $this->Registration->getLastInsertId();
Here, you can replace Registration with your model name.
Thanks
Use this one
function designpage() {
//to create a form Untitled
$this->Form->saveField('name','Untitled Form');
echo $this->Form->id; //here it works
}
You can get last inseted id with many ways.Like Model name is User so best way to fetch the last inserted id is
$this->User->id; // For User Model
You can also use Model function but below code will return last inserted id of model with given model name for this example it will return User model data
$this->User->getLastInsertId();
$this->User->getInsertID();
When you use save(), the last insert ID is set to the model’s $id property. So:
if ($this->Model->save()) {
printf('Last insert ID was %s', $this->Model->id);
}
Each time a save method is called on a model, cake internally calls Model::getLastInsertId() and stores the result into model class attribute id, so after calling save() it is not necessary to call Model::getLastInsertId() or inserId(), as tha value can be directly accessed like this
$id = $this->id;// within a model
$id = $this->{$this->modelName}->id;// in a controller
After insertion of data, we can use following code to get recently added record's id:
$last_insert_id=$this->Model->id;
each time you perform an insert operation on any model, cake internally fetchesthe last insert Id and Sets to Model->id attribute.
so one can access it directly by $Model->id;,
no need to query again for lastInsertId.
I think it works with getLastInsertId() if you use InnoDB Tables in your MySQL Database. You also can use $this->Model->id
$Machinedispatch =
$this->Machinedispatch->find('first',array('order'=>array('Machinedispatch.id DESC')));
Simplest way of finding last inserted row. For me getLastInsertId() this not works.
Actually you are using the getLastInsertId or getInsertId in a wrong manner.
getLastInsertId() is meant to work only after save() method.
It will even not work after a manual insert, as cake engine is storing the mysql_insert_id under $this->_insertID inside the save method which can be retrieved via the getLastInsertId or getInsertId.
Now in your case
$this->Model->id
OR
$this->Model->find('first',array('order'=>'id DESC'))
Will do.
This is interesting, I also stumbled upon this issue. What you asked perhaps how to get the last ID of a certain model regardless of it's state, whether it's just been inserted or not. To further understand what getInsertID does, we need to take a look at the source:
Link 1: http://api20.cakephp.org/view_source/model#line-3375
public function getInsertID() {
return $this->_insertID
}
Yup, that's the only piece of code inside that function. It means that cakephp caches any last inserted ID, instead of retrieve it from the database. That's why you get nothing if you use that function when you haven't done any record creation on the model.
I made a small function to get the last ID of a certain table, but please note that this should not be used as a replacement of getLastID() or getLastInsertID(), since it has an entirely different purpose.
Add the function lastID() to the AppModel as shown below so that it can be used system wide. It has it's limit, which can't be used on model with composite primary key.
class AppModel extends Model {
public function lastID() {
$data = $this->find('first',
array(
'order' => array($this->primaryKey . ' DESC'),
'fields' => array($this->primaryKey)
)
);
return $data[$this->name][$this->primaryKey];
}
}
Original Source : Class Model
In CakePHP you can get it by:
Model::getInsertID() //Returns the ID of the last record this model inserted.
Model::getLastInsertID() //Alias to getInsertID().
$this->Model->field('id', null, 'id DESC')