Binary Type Doctrine Symfony 6 - doctrine

I have saved my passwords in my database as binary type hashed with AES encryption.
Now I wanted to load them as entities in my symphony 6 application.
Unfortunately symfony doesn't support binary type.
So I tried to write the entity with this column as type string but this throws an error as symfony cannot read binary type as string.
#[ORM\Column(type: Types::BINARY,length: 50, nullable:true)]
private ?string $pwd = null;
public function getPwd(): ?string
{
return $this->pwd;
}
public function setPwd(string $pwd): self
{
$this->pwd = $pwd;
return $this;
}
Does anybody has a solution for this?
I don't want to change the values/type in the database as they are already used multiple times in other applications. Furthermore I don't need to add values to the database only read it with symfony. Actually, I do not even need to read the password column but the other columns and this is not possible if the entity throws an error because of the password column.

Related

How can I use type as STRING for polymorphic relation table ids (...able_id) table in laravel?

I will use the db example below (modified the example in laravel docs) to explain.
Table structure (modified example)
posts
id - integer
name - string
videos
id - string // here I have to use "string"
name - string
tags
id - integer
name - string
taggables
tag_id - string // should normally be "integer"
taggable_id - string // should normally be "integer"
taggable_type - string
Model Relationship (modified example)
// Post.php
public function tags()
{
return $this->morphToMany( Tag::class, 'taggable', 'taggables', 'taggable_id', 'tag_id');
}
// Video.php
public function tags()
{
return $this->morphToMany( Tag::class, 'taggable', 'taggables', 'taggable_id', 'tag_id');
}
// Tag.php
public function posts()
{
return $this->morphedByMany(Post::class, 'taggable', 'taggables', 'tag_id', 'taggable_id');
}
public function videos()
{
return $this->morphedByMany(Video::class, 'taggable', 'taggables', 'tag_id', 'taggable_id');
}
In my project I need to use the videos table id type as string. According to this, being able to store the relation "videos<->tags" the tabbables table's taggable_id must be a string as well, otherwise I can't store the relation.
As long as NO "video<->tag" relation exist it the table everything works fine but as soon as I add even one single "video<->tag" relation the problem starts.
I can use all available methods on the "video<->tags" relation without any problem. $video->tags()->attach([1,2]) or $video->tags()->sync() or $video->tags()->detach() are all working.
But the post<->tag relation's methods have problems. Altough I can attach relations like $post->tags()->attach([1,2]) or call like $post->tags, I can't use $post->tags()->sync() or $post->tags()->detach() methods. When I try, I get this error below:
Illuminate/Database/QueryException with message 'SQLSTATE[22007]: Invalid datetime format:
1292 Truncated incorrect DOUBLE value: 'here_string_id_of_video' (SQL: delete from
`taggables` where `taggable_id` = 300 and `taggable_type` = App/Models/Video)'
This is a uncommon and tricky situation. I know that this is logical because the query expects the serched record type to be ingeter. But I need a way to overcome this problem. Any recommendations and views would be appreciated.
UPDATE
Those are some solutions that could come to mind.
I could use string type for the other tables as well. Which does not sound plausible. This would need a lot of work.
I could process the intermediate table manually with a model.
App\Models\Taggable::where('taggable_id', '300')
->where('taggable_type', 'App\Models\Video')->delete()
I could (as #GauravGupta suggested) create an extra id field (external_id) that is string type and keep the native integer id intact.

Laravel Eloquent Model Dynamic Stored Properties from and to a single serialized field

Using Eloquent L5.1
I'd like to not have to define a set of properties for a model. Instead having everything stored within the database as a serialized column.
In other words any property that is set to this model should before save be removed from the object and added to an array to be serialized and then saved in db to a "data" column.
In turn after retrieving the object from db the model should be hydrated with the de-serialized parameters from the data column.
I could override a good number of Illuminate\Database\Eloquent\Model methods to accomplish this and I'm willing to do so, was curious if anyone had an example of this.
An example of this might be for configuration objects that have virtually unlimited unknown values that have multiple itterations for different objects or for different users.
Put these accessors and mutators in your Model:
class YourModel extends Model
{
public function getDataAttribute($data)
{
return collect(json_decode($data,true));
}
public function setDataAttribute($data)
{
$data = (is_array($data) || is_object($data)) ? json_encode($data) : $data;
return $this->attributes['data'] = $data;
}
}
Now when you can pass data as json string, array or object
YourModel::create(['data'=>'{"working":"ok"}']);
YourModel::create(['data'=>['working'=>'ok']]);
It will work in all three cases.

Laravel - Using different field names in the database (userid in a table and created_by in other)

I am trying to use a table for my Users and separate table for users' Projects in my database. However I want the names of the fields to be different for user id. What I want to take the id from the 'Users' table; and while saving the created project to the database, use that (user) id as created_by_id in Projects table.
public function store(CreateProjectRequest $request)
{
$project = new Project($request->all());
Auth::user()->projects()->save($project);
// Project::create($request->all());
return redirect('pages/home');
}
Also in Users.php, I added:
public function projects()
{
return $this->hasMany('App\Project');
}
The commented field is working on its own. However, I guess my problem arises because when I comment that line again, and add the other two lines ($project... and Auth::user... bits), I guess it is assuming I have a field in the Projects table named id.
I thought I would work around this problem with changing the primary key but I couldn't find how to take the Auth::user()->id; and make it write that value in created_by_id in a secure way. This is what I found though:
class Project extends Eloquent {
protected $primaryKey = 'created_by_id';
}
Edit: I don't think changing the primary key is my solution.
You can pass a second and third parameter to hasMany() method to specify the keys to use. Documentation
public function projects()
{
return $this->hasMany('App\Article','userid','created_by');
}

Yii2: Eagerly selecting calculated column and loading value into model-property

I thought I know every aspect of Yii2 in the meantime, but this one gives me headaches.
Situation
Two tables: Client and Billings. The Client-Table holds a regular list of clients. The Billing-table has several entries for each client (1:n).
Problem
I want to fetch a calculated DB-Field together with the row itself and access it via a virtual property of the model.
Key is that it gets calculated and selected together with the row itself. I know I can achieve something similliar with a regular virtual getter calculating the amount...but this is not at the same time as the select itself.
My Plan
In the query-object of the client-model i tried to add an an additional select (addSelect-Method) and give the field an alias. Then I added the alias of this select with the attributes-method of the model. Somehow this didn't work.
My Question
Does someone of you know the right way to achieve this? As this is a very common problem, I can not imagine this beeing too hard. I just somehow can't find the solution.
Sample code:
echo $client->sumOfBillings should output the contents of the corresponding property within the client-model. The contents of this property should be filled when fetching the client-row itself and not at the moment the property gets called.
I actual found the answer myself. Here is how you do it:
Query object
The fetching of all the Yii2-Models is done via their corresponding Query-Object. This object is retrieved via the models find()-Method. If you override this method, you can return your own query-object for that class. In the example above my model looks like this:
class Client extends \yii\db\ActiveRecord
{
//...
public static function find()
{
return new ClientQuery(get_called_class());
}
//...
}
Now within the Query-Objects init()-Method we can add the corresponding additional selects:
public class ClientQuery extends \yii\db\ActiveQuery
{
public function init()
{
parent::init();
//prepare subquery for calculation
$sub = (new Query())
->select('SUM(billing_amount)')
->from('billing')
->where('billing.client_id = client.id');
$this->addSelect(['client.*', 'sumBillings'=>$sub]);
}
}
We are now done with the query-Object. What have we done now? When selecting a client the sum gets calculated and loaded as well. But how do we access it? This was the hard part where I struggeled. The solution lies within the ActiveRecord-class.
Possibilities to populate the model with calculated data
There are several possibilities to load this data into the model-class. To understand what options we have, we can check out the populateRecord($record, $row)-method of the BaseActiveRecord-class:
/**
* Populates an active record object using a row of data from the database/storage.
*
* This is an internal method meant to be called to create active record objects after
* fetching data from the database. It is mainly used by [[ActiveQuery]] to populate
* the query results into active records.
*
* When calling this method manually you should call [[afterFind()]] on the created
* record to trigger the [[EVENT_AFTER_FIND|afterFind Event]].
*
* #param BaseActiveRecord $record the record to be populated. In most cases this will be an instance
* created by [[instantiate()]] beforehand.
* #param array $row attribute values (name => value)
*/
public static function populateRecord($record, $row)
{
$columns = array_flip($record->attributes());
foreach ($row as $name => $value) {
if (isset($columns[$name])) {
$record->_attributes[$name] = $value;
} elseif ($record->canSetProperty($name)) {
$record->$name = $value;
}
}
$record->_oldAttributes = $record->_attributes;
}
As you can see, the method takes the raw-data ($row) and populates the model instance ($record). If the model has either a property or a setter-method with the same name as the calculated field, it will be populated with data.
Final code of Client-Model
This is my final code of the Client-model:
class Client extends \yii\db\ActiveRecord
{
private $_sumBillings;
//...
public static function find()
{
return new ClientQuery(get_called_class());
}
public function getSumBillings()
{
return $this->_sumBillings;
}
protected function setSumBillings($val)
{
$this->_sumBillings = $val;
}
//...
}
The populateRecord()-method will find the setter-method ($record->canSetProperty($name)) and call it to fill in the calculated value. As it is protected, it is otherwise readonly.
VoilĂ ...not that hard actually and definitely useful!

Whats the right way to store JSON in a database with Laravel?

I have JSON data I want to store in a database. Ideally, the data should be automatically decoded when I retreive from the database and automatically encoded when I store in the database.
How can I do this?
Use Accessors and Mutators, for an attribute called foobar add these two functions in your Eloquent model:
public function getFoobarAttribute($value){
return json_decode($value);
}
public function setFoobarAttribute($value){
$this->attributes['foobar'] = json_encode($value);
}

Resources