Laravel's 5.2.33 Analogue (Data Mapper) orm Query Exception - php

I'm getting
Undefined column: 7 ERROR: no existe la columna «users_id_seq»
LINE 1: ...ated_at", "updated_at") values ($1, $2) returning "users_id_...
^ (SQL: insert into "users" ("created_at", "updated_at") values (2016-05-26 15:19:02, 2016-05-26 15:19:02) returning "users_id_seq")
When running an insert from a controller
this is my entity class
namespace App\Entities\Users;
use Analogue\ORM\Entity;
class BaseEntity extends Entity
{
private $remember_token;
private $created_at;
private $updated_at;
private $deleted_at;
private $id;
private $name;
private $email;
private $password;
private $identification;
private $cellphone;
Here are getter/setter pairs for each property
}
And this is my map class
namespace App\Entities\Users;
use App\Entities\BaseEntityMap;
class UserMap extends BaseEntityMap
{
protected $primaryKey = 'id';
public $softDeletes = true;
public $timestamps = true;
}
And this is the controller class
namespace App\Http\Controllers\Users;
use App\Http\Controllers\Controller;
use App\Http\ServiceResponse;
use App\Entities\Users\User;
use Faker\Factory as Faker;
use Carbon\Carbon;
use Monolog\Logger as Log;
class UserController extends Controller
{
public function createRandom()
{
$logger = new Log("error");
$randomUsers = array();
for($i=0; $i<1000; $i++)
{
$userMapper = $this->mapper->mapper(User::class);
$faker = Faker::create();
$user = new User();
$user->setName($faker->name);
$user->setEmail($faker->email);
$user->setPassword(bcrypt(rand(1000, 9999)));
$user->setIdentification(bcrypt(rand(1000000, 100000000)));
$user->setCellphone($faker->phoneNumber);
//$user->setCreatedAt(Carbon::now());
//$user->setUpdatedAt(Carbon::now());
//$user->setDeletedAt(null);
$logger->error("user --> " . print_r($user, true));
$userMapper->store($user);
$randomUsers[] = $user->convertToStdClass();
}
$response = new ServiceResponse(0, "createRandom", $randomUsers, "success");
return response()->json($response->toJson());
}
}
And this is what the query looks like on the postgres log file
2016-05-26 10:22:17 COT [4777-1] postgres#ewbackend ERROR: no existe la columna «users_id_seq» en carácter 76
2016-05-26 10:22:17 COT [4777-2] postgres#ewbackend SENTENCIA: insert into "users" ("created_at", "updated_at") values ($1, $2) returning "users_id_seq"
In english it's says that the column "users_id_seq" doesn't exists, but I already check on the db, and that sequence exists.
And this is the sql for the user table
-- Table: public.users
-- DROP TABLE public.users;
CREATE TABLE public.users
(
id integer NOT NULL DEFAULT nextval('users_id_seq'::regclass),
name character varying(255) NOT NULL,
email character varying(255) NOT NULL,
password character varying(255) NOT NULL,
identification character varying(255) NOT NULL,
cellphone character varying(255) NOT NULL,
remember_token character varying(100),
created_at timestamp(0) without time zone,
updated_at timestamp(0) without time zone,
deleted_at timestamp(0) without time zone,
CONSTRAINT users_pkey PRIMARY KEY (id),
CONSTRAINT users_email_unique UNIQUE (email),
CONSTRAINT users_identification_unique UNIQUE (identification)
)
WITH (
OIDS=FALSE
);
ALTER TABLE public.users
OWNER TO postgres;
I also check the table (I created with a migration, just add some fields to the migration user example included with laravel 5.2.33) and all columns are there, with the correct types
I try assigning the dates by my self, but that make no difference.
I also try to quit the timestamps=true on my map class but then i see another error in which the query has no fields or values on the postgres log file, and I need the timestamps columns.
The log showings the user instance, shows that all of the data was set correctly.
I also try to put the entity properties public instead of private but that doesn't work.
So I apreciate any ideas on this issue. Also if can you tell me if analogue support postgres transactions (a set of queries that runs as one in order to fail if one of the queries fails or commit only if all the queries were successfull operations )

Analogue Entities use magic setters getters, so you don't have to manually add private properties + getters and setters.
Did you try :
class BaseEntity extends Entity
{
}
And set your column like this :
$user->name($faker->name);
$user->email($faker->email);
etc..
And yes afaik, it does support transactions on Postgres.

Related

Saving model with not nullable relationship

