How to generate gii crud Yii2 without Primary Key? - database

How can i generate the crud wihtout primary key because, my dabatase, this table don't have a primary key. there is FK only.
when i try to generate it will be like this
image.
Thank you for your help.

I think, it is not very good to use CRUD without PK. But, if there are no other options, you can add fake PK variable to table temporarily and after generation delete that. You should change some code to escape errors on generated files (controller and views) to remove references to that fake variable. And you should be more careful, because, you could update or delete some other record instead needed one
Update
Assuming that the DB structure is like this one and you should generate CRUD for the table 'othertable', you can:
add PK as "id" to the table
regenerate model "Othertable"
generate CRUD for "othertable"
Remove id from table
Regenerate "Othertable"
Add these lines to "Othertable":
//imitate id
public $id;
//rediclare init
public function init() {
parent::init();
$this->id= $this->sometable_id;
}
// Rediclare primary key. For this condition sometable_id
// have chosen as primary
// key. We can change it
public static function primaryKey() {
return ['sometable_id'];
}
Remove id from OthertableSearch model
Change findModel($id) method on OthertableController as:
protected function findModel($id)
{
if (($model = Othertable::find()->where(['sometable_id'=>$id])->one()) !== null) {
$model->id=$model->sometable_id;
return $model;
}
throw new NotFoundHttpException('The requested page does not exist.');
}
Attentions
In this example I used sometable_id of the "othertable" assuming that there is only one record on the table with this sometable_id value (a.g. unique), otherwise every time you can get first record and change/delete that instead needed one. It can be changed to other unique variable(s) of the table. If you want use other variable, you should change on model and on findModel() method of the controller.

Related

auto increment field in Peewee

Is there a way to define autoincrement Field in peewee.
I understand we could define sequence but the need to create the sequence manually and not managed by create_tables deters me from using it. ( The build process is managed by create tables and I would prefer not to add manual steps )
import peewee
class TestModel(peewee.Model):
test_id = peewee.BigIntegerField(sequence='test_id_seq')
Alternate to the above code I would rather have. As most databases have serial field I dont see a point maintaining a sequence.
import peewee
class TestModel(peewee.Model):
test_id = peewee.AutoIncremenetIntField()
Either you can use PrimaryKeyField() as #wyatt mentioned in comment
or you can use Playhouse- Signal Support (peewee extensions)
from playhouse.signals import Model, pre_save
class MyModel(Model):
data = IntegerField()
#pre_save(sender=MyModel)
def on_save_handler(model_class, instance, created):
# find max value of temp_id in model
# increment it by one and assign it to model instance object
next_value = MyModel.select(fn.Max(MyModel.temp_id))[0].temp_id +1
instance.temp_id = next_value
The given answers here are outdated but this was still my first Google search result.
Peewee has a special field type for an auto incrementing primary key called AutoField:
The AutoField is used to identify an auto-incrementing integer primary
key. If you do not specify a primary key, Peewee will automatically
create an auto-incrementing primary key named “id”.
Take a look at the documentation. Example usage:
class Event(Model):
event_id = AutoField() # Event.event_id will be auto-incrementing PK.

Retrieving data from referenced key table - Laravel-4

