<?php
// Model
class ProfileDelivery extends \Eloquent {
protected $table = 'profile_delivery';
protected $guarded = array();
public $timestamps = FALSE;
}
// Somewhere
$deliveryGuy->id = 1;
print $deliveryGuy->id; // Prints 1
if (!$deliveryGuy->save()) {
throw new \Exception('Cant save .');
}
print $deliveryGuy->id; // Prints 0
Can anyone explain me why the ID value is lost?
Not sure if you solved this for your situation but in Laravel 5.1 this just happened to me - the primary key of one table is the same as the primary key to another table because there is a 0 or 1 - to - 1 relationship between them.
What is happening is that Eloquent is assigning the primary key to the last insert id of the insert, but because the primary key is not an auto increment value, it is assigning it to zero. It is stored in the database correctly, but the model after the save is not useful if you need to use that key. The solution is to override the insertAndSetId function for the model that has the foreign primary key to prevent its setting of the primary key attribute. Of course, you don't want to do this for any models that do have an auto-incrementing key, just models that you are assigning the primary key manually. It's also not necessary if you don't need to use the model immediately after creating it because as I said above the database has the correct info in it.
protected function insertAndSetId(Builder $query, $attributes)
{
$id = $query->insertGetId($attributes, $keyName = $this->getKeyName());
// $this->setAttribute($keyName, $id);
}
This is because your id column in the database probably does not have autoincrement set.
I tried this with a test model without autoincrement and it returns 0, but when I changed the id column to autoincrement it returned the id correctly.
Check this function in laravel/Framework/Src/Illuminate/Database/Eloquent/Model.php
It says it will insert and set id if it has autoincrement.
protected function performInsert($query)
{
if ($this->fireModelEvent('creating') === false) return false;
// First we'll need to create a fresh query instance and touch the creation and
// update timestamps on this model, which are maintained by us for developer
// convenience. After, we will just continue saving these model instances.
if ($this->timestamps)
{
$this->updateTimestamps();
}
// If the model has an incrementing key, we can use the "insertGetId" method on
// the query builder, which will give us back the final inserted ID for this
// table from the database. Not all tables have to be incrementing though.
$attributes = $this->attributes;
if ($this->incrementing)
{
$this->insertAndSetId($query, $attributes);
}
// If the table is not incrementing we'll simply insert this attributes as they
// are, as this attributes arrays must contain an "id" column already placed
// there by the developer as the manually determined key for these models.
else
{
$query->insert($attributes);
}
// We will go ahead and set the exists property to true, so that it is set when
// the created event is fired, just in case the developer tries to update it
// during the event. This will allow them to do so and run an update here.
$this->exists = true;
$this->fireModelEvent('created', false);
return true;
}
For me, I had to set protect $primaryKey to the column name of the primary key in the model to solve the issue. (skill_id was the column name so in the Skill model I set protected $primaryKey = 'skill_id', default is 'id'.)
Related
I have added a custom primary key within the table and now the Laravel is not even finding the result at all. giving error that the page could not be found.
NotFoundHttpException
No query results for model [App\usersinformation].
Controller --------------------
public function show(usersinformation $usersinformation)
{
//
// $users = $user = usersinformation::where('user-id','=',$usersinformation) -> first();
return view('usersinformation.show');
}
Model -------------------
class usersinformation extends Model
{
//
public $table = "usersinformation";
public $incrementing = false;
protected $fillable = [
'fname','lname', 'user-picture', 'phone-number', 'user-id', 'place-id'
];
protected $primaryKey = 'user-info-id';
public function users(){
$this -> belongsTo('App\users');
}
route ---- web.php
Route::post('/show','App\Http\Controllers\usersinformationController#show');
Still facing the same issue, if I comment the primary key, it will give error that the id field is not found within the table when I add the custom primary key in the model, it will give error page not found.
You're typehinting usersinformation $usersinformation, so it's trying to find the record for the ID you're passing in. In the next line, you're trying to pass the id into the user-id, so I'm guessing you're actually passing in the user-id to the route, and not the id of the user information row. If that is the case, then you need to change the typehinting so it won't try to find the record before it enters the function.
public function show($user_id)
{
$user_information = usersinformation::where('user-id','=',$user_id) -> first();
return view('usersinformation.show', ['userinformation' => $user_information]);
}
Your primaryKey line is fine and should work, but know that dashes in table and column names are strongly discouraged because it leads to all sorts of confusion. Underscores are much better. See this link for more information.
I am on a project where I am using custom PKs and FKs, and I'm trying to set up a one to one relationship.
For example, in Employee.php:
public function title()
{
return $this->hasOne('App\Title', 'TitleID');
}
On Tinker, I can retrieve an employee TitleID like so:
$employee = Employee::first();
$employee->TitleID;
Which returns:
"6"
I have now made a model: Title.php:
class Title extends Model
{
protected $table = "dbo.title";
protected $primaryKey = 'TitleID';
}
I can retrieve the contents of this model correctly when running $title = Title::all(); in Tinker.
I have set up a new relationship in Employee.php:
public function title()
{
return $this->hasOne('App\Title', 'TitleID');
}
However, in Tinker (which I have restarted) when I run:
$employee = Employee::first();
$employee->title()->get();
It returns:
Illuminate\Database\Eloquent\Collection {#3027
all: [],
}
What have I done to set up this relationship incorrectly?
The issue was that because the primary key of the other table isn't id, it wasn't able to find the collection.
However, according to the documentation, it reads:
Additionally, Eloquent assumes that the foreign key should have a value matching the id (or the custom $primaryKey) column of the parent.
So I assumed that because I set a custom $primaryKey value, it would intuitively be able to find it - however it seems the issue was to do with the local key's name breaking Eloquent's convention.
I solved the issue by declaring both the foreign and local key respectively:
public function title()
{
return $this->hasOne('App\Title', 'TitleID', 'TitleID');
}
You just need to access the property title instead of calling title():
$employee = Employee::first();
$employee->title;
My Document model has a custom primary key name, so I typed:
class Document extends Model {
protected $primaryKey = 'fluxo_mensagem_id';
After this, I suppose Laravel to know my primary key name and then I wouldn't expected to have to type it manually every time I need to set its value. Something like:
$document = new Document;
$document->setPrimary($pivot->id);
Instead of:
$document = new Document;
$document->fluxo_mensagem_id = $pivot->id;
For more details, my partial ER diagram:
Question 1
Laravel provides some method to set primary key values dynamically after custom names defined on model class?
Question 2
On document table, the column fluxo_mensagem_id is a foreign key that references id fluxo_mensagem pivot (intermediate) table. There's some way to "associate" (as we can do with Belongs To relationships) Pivot object to a Document model?
For example:
$pivot = $mensagem->fluxos()->first()->pivot;
$document = new Document;
$document->fluxoMensagem()->associate($pivot);
This would fit the problem because his intention is to set the foreign key on the child model.
Regarding Question 1: You can set the primary key value as any other, but you need to set the $incrementing = false, otherwise it'll be saved as 0.
/**
* Indicates if the IDs are auto-incrementing.
*
* #var bool
*/
public $incrementing = false;
I have 2 models namely Role and User models. With the following code respectively on each models:
Role.php:
public function users(){
return $this->belongsToMany('\Models\User', 'rbac_user_roles','role_id','username');
}
..
User.php:
public function roles(){
return $this->belongsToMany('\Models\RBAC\Role', 'rbac_user_roles','username','role_id');
}
but when I try to dump the data like so:
$model = Role::find( 1);
$model2 = User::find( 'test_user');
var_dump( $model->users->toArray() );
var_dump( $model2->roles->toArray() );
The $model->users->toArray() finds actual data while $model2->roles->toArray() returns nothing. Which is odd because I am pretty sure that the code works correctly.
With this, I would like to ask, is there an effect if the primary key for the database is a string for eloquent? because I believe this is the culprit here. If so, what can i do to remedy the situation?
The situation needs/has the following conditions
-> Can't add a new column for index enabled auto-increment key for users table
-> All table and data is correctly setup, as the first var_dump() actually dumps the correct data.
Thanks,
Jan
EDIT:
I also tried the following in getting the User:
$model2 = User::where( 'username', 'test_user')->get()->first();
Note: The primary key for the table Users is a string
Apparently, Eloquent is quite strict with non-increment primary keys. You should set the attribute for increments to false in the Eloquent Model like:
public $incrementing = false;
I am creating a real estate website that has Listing ID's attached to each listing. I am running a script via shell in CakePHP that is parsing a csv file and should be updating any listing that already exists or inserting a new one if it does not.
The problem is that I keep getting a Duplicate entry '###' for key "PRIMARY' where ### is the Listing ID that is being provided by the CSV. This script is being run from the command line.
Here's a smaller version of what my table includes:
CREATE TABLE `listings` (
`ListingID` int(11) NOT NULL,
`AccessibilityYN` varchar(50) DEFAULT NULL COMMENT 'AccessibilityYN',
`BathsFull` int(6) DEFAULT NULL COMMENT 'BathsFull',
`BathsPartial` int(6) DEFAULT NULL COMMENT 'BathsPartial',
`BathsTotal` decimal(5,1) DEFAULT NULL COMMENT 'BathsTotal',
`Beds` int(11) DEFAULT NULL COMMENT 'Beds',
PRIMARY KEY (`ListingID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Here's my Listing Model (notice that I have public $primaryKey = 'ListingID';)
class Listing extends AppModel {
public $name = 'Listing';
public $primaryKey = 'ListingID';
public $belongsTo = array(
'Agent' => array(
'className' => 'Agent',
'foreignKey' => 'AgentID'
)
);
}
Here's the shell I'm running via command line:
class MyShell extends AppShell {
public $uses = array('Listing');
public function update_imported_listings() {
/***SOME CODE HERE TO GET THE $entry FROM THE CSV***/
$this->Listing->ListingID = $entry['ListingID'];
if(!$this->Listing->exists()){
$this->Listing->create();
}
if($this->Listing->save($entry)){
echo "Saved Listing";
} else {
echo "Listing Failed";
}
}
}
I understand that CakePHP usually likes id to be the field used in the database, however I have set $primaryKey = 'ListingID' in my model. I've tried setting ListingID to Auto Increment in the DB but that didn't work.
Anybody have any ideas? I'm fresh out.
Setting ListingID doesnt' do anything
This line is your problem:
$this->Listing->ListingID = $entry['ListingID'];.
Irrespective of what your actual primary key field is in database the primary key value is always specified using Model->id property. As such, change it to:
$this->Listing->id = $entry['ListingID'];
You don't need to call exists
There is not need to explicitly check if record with particular primary key values exists. Cake will automatically update and record instead of creating a new one if the data array passed to save() contains a valid primary key value which exists in db. Just ensure you call create() before saving if you are using save() in a loop.
Don't break CakePHP conventions, use 'id' field as primary key.
http://book.cakephp.org/view/24/Model-and-Database-Conventions
I was getting the same error running a cakePHP shell script, turns out the latest record's ID was at the maximum value allowed by the size of the column (whoever made the table used a medium int for the id column), so auto_increment wasn't working. Changed the column to allow for larger numbers to fix. Probably something obvious, but might help someone out there.