how to get model primary key value after save - yii2

i have a problem when i try to get the primary key (auto increment) from the db after i save the model.
In the database the tabel doesn't have a primary key so i set it using this:
public static function primaryKey(){
return ['id_cod'];
}
And i removed it from the models rules.
When i save the model, all the data is saved on the db included id_cod, but if i try to access to this property it gives me null.
$evento = new Evento();
//populate the model with some data
//..... eg: $evento->name = 'name';
//save model
$evento->save();
$evento->refresh();
echo Yii::$app->db->getLastInsertID(); // gives me the correct id_cod but i think it's not the correct way
echo $evento->id_cod;//gives me null
echo $evento->name;//gives me name
How can i get the id_cod just after save the model?

Related

django admin site returns MultipleObjectsReturned exception with inspectdb imported legacy database and composite primary key

Using inspectdb, I have imported a legacy database, that contains entities with composite primary keys, in django . The database schema contains about 200 different entities and inspectdb is quite handy in that situation.
This is the schema in mysql:
CREATE TABLE `mymodel` (
`id` bigint(20) unsigned NOT NULL DEFAULT '0',
`siteid` bigint(20) unsigned NOT NULL DEFAULT '0',
...
PRIMARY KEY (`siteid`,`id`),
...
Following the autogenerated model in django (imported using python manager.py inspectdb)
class Mymodel(models.Model):
id = models.PositiveBigIntegerField()
siteid = models.PositiveBigIntegerField(primary_key=True)
...
class Meta:
managed = False
db_table = 'mymodel'
unique_together = (('siteid', 'id'),
I have registered all models in the admin site using the following approach:
from django.contrib import admin
from django.apps import apps
app = apps.get_app_config('appname')
for model_name, model in app.models.items():
admin.site.register(model)
After all the work is done, I navigate to the admin site and click on any object in the "mymodel" section and the following exception will be returned:
appname.models.Content.MultipleObjectsReturned: get() returned more than one Mymodel-- it returned more than 20!
Obviously, (this is what it seems to me at least) admin is using the siteid to get the object, tough it should use the unique_together from the Meta class.
Any suggestions how I can achieve to solve this with a general configuration and get the admin site module to query using the unique_together?
Yes you can solve this problem but you put a little more effort.
First you separate model-admin class for model Mymodel and customize model-admin class method:
Since django admin build change url in ChangeList class, So we can create a custom Changelist class like MymodelChangelist and pass id field value as a query params. We will use id field value to getting object.
Override get_object() method to use custom query for getting object from queryset
Override get_changelist() method of model-admin to set your custom Changelist class
Override save_model() method to save object explicitly.
admin.py
class MymodelChangelist(ChangeList):
# override changelist class
def url_for_result(self, result):
id = getattr(result, 'id')
pk = getattr(result, self.pk_attname)
url = reverse('admin:%s_%s_change' % (self.opts.app_label,
self.opts.model_name),
args=(quote(pk),),
current_app=self.model_admin.admin_site.name)
# Added `id` as query params to filter queryset to get unique object
url = url + "?id=" + str(id)
return url
#admin.register(Mymodel)
class MymodelAdmin(admin.ModelAdmin):
list_display = [
'id', 'siteid', 'other_model_fields'
]
def get_changelist(self, request, **kwargs):
"""
Return the ChangeList class for use on the changelist page.
"""
return MymodelChangelist
def get_object(self, request, object_id, from_field=None):
"""
Return an instance matching the field and value provided, the primary
key is used if no field is provided. Return ``None`` if no match is
found or the object_id fails validation.
"""
queryset = self.get_queryset(request)
model = queryset.model
field = model._meta.pk if from_field is None else model._meta.get_field(from_field)
try:
object_id = field.to_python(object_id)
# get id field value from query params
id = request.GET.get('id')
return queryset.get(**{'id': id, 'siteid': object_id})
except (model.DoesNotExist, ValidationError, ValueError):
return None
def save_model(self, request, obj, form, change):
cleaned_data = form.cleaned_data
if change:
id = cleaned_data.get('id')
siteid = cleaned_data.get('siteid')
other_fields = cleaned_data.get('other_fields')
self.model.objects.filter(id=id, siteid=siteid).update(other_fields=other_fields)
else:
obj.save()
Now you can update any objects and also add new object. But, On addition one case you can't add- siteid which is already added because of primary key validation

Can I use AUTO_INCREMENT in my laravel project?

I have an Eloquent model that has a column that is a number composed of various codes and at the end a number that should increment automatically. This last number is the same number I use to define the primary key of my model, so my question is:
Is there a way to use the AUTO_INCREMENT variable from my MySQL database?
If not, what is the best way to create a variable in Laravel that automatically increments?
example:
$code1 = $this->getCode1();
$code2 = $this->getCode2();
$autoIncr = ...;
$final_code = $code1 . $code2 . $autoIncr;
you can create a function that returns the next id (autoincrement) of your table and the insert the entry in your table;
$code1 = $this->getCode1();
$code2 = $this->getCode2();
$autoIncr = $this->getNextAutoincrement();
$final_code = $code1 . $code2 . $autoIncr;
//Insert in your table
$row = YourModel::create([
'finalCode' => $final_code
]);
private function getNextAutoincrement() {
//don't forget import DB facade at the beginning of your class
$id = DB::select("SHOW TABLE STATUS LIKE 'YOUR_TABLE_NAME'");
$next_id=$id[0]->Auto_increment;
return $next_id;
}
Hope I've helped you

Ionic3 - fastest way to syncronize big JSON file data with Sqlite

Good afternoon, I am creating an application in ionic using angular where currently it handles two connection modes: connected if the user has internet access and disconnected if they do not have it
Currently I have a feature and it is that the user has the possibility to sync data and apply in SQLite
like this JSON (to syncronize)
{
countries: [/* 200+ records */],
vaccine: [/* 3000+ records */],
... other 20 keys
}
and the SQLite structure(mobile) has a table per key like this
CREATE TABLE IF NOT EXISTS countries(
id INTEGER PRIMARY KEY,
code TEXT NOT NULL,
name TEXT NULL,
--- other columns
);
CREATE TABLE IF NOT EXISTS vaccine(
id INTEGER PRIMARY KEY,
name TEXT NULL,
--- other columns
);
How can I execute the synchronization process without executing sql per cycle? but validating that if the row exists, update it
public descargar(clave): void {
this.descargarParametricas().subscribe(
parametros => {
// make process by key
Object.keys(parametros).forEach(
index => this.descargarParametrica(index, parametros[index]) : void(0)
);
}
);
}
public descargarParametrica( key: string, parametros: any[] ){
parametros.forEach( item => {
const headers = Object.keys(item);
const rows = Object.values(item).map( item => item === '' ? 'NULL' : item );
const sqlQuery = `INSERT INTO ${key}(${headers.join()}) VALUES (${rows.join()});`;
// execute query per loop is too slow, only countries data(200 records) affect performance and stop
this.datalayer.execute(sqlQuery);
})
}
this.descargarParametricas() return a JSON 40kb size, the problem is that the insertion process must be done by the key of the json and update if the row exist, actually have a performance issues because the insertion/update process execute row per row
thanks for all

Yii2 REST API update (put) when composite key

I am trying to update my model via PUT http request in Yii2 framework.
Everything works fine when I have single Primary Key in my model.
Problems are when I have composite primary key in table.
How to update?
I submit JSON:
{"date_execution":"2017-08-26","order_id":"59", "company_id":13,"your_price":100,"car_id":"8","note":"lorem ipsum"}
my composite primary key include:
- order_id
- company_id
I tried following requests:
PUT SERVER/offer/100 - where 100 is company_id
PUT SERVER/offer/2000 - where 2000 is order_id
those 2 requests are returning problem:
{"name":"Not Found","message":"Object not found: 13","code":0,"status":404,"type":"yii\\web\\NotFoundHttpException"}
I also tried
PUT SERVER/offer/2000/100 - where 2000 is order_id and 100 is company_id
PUT SERVER/offer/100/2000
those 2 return controller/action not found exception
Also I added order_id and company_id to JSON,
but nothing works.
Controller Class:
use yii\rest\ActiveController;
class OfferController extends ActiveController
{
// adjust the model class to match your model
public $modelClass = 'app\models\Offer';
public function behaviors(){
$behaviors = parent::behaviors();
// remove authentication filter
$auth = $behaviors['authenticator'];
unset($behaviors['authenticator']);
// add CORS filter
$behaviors['corsFilter'] = [
'class' => CustomCors::className()
];
// re-add authentication filter
$behaviors['authenticator'] = [
'class' => CompositeAuth::className(),
'authMethods' => [
HttpBearerAuth::className(),
],
];
// avoid authentication on CORS-pre-flight requests (HTTP OPTIONS method)
$behaviors['authenticator']['except'] = ['options'];
return $behaviors;
}
}
It should work if you use PUT SERVER/offer/2000,100
You can print primaryKey() of the model to know the order of the keys.
You can see it in the docs here
https://www.yiiframework.com/doc/api/2.0/yii-rest-action
If composite primary key, the key values will be separated by comma.
yii\rest\UpdateAction uses ActiveRecord::findModel() method to load data. There is an answer in those phpdoc:
If the model has a composite primary key, the ID must be a string of
the primary key values separated by commas
So the right resource is (considering the first key field in the table structure is company_id)
PUT SERVER/offer/100,2000
You firstly need to add primaryKey() in the model, to override the default primaryKey() of the ActiveRecord class. This function needs to return your composite primary key.
What you need to do the model thus would be
primaryKey()
{
return array('company_id', 'order_id');
}

I want to get Id of primary table but get null and Trying to get property of non-object

Here is my controller code. Can someone help me? how can i get primary table id. I have primary table with one id and secondary table called articles in which all fields are shown here in controller code how can i get id of primary table(the relationship is primary and foreign key relationship)
public function store(Request $request)
{
$article = new Article;
$article->user_id = Auth::user()->id;
$article->content = $request->content;
$article->live = (boolean)$request->live;
$article->post_on = $request->post_on;
dd($article->user_id);
$article->save();
// Article::create($request->all());
}
You need to create an inverse relationship e.g. belongsTo in your Article model which attributes that article to your User model.
https://laravel.com/docs/5.4/eloquent-relationships#one-to-one
See the Defining The Inverse Of The Relationship section.
Then you can do something like $article->user->id.
If your relationships are already defined, use $article->fresh('user') after the save() method.