The structure of concerning tables is as follows (MySQL):
//Table Name : team
tid PK
team_name (varchar)
//Table Name : fixture
fid PK
home_team_id FK |_ both referenced to 'tid' from 'team' table
away_team_id FK |
My aim is to retrieve the team names. Considering this structure, I think I'll have to retrieve home_team_id and away_team_id and then do something like
Fixture::where('tid','=',$home_team_id)->get();
My question is, is this the correct way to accomplish what I aim to do?
and
should this be done from the controller? (if so, then I'll have to do two queries from same function)
First, rather than having your primary keys be tid and fid, just keep them both as id. This is not only best practice, but will allow you to more easily use Laravel's Eloquent ORM as it by default assumes your primary key column is named id.
Second thing, make sure your table names are in plural form. Although this is not necessary, the example I'm about to give is using Laravel defaults, and Laravel assumes they are in plural form.
Anyway, once you've 'Laravelized' your database, you can use an Eloquent model to setup awesome relationships with very minimal work. Here's what I think you'd want to do.
app/models/Team.php
class Team extends Eloquent {
// Yes, this can be empty. It just needs to be declared.
}
app/models/Fixture.php
class Fixture extends Eloquent {
public function homeTeam()
{
return $this->belongsTo('Team', 'home_team_id');
}
public function awayTeam()
{
return $this->belongsTo('Team', 'away_team_id');
}
}
Above, we created a simple model Team which Laravel will automatically look for in the teams database table.
Second, we created model Fixture which again, Laravel will use the fixtures table for. In this model, we specified two relationships. The belongsTo relationship takes two parameters, what model it is related to, in both cases here they are teams, and what the column name is.
Laravel will automatically take the value in away_team_id and search it against the id column in your teams table.
With just this minimal amount of code, you can then do things like this.
$fixture = Fixture::find(1); // Retrieves the fixture with and id of 1.
$awayTeam = $fixture->awayTeam()->first(); // var_dump this to see what you get.
$homeTeam = $fixutre->homeTeam()->first();
Then you can proceed as normal and access the column names for the tables. So say you have a 'name' column in the teams table. You can echo out the the home team name from the fixture like so.
$fixture = Fixture::find(1); // Get the fixture.
echo $fixture->homeTeam->name;
It's nearly 2AM, so there might be an error or two above, but it should work.
Make sure you check the docs for Eloquent, especially the bits relating to relationships. Remember to name your columns and tables in the way Laravel wants you to. If you don't, there are ways to specify your custom names.
If you want to get even more fancy, you can define the inverse relationship like this on your Team model.
app/models/Team.php
class Team extends Eloquent {
public function fixturesAtHome()
{
return $this->hasMany('Fixture', 'home_team_id');
}
public function fixturesAway()
{
return $this->hasMany('Fixture', 'away_team_id');
}
}
Then to get all of a particular team's home fixtures...
$team = Team::find(1); // Retreive team with id of 1;
$homeFixtures = $team->fixturesAtHome();

cakephp id convention saveField issue

I have a "production" table with field employee_id as a belongsTo relation to employees table.
The problem is my employees table uses field emp_appserial as primary key -as opposed to id field- (not every entry on employees table gets an id value, everyone gets auto increment emp_appserial)
I wonder if there is a way to use saveField using a field other than id to get to my record: (I mentioned I have records with no "id" value, only emp_appserial, which is pk)
$this->loadModel('Employees');
$this->Employees->id = $id;
$this->Employees->saveField('emp_hrnote', 'text to be saved');
I'd like to use:
$this->Employees->emp_appserial = $id;
instead of
$this->Employees->id = $id;
I that doable?
Aside from that, it may not be too late to re-design my tables, but I already have a lot of production data :-(
Thank you for any pointers.
The following should do the trick (btw, models should be singular):
class Employees extends Model {
public $primaryKey = 'emp_appserial';
}
If you don't set the $primaryKey attribute, it gets set to id: Source
Once you set that saveField() will use that field for the condition: Source
Edit: Just to make it clear, you would still use Model::$id to set the primary key value. Model::$id holds the primary key value, Model::$primaryKey holds the primary key field
Used
$this->Employee->updateAll(
array('Employee.emp_hrnote' => "$thetxt"),
array('Employee.emp_appserial' => $id)
);
As a workaround is just fine, however I wish I could solve my empty id issue... will post another issue with this on another post.

How to set parent_id=NULL in child table when record in parent table is deleted?

How to set parent_id=NULL in child table when record in parent table is deleted?
It's like ON DELETE = SET NULL in MySQL INNODB tables, but I would like to avoid using all this (cascading, ignoring, updating and setting null) functionality in INNODB level and move it to atk4 Model to keep all this in logic one place.
For example,
class Model_Parent extends Model_Table{
public $table='parent';
function init(){
parent::init();
$this->addField('name');
$this->hasMany('Child');
$this->addHook('beforeDelete',$this);
}
function beforeDelete($m){
// I guess here I should somehow set parent_id=NULL in all related Model_Child
// records, but when I do so, then it's again DB constraint violation of course
$c = $m->ref('Child');
foreach($c as $junk){
$c->set('parent_id',NULL); // this and below is not working
$c->save();
}
}
}
class Model_Child extends Model_Table{
public $table='child';
function init(){
parent::init();
$this->addField('name');
$this->hasOne('Parent');
}
}
It's simple, you just need to go into DSQL from Model:
$m->ref('Child')->dsql()->set('parent_id',null)->update();
More info: http://www.youtube.com/watch?v=sSRaYpoJFHk&list=PL7CBF92AB03A1CA3B&index=3&feature=plpp_video
You are trying to re-invent the wheel by doing a typical database task in your code.
If you don't want the database to manage the foreign key relations, you shouldn't use those relations. In that case you can set your columns to NULL or any other value. But no one could prove the consistency of your database.
Check if parent_id column permits NULL values.

One To Many and Duplicate entry

I use JPA->Hibernate. PlayFramework. I want to have relationship.
Category - 1:n -> Tag
Every category can have many tags, but tags do not know about it.
So, i do like this:
#Entity
public class Category ... {
#OneToMany
public List<Tag> tags = new LinkedList<Tag>();
}
I have test:
#Test
public void playWithTags() {
Tag tag1 = new Tag("tag1").save(); // managed by playframework
Category cat1 = new Category("cat1");
cat1.tags.add(tag1);
cat1.save();
// check if tag1 and cat1 were saved
assertEquals(1, Tag.count());
assertEquals(1, Category.count());
Category cat2 = new Category("cat2");
cat2.tags.add(tag1);
cat2.save();
}
The result is:
16:18:01,555 ERROR ~ Duplicate entry '1' for key 'tags_id'
16:18:01,555 ERROR ~ Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelp
....
java:908)
at java.lang.Thread.run(Thread.java:619)
Caused by: java.sql.BatchUpdateException: Duplicate entry '1' for key 'tags_id'
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2020)
It seems that cat2.save() try to do more then it should
If if use merge() instead of save() it works good:
cat2.merge();
BUT WHY?
I have fixed the problem. The problem was in that, that I used NOT THAT annotation. So i just changed #OneToMany to #ManyToMany and voilà - No any restrictions anymore.
But if saying about the OneToMany then it seems there was a unique-restriction on database-level which prevented us to put not-unique values to tags_id. Therefore we could not put same tag to One category. I.e. it wanted One category for Many tags, but if tags were already 'used' - no way.. I tried to put unique=true/false in #JoinTable -> #JoinColumn - but it does not help. For me it's still strange, but at least current problem was fixed.
You're mixing up two concepts: Primary key and foreign key.
There can be only one PK but FK just means "there must be an element with this ID in some other table". FK doesn't constrain uniqueness.
[EDIT] Your problem is that you're mixing entities. How did you get the tag1 which is returned by save()?
This entity must be one which you get from Hibernate, not the result from new. Even if it looks insane, you must do this in save():
session.save(tag);
return session.load(tag.getId());
This way, you get an entity that is managed by Hibernate. Only when the entity is managed by Hibernate, Hibernate knows when it has to save the entity and when it has already been saved.
So when you do cat2.tags.add(tag1); in your example above, Hibernate thinks "oh, I don't know anything about this tag, it must be a new one".
And tries to save the tag again.

Resources