Consider the following two relations:
User:
CREATE TABLE user (
id INT NOT NULL,
social_provider_id INT NOT NULL,
CONSTRAINT `user_social_provider_id_fk` FOREIGN KEY (`social_provider_id`)
REFERENCES `social_provider` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
)
Social provider:
CREATE TABLE social_provider (
id INT NOT NULL,
name VARCHAR NOT NULL )
Eloquent models:
class User extends Model{
protected $table = 'user';
public function socialProvider(){
return $this->hasOne('/SocialProvider');
}
}
Now I want to create a new User object and save it:
$user = new User();
$socialProvider = SocialProvider::find(1);
$user->socialProvider()->save($socialProvider);
$user->save();
But I get this exception on the line where I assign the SocialProvder object
Call to undefined method Illuminate\Database\Query\Builder::save()
I tried to save the User object first and then assign the relationship, but obviously this is not possible because of the NOT NULL constraint in the definition of the user table.
My workaround at the moment is to assign the relationship this way:
$user->social_provider_id = $socialProvider->id;
But I would like to use Eloquent's features.
How can I save a new model with a not nullable relationship, without having to assign IDs by myself?
Solution:
Like #Panagiotis Koursaris suggested, the solution is to use associate() instead of save()
Try this:
$user = new User();
$socialProvider = SocialProvider::find(1);
$user->socialProvider()->associate($socialProvider);
$user->save();
In User model, do this
public function socialProvider(){
return $this->hasOne('App/SocialProvider');
}

Laravel 5 update without id

