Laravel convert database integer to string - php

I am using Laravel 5.5 & have Items table with more than 50 columns set as Tinynt to store values.
Item::where('id',$id)->first();
Now in my view I want to replace all integer values to corresponding String like
if($item->column1 == 1) { $value = 'String1'); }
if($item->column1 == 2) { $valuee = 'String2'); }
& so on. I know I can use Laravel Mutator but I have more than 50 columns & settings Mutator will not solve my issue. My problem is some related to this post but problem is number of columns.
Any solution please ?

I think 50 is the best way, but you can redefine __get() magic method:
//your Item model class
protected $castMutators = [
//column1 => ['1' => 'string1', 2 => 'string2'],
//column2 => ['1' => 'string1', 2 => 'string2'],
//...
//column50 => ['1' => 'string1', 2 => 'string2'],
];
public function __get($name)
{
if (in_array($name, $this->castMutators)) {
$this->{$name} = $this->castMutators[$name][$this->name]
}
parent::__get($name);
}

You can override the getAttributeValue() or setAttributeValue() function on the Eloquent model like below. Then you can use the same accessor or mutator for multiple attributes.
protected function getAttributeValue($key)
{
$value = parent::getAttributeValue($key);
//if the value has already been mutated, don't modify, else if
//the key is in the array of specified attributes, mutate and return it
if($value === $this->getAttributeFromArray($key) && in_array($key, $this->attributes_to_mutate) ) {
$value = $this->myCustomMutator($value);
}
return $value;
}
Same goes for setAttributeValue($key, $value)

save array to config/your_config.php
<?php
return [
'columns' => [
1 => 'string_1',
2 => 'string_2',
],
];
usage:
config('your_config.columns')[1] // string_1
config('your_config.columns')[2] // string_2

Related

Filter laravel collection in sub collection

My collection is like this.
Collection {
0 => Name_Model {
"id" => 44
"name" => "The name of "
"list_angg" => Collection {
0 => Name_Model_sub {
"code" => "02"
"nameofcode" => "The name of 02"
}
1 => Name_Model_sub {
"code" => "01"
"nameofcode" => "The name of 01"
}
}
}
1 => Name_Model {
"id" => 45
"name" => "The name of thus"
"list_angg" => Collection {
0 => Name_Model_sub {
"code" => "03"
"nameofcode" => "The name of 3"
}
}
}
}
I want to filter that model by value of list_angg->code. So I try like this. Filter and foreach that list_angg->code
$jurnals = $filterCollection->filter(function($value, $key) use ($kode_fakultas){
foreach ($value->list_angg as $lists) {
$filtered = $lists->where('code', $kode_fakultas);
return $filtered;
}
return $filtered;
});
dd($jurnals);
I try use method reject() and map().
But filter didn't work as well. Is I miss something?
Hope I understood the question correctly.
To filter all elements which list_angg->code has the given value you can use a combination of filter() and contains().
$filterCollection->filter(function ($value) use ($code) {
return $value->list_angg->contains('code', $code);
});
filter() returns all values in a collection which return a truthy value.
contains() returns true or false if a collection contains a value matching the condition provided, which can be a closure, a value or a key and value.
Keep in mind contains() uses "loose" comparison, so if you need a strict match you can use containsStrict.
Your code is not filtering correctly because in the filter closure you are always returning the model instance, which evaluates to true or false based on the first element and therefore it is considered as a pass or fail based on that.
References:
https://laravel.com/docs/8.x/collections#method-contains
https://laravel.com/docs/8.x/collections#method-filter
https://laravel.com/docs/8.x/collections#method-containsstrict
you can do this by first restructuring the collection according to your requirements. For example:
public function formatCollection($collection)
{
$results = [];
foreach ($collection as $item)
{
$results[] = [
'foe' => $item['bar'],
'baz' => $item['foo']
];
}
return collect($results);
}
This will return the required json format and after that you can apply your filters to it. For Example:
$result = formatCollection($collection);
This will return the collection on which you can apply
$result->filter(function(value){
return (value === 'foo');
}
This will return the required information or models you require in your collection.

PHP Access a Nested Object Property Using Variable

I am using PHP7.
I have an Object I am trying to parse:
$RECORD = {
'name' => 'Stephen Brad Taylor',
'address' => '432 Cranberry Hills, Pittsburg',
'phone' => '708 865 456',
'Account' => (Object Vendor/Entity/User) {
'email' => 'INeedThisEmail#pleaseHelp.com' // I want to access this property.
'id' => 34,
'accessible' => ['email', 'id]
}
}
I have an array which I am using to select certain fields from RECORD:
$fieldnames = [
'name',
'address',
'phone',
'Account["email"]'
];
I am trying to parse the fieldnames from RECORD as follows:
$data[]
foreach($fieldnames as $k => $fieldname) {
$data[k] = $RECORD->$fieldname
}
The method above works for the first-level attributes: name, address, and phone. However, email returns null.
I have tried the following below and none have worked:
$data[k] = RECORD->${$fieldname}
$propertyName = '$RECORD->$fieldname'
$data[k] = ${$propertyName}
Does anyone know a way to access an object's properties using a string from an object reference?
Much gratitude <3
You can't use Account["email"] directly as a property accessor, it won't be split up to find the nested property. You need to parse it yourself.
foreach($fieldnames as $k => $fieldname) {
if (preg_match('/^(.*)\["(.*)"\]$/', $fieldname, $match) {
$data[$k] = $RECORD->{$match[1]}->{$match[2]};
} else {
$data[$k] = $RECORD->$fieldname;
}
}
Also, you need $ in $k.
This code only works for 1 level deep. If you need to deal with arbitrary levels, you'll have to write a recursive procedure. See How to access and manipulate multi-dimensional array by key names / path? for examples of how to code this.
I use anonymous functions for such cases. (PHP 7.4)
$index = fn($item) => $item->dotaItem->prop_def_index;
if (get_class($collection) === Collection::class) {
$index = fn($item) => $item->prop_def_index;
}

Check if value exists within an array of objects

I am working on an API which receives a PHP object of $POST data. I am trying to check wether the 'smsPhoneNumber' inside customFields exists but not sure how to do this.
I am currently able to check for 'email' using:
if ( property_exists( $data, 'email' ) ) {
return true;
}
Question: How to check if 'smsPhoneNumber' exists?
--
var_dump:
object(stdClass)[1515]
public 'email' => string 'email#email.com'
public 'customFields' =>
array (size=2)
0 =>
object(stdClass)[1512]
public 'name' => string 'Firstname'
public 'value' => string 'james'
1 =>
object(stdClass)[1514]
public 'name' => string 'smsPhoneNumber'
public 'value' => string '077'
You could use an array_filter to get the custom field you want.
$phoneFields = array_filter($data->customFields, function($field) {
return $field->name === 'smsPhoneNumber';
});
This will only return objects in the array that have a name property equal to smsPhoneNumber.
if (!count($phoneFields)) {
// Phone not found
}
// or
if ($phone = current($phoneFields)) {
echo "The first phone number found is " . $phone->value;
}
The drawback of using array_filter() to search for the subarray values is:
array_filter() will not stop once it finds a match; it will keep iterating even after a match is found until it reaches the end of the array.
You should use a technique that allows an early break/return.
I recommend a simple foreach() with a break.
$foundIndex = null;
foreach ($data->customFields as $index => $customFields) {
if ($customFields->name === 'smsPhoneNumber') {
$foundIndex = $index;
// or $wasFound = true;
// or $smsNumber = $customFields->value;
break;
}
}
This will prove to be very efficient and easy to read/maintain.

Laravel 5.6 - get changed values after updateOrCreate

I have used laravel 5.6 and used the updateOrCreate model to add or update some data.
But I need to get all the values which changed
$q=Userssub::updateOrCreate(
['userid' => $uid ],
['model' => $model]
);
and the result shows like in this image
How can I get the changes array?
I tried to get it with
$u->changes
and
$u->changes->toarray()
but both return null.
What can I do to get the changed values?
Eloquent models have two protected arrays, $original and $changes, which contain the attributes as they were when fetched from storage and the attrbirutes which have been modified, respectively.
So you can use getOriginal() and getChanges() and compare the differences.
$model = Model::createOrUpdate([...]);
// wasRecentlyCreated is a boolean indicating if the model was inserted during the current request lifecycle.
if (!$model->wasRecentlyCreated) {
$changes = $model->getChanges();
}
This creates an array which will contain the original attribute value and what it was changed to:
if (!$model->wasRecentlyCreated) {
$original = $model->getOriginal();
$changes = [];
foreach ($model->getChanges() as $key => $value) {
$changes[$key] = [
'original' => $original[$key],
'changes' => $value,
];
}
}
e.g.
(
[first_name] => [
[original] => Kevinn
[changes] => Kevin
]
[website] => [
[original] => google.com
[changes] => google.ca
]
)

Include class name when using Doctrine 2 array hydration

In Doctrine 2 is there a way to get the array hydration mode to include the class name of the relevant entity in the output, so instead of:
array(
'id' => 1,
'name' => 'test',
// ...
);
You get:
array(
'__class' => 'MyProject\MyClass',
'id' => 1,
'name' => 'test',
// ...
);
I know the Doctrine\ORM\Internal\Hydration\ArrayHydrator class has access to the relevant information, but I'm trying to work out if this can be done without re-implementing the entire ArrayHydrator?
So creating a custom hydrator that extends ArrayHydrator and overriding the gatherRowData method with this is one potential solution:
protected function gatherRowData(array $data, array &$id, array &$nonemptyComponents)
{
$rowData = parent::gatherRowData($data, $id, $nonemptyComponents);
foreach ($rowData['data'] as $dqlAlias => $data) {
$class = $this->_rsm->aliasMap[$dqlAlias];
$meta = $this->getClassMetadata($class);
if ($meta->discriminatorMap) {
$class = $meta->discriminatorMap[$data[$meta->discriminatorColumn['name']]];
}
$rowData['data'][$dqlAlias]['__CLASS__'] = $class;
}
return $rowData;
}
Be interested to know if there's a better way?

Categories