I cretead model, with columns:
like4u_id, vtope_id, panel_id
I set these columns option - Nullable, but if i save model, i get error:
SQLSTATE[HY000]: General error: 1366 Incorrect integer value: '' for
column 'like4u_id' at row 1 (SQL: update
master_vars set updated_at = 2018-05-23
16:03:14, like4u_id = , vtope_id = where id = 328)
What is the problem? It's field not required and column nullable..
It may happen with MySQL databases.
You need to use the Nullable trait in your model for set to NULL the attributes when left empty.
Here is the docs of the Nullable trait
When a form field is empty but should contain an "integer" value in the database some engines will try to insert an empty string into an integer field.
This is what causes the error message, basically trying to put the square through the round hole.
If you implement the Nullable trait you can make sure that these fields, if left empty are inserted as a true NULL instead of a string
I prefer to have my trait as a use statement above the class and then a short use int the class itself.
You can also put it directly in the class by use \October\Rain\Database\Traits\Nullable; instead of use Nullable; if you don't wish to have it appear in two spots. It's up to your preference.
use Model;
use October\Rain\Database\Traits\Nullable;
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/**
* Page Model
*/
class ModuleLink extends Model
{
public $table = 'your_table_name_here';
use Nullable; // This sets the trait to be used in this Model.
//^^^^^^^^^^^^^
public $nullable = [
'module_id', // Define which fields should be inserted as NULL when empty
'sort_order',
];
Related
if I run the following:
App\User::selectRaw('country as id, COUNT(*) as value')->groupBy('country')->get()
I get the correct output:
all: [ App\User {#705 id: "UK", value: 2,},],}
However when I run
App\User::selectRaw('country as id, COUNT(*) as value')->groupBy('country')->get()->toJSON()
it seems to flip the id value to 0:
[{"id":0, "value":2}]
now what's interesting is if I convert it so that I don't alias the country field I get the correct output:
[{"country":"UK", "value":2}]
I need to have the field returned as id but can't seem to work out why it's doing this
When you call toJson() on the model, if the $incrementing property is true, Laravel will automatically attempt to cast the $primaryKey field to the $keyType type. If you have not overridden any of these values, that means the id field will get cast to an int during the json generation.
In your select, you named your country field as id, so when you generate the json, it attempts to cast this value (UK) to an int, which of course is 0.
You can change your select statement to not name the field id, or you can work around this functionality in a ton of different ways, either modifying model properties before and after the call to toJson(), or by overriding the getCasts() method to avoid this functionality altogether.
Edit
Without knowing your codebase or your use cases, I would say the most flexible solution for you would be to add a new method to your App\User model, something like:
public function toJsonCustom($options = 0)
{
$incrementing = $this->getIncrementing();
$this->setIncrementing(false);
$json = $this->toJson($options);
$this->setIncrementing($incrementing);
return $json;
}
Then, you call your custom toJson method instead of the original one:
App\User::selectRaw('country as id, COUNT(*) as value')
->groupBy('country')
->get()
->toJsonCustom();
I have an existing entity in database. I would like to add a new column to this entity:
/**
* #ORM\ManyToOne(targetEntity="Language")
* #ORM\JoinColumn(name="language_id", referencedColumnName="id", nullable=false)
*/
protected $language;
When I now use "vendor/bin/doctrine-migrate migrations:diff", the generated migration script does not contain a default value for language_id. Therefore the migration-script fails. Setting a default value for the property in the object does not help. How can I define a default value for the fk-column? I neither found something in doctrines documentation nor through google/stackoverflow.
If the column is not null then it should represent a valid relationship; assuming you use 0 instead, Doctrine will try to load the association using that, which would of course fail. In these cases you would need to update the database and mapping to allow a null value.
If however you require a default language association to be defined then you explicitly need to set it when you create the entity.
$language = $entityManager->find(1);
$entity = new Entity;
$entity->setLanguage($language);
$entityManager->persist($entity);
$entityManager->flush();
For this reason, you might want to consider a 'service' that encapsulates the creation of your entity so you know a language will always be valid and assigned by default.
It may not be a clean way to do it, but maybe you can execute the SQL query yourself and add manually the DEFAULT statement ?
ALTER TABLE registered_user ADD language_id VARCHAR(255) NOT NULL DEFAULT {default_value} WITH VALUES;
I'm quite surprised that adding a default property in the annotation is not working here!
In laravel 5.1 there is new feature called Attribute Casting, well documented at here :
http://laravel.com/docs/5.1/eloquent-mutators#attribute-casting
My question is, it is possible to make attribute casting dynamically ?
for example, I have a table with columns :
id | name | value | type |
1 | Test_Array | [somearray] | array |
2 | Test_Boolean | someboolean | boolean |
it is possible to set value attribute cast, depends on type field, that work both in write(create/update) and fetch ?
You'll need to overwrite Eloquent model's getCastType() method in your model class:
protected function getCastType($key) {
if ($key == 'value' && !empty($this->type)) {
return $this->type;
} else {
return parent::getCastType($key);
}
}
You'll also need to add value to $this->casts so that Eloquent recognizes that field as castable. You can put the default cast there that will be used if you didn't set type.
Update:
The above works perfectly when reading data from the database. When writing data, you have to make sure that type is set before value. There are 2 options:
Always pass an array of attributes where type key comes before value key - at the moment model's fill() method respects the order of keys when processing data, but it's not future-proof.
Explicitely set type attribute before setting other attributes. It can be easily done with the following code:
$model == (new Model(['type' => $data['type']))->fill($data)->save();
The $casts attribute it used whenever you access a field, not when it is fetched from the database. Therefore, you can update the $casts attribute after the model has been populated, and it should work fine whenever you access the value field. You just need to figure out how to update the $casts attribute when the type field is changed.
One potential option would be to override the fill() method so that it calls the parent fill() method first, and then updates the $casts attribute with the data in the type field.
Another potential option would be to abuse the mutator functionality, and create a mutator on the type field, so that whenever it changes, it would update the $casts attribute.
Some of the answers here are really overthinking things, or they're subtly wrong.
The principle is simply to set the $casts property before you need it, eg. before writing or reading properties to the database.
In my case I needed to use a configured column name and cast it. Because PHP doesn't allow function calls in constant expressions, it can't be set in the class declaration, so I just declared my column/property's cast in my model's constructor.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class MyModel extends Model
{
protected $casts = [
// we can't call a function in a class constant expression or
// we'll get 'Constant expression contains invalid operations'
config('my-table.array-column.name') => 'array',
];
public function __construct()
{
$this->casts = array_merge(
$this->casts,
[
// my column name is configured so it isn't known at
// compile-time so I have to set its cast run-time;
// the model's constructor is as good a place as any
config('my-table.array-column.name') => 'array',
]
);
parent::__construct(...func_get_args());
}
}
Suppose I have to set column value formula to 1. So how can I do it before persisting. After persisting I should get 1 in database.
$f=1;
$product->setFormula($f);
$em->persist($product);
If I use above line it gives an error
Expected value of type "Nimo\MrmdBundle\Entity\Product" for
association field "Nimo\MrmdBundle\Entity\Product#$basedOn", got
"integer" instead
Here is entity code
/**
* #ORM\ManyToOne(targetEntity="Product")
* #ORM\JoinColumn(name="formula", referencedColumnName="someothercolumn",nullable=true)
**/
private $formula = null;
You have to correct your entity definition first, However here's what you need to do in your controller. This will not work until you make sure your entities are correctly defined. (I can't because I don't know your entity definitions)
$f=1;
$em = $this->container->get('doctrine.orm.entity_manager');
$repo = $em->getRepository('AppBundle:Formula'); //This should be your referred entity
//You can also do findOneByName below
$formula= $repo->findOneById($id); //This should be the primary key of the referred entity NOT 1
$formula->setFormula($f);
$em->persist($formula);
When you are creating a relationship between two entities you can not pass a single value or variable containing a single value.
Entity works on objects. So try to pass the object of some entity or create an object with some value it will work. I also face the same error while passing a single value. Just pass the Object of an entity relationship annotation will picked up the joining column of other entity.
If a table has defaults on certain fields and NULL is not allowed, one would expect the insert script to use those defaults, as MariaDB/MySQL usually does. For example, if the table products has an AI field "id", a required field "name" and two required fields "active" and "featured" which both default to 1, then the query
INSERT INTO products (name) VALUES ('someName');
automatically inserts 1 as the value of active and featured. However, when using Phalcon's models like so:
$product = new Products();
$product->setName('someName');
$product->save();
returns validation errors saying "active" and "featured" are required.
Is there a flag I should provide during model generation in order for Phalcon tools to harvest and input the defaults into Model classes, or another way to make Phalcon automatically use defaults if found? Best approach would be just ignoring the fields that weren't set, I reckon. Can I make the models do that?
You can use a raw database value to avoid that, in specific inserts:
<?php
use Phalcon\Db\RawValue;
$product = new Products();
$product->setName('someName');
$product->setType(new RawValue('default')); //use default here
$product->save();
Or, general before create/update for specific fields:
use Phalcon\Db\RawValue;
class Products extends Phalcon\Mvc\Model
{
public function beforeValidationOnCreate()
{
$this->type = new RawValue('default');
}
}
Or ignore these fields in every SQL INSERT generated:
use Phalcon\Db\RawValue;
class Products extends Phalcon\Mvc\Model
{
public function initialize()
{
$this->skipAttributesOnCreate(array('type'));
}
}
Although I find twistedxtra's answer fascinating from the aspect that Phalcon contains this wicked method to read the column default, I believe from a architectural point of view this might be the wrong approach as you rely on your database to define the defaults of the properties of your model.
I would set the default value when declaring the property and keep the logic in the application layer. But that's just me.
Use Like below
The skipAttributesOnCreate will make sure Phalcon does not attempt to put a a value in that column. The database will apply the default value.
public function initialize()
{
$this->setSource('table_name');
$this->skipAttributesOnCreate(['name_of_column']);
}