I have a problem in Laravel 5. When I update a record in database, I get error Unknown column 'id' in 'where clause'. In the controller, I use WHERE clause to get the record I want to update. My primary key is not id and the type is bigInteger. I've tried adding protected $primaryKey in the model but it doesn't work for bigInteger. Is there any way to use my own primary key instead of using id?
Controller
$item = Item::where('item_id','=',$item_id)->first();
$item.name = $name;
$item.type = $type;
$item.save();
pls add this line to your Item.php model
class Item extends Model {
// add this line only
protected $primaryKey = 'item_id';
//..... the rest of your model
since your using custom id name, laravel will not know what is your primary key without you specify it
Laravel's orm $primaryKey default is 'id'.
When orm update, it use the sql like:
... where {$this->primaryKey} = {$this->{$this->primaryKey}}
So when you class extends orm.
You should redefine protected $primaryKey = '<your_table_primary_key>';.
Try this $item = Item::where('item_id', $item_id)->first(); If still don't working add also protected $primaryKey = "item_id"; to your model

Using a UUID as primary key with Laravel 5

I'm trying to create tables that will have a primary key which is a UUID defined as binary(16) instead of the default auto-incrementing id field.
I've managed to create migrations using raw SQL statements though DB::statement like so:
DB::statement("CREATE TABLE `binary_primary_keys` (
`uuid` binary(16) NOT NULL DEFAULT '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;");
However, I have trouble getting the model working. I've followed the tutorial available here. I've defined my model like so:
class UuidModel extends Model
{
public $incrementing = false;
public $primaryKey = 'uuid';
/**
* The "booting" method of the model.
*
* #return void
*/
protected static function boot()
{
parent::boot();
/**
* Attach to the 'creating' Model Event to provide a UUID
* for the `id` field (provided by $model->getKeyName())
*/
static::creating(function ($model) {
$model->{$model->getKeyName()} = (string)$model->generateNewId();
echo($model->{$model->getKeyName()});
});
}
/**
* Get a new version 4 (random) UUID.
*/
public function generateNewId()
{
return Uuid::generate();
}
}
where Uuid is an alias to Webpatser\Uuid.
One problem, I'm having is I cannot derive UuidModel from Eloquent as explained in the tutorial. In fact I don't see an Eloquent class. I'm deriving from Model instead. I am guessing the tutorial was written in Laravel 4.
I would appreciate help in implementing tables with UUIDs as primary keys in Laravel 5.
EDIT 1:
So, if I define my class like so:
use Illuminate\Database\Eloquent
class UuidModel extends Eloquent { ... }
I get the following error:
PHP Fatal error: Class 'Illuminate\Database\Eloquent' not found in /home/vagrant/transactly/app/UuidModel.php on line 8
If I remove the use Illuminate\Database\Eloquent line, I get the following error:
PHP Fatal error: Class 'App\Eloquent' not found in /home/vagrant/transactly/app/UuidModel.php on line 8
Edit 2:
I have discovered that the static::creating event is never called for when instances of UuidModel are created.
I tried setting up the creating event listener in AppServiceProvider but that's not being called as well. Interestingly, the creating event is not called for a regular Laravel generated model User either.
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
/**
* Attach to the 'creating' Model Event to provide a UUID
* for the `id` field (provided by $model->getKeyName())
*/
echo "Booting...\n";
UuidModel::creating(function ($model) {
echo "Creating Uuid Model...\n";
$model->{$model->getKeyName()} = (string)$model->generateNewId();
});
User::creating(function($user){
echo "Creating User Model...";
$user->name = 'Forced Name in boot()';
});
}
public function register(){}
}
How about this idea for storing a 36chr UUID as Binary(16) :
IMO there is an advantage in not having Laravel generating the UUID. Namely, if new records (some day in the future) get inserted into the database from outside the application the UUID field is properly populated.
My suggestion: Create a UUID default value trigger using migrations
(this trigger makes the DataBase server do the work to generate the UUID each time a new customer is inserted)
<?php namespace MegaBank\HighInterestLoans\Updates;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class MigrationTriggerForCustomers extends Migration
{
public function up()
{
DB::unprepared('CREATE TRIGGER before_insert_customers
BEFORE INSERT ON
`megabank_highinterestloans_customers`
FOR EACH ROW
SET new.uuid = UNHEX(REPLACE(UUID(), "-","");');
}
public function down()
{
DB::unprepared('DROP TRIGGER `before_insert_customers`');
}
}
Finally, if you want to get a human-readable version of your UUID just do the following:
SELECT HEX(UUID) FROM customers;
Anyway, hope this helps someone :-)
So, I got the thing working like a charm (not tested unit testing):
class UuidModel extends Eloquent is an older (Laravel 4) construct. We use class UuidModel extends Model in Laravel 5
The solution was to move the
UuidModel::creating(function ($model) {
echo "Creating Uuid Model...\n";
$model->{$model->getKeyName()} = (string)$model->generateNewId();
});
from AppServiceProvider::boot() to EventServiceProvider::boot(). No other changes were required. Everything worked as expected.
I still don't know why (2) works in EventServiceProvider and not in AppServiceProvider as explained in the official docs. But judging from the name, that's perhaps the way it was meant to be.
This is a quick solution without using events.
UUidModel.php
<?php namespace App;
use \Illuminate\Database\Eloquent\Model;
use \Illuminate\Database\Eloquent\Builder;
class UuidModel extends Model
{
/**
* Insert the given attributes and set the ID on the model.
*
* #param \Illuminate\Database\Eloquent\Builder $query
* #param array $attributes
* #return void
*/
protected function insertAndSetId(Builder $query, $attributes)
{
$keyName = $this->getKeyName();
$id = $attributes[$keyName] = $this->generateNewId();
$query->insert($attributes);
$this->setAttribute($keyName, $id);
}
/**
* Get a new version 4 (random) UUID.
*/
public function generateNewId()
{
return 'uuid!!' ;// just for test
}
}
?>
Model Example Car.php
<?php namespace App;
class Car extends UuidModel {
}
also try use this package will automatically generate and assign UUID field in your model, also can show and update by UUIDs key.
https://github.com/EmadAdly/laravel-uuid

Laravel4 Model primary key value is lost after insert

<?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'.)

Database_Exception [ 1146 ]: Table 'kohana.userdetailses' doesn't exist

This is my Controller
userdetails.php
<?php defined('SYSPATH') or die('No direct script access.');
class Controller_Userdetails extends Controller {
public function action_index() {
$view = new View('userdetails/index');
$this->response->body($view);
}
public function action_add() {
$userdetails = new Model_Userdetails();
$view = new View('userdetails/adddetails');
$view->set("userdetails", $userdetails);
$this->response->body($view);
}
model is
userdetails.php
<?php defined('SYSPATH') or die('No direct script access.');
class Model_Userdetails extends ORM {
}
userinfo.sql
CREATE TABLE `kohana`.`userinfo` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`first_name` varchar(100) DEFAULT NULL,
`last_name` varchar(100) DEFAULT NULL,
`email` varchar(100) DEFAULT NULL,
`description` text,
PRIMARY KEY (`id`)
);
I am newly learning php and kohana.I am using kohana 3.2 version.I am following this tutorial to create,edit,update and delete data in database.I tried with above code,i am getting this error
"Database_Exception [ 1146 ]: Table 'kohana.userdetailses' doesn't exist [ SHOW FULL COLUMNS FROM `userdetailses` ]"
need some help to solve this.
Kohana guesses the table name if $_table_name is not set. It pluralizes the model name as most of the time a model describes a single object, and the table describes a lot of them.
EDIT:
I saw you actually named your table userinfo and the model userdetails. If that is what you want:
class Model_Userdetails {
protected $_table_name = 'userinfo';
........
}
Or alternatively rename the model to Model_Userinfo, or the table to userdetails and:
--- END EDIT ---
In your case it would seem most appropiate to:
class Model_Userdetails {
protected $_table_name = 'userdetails';
........
}
Offcourse, you could alternatively rename your class to Model_Userdetail so that the table name will be guessed as userdetails
UPDATE:
Even though Kohana should guess these as well (i.e. SHOW FULL COLUMNS FOR table or sth), this might resolve the property not found error as discussed below in the comments.
protected $_table_columns = array(
'id' => array('type' => 'int'),
'firstname' => array('type' => 'string'),
....... // repeat for all columns
);
Update:
There is a typo in your PHP code: deScription. Anyway, it is a good habit to define the table columns as this will save you an extra query every time a model is initialized for the first time. Along with some validation stuff which can take parameters from the array (e.g. the description of type TEXT is more or less not restricted in length, but you might want to limit it to say 2000 characters)

Categories