How to build multi array in Transformer Laravel? - php

I have the following code:
public function transform($obj)
{
return [
'id' => (int) $obj->id,
'name' => $obj->name,
"prototype" => $obj->_prototypes()->get()
];
}
Where $obj->_prototypes()->get() is collection with fields (id, name).
How to format new array like as:
'name' => 'name' => $obj->name,
"prototype" => [
["id": 1, "name" : "ok"],
["id": 2, "name" : "ok 2"],
]
So, I need to iterate $obj->_prototypes()->get() inside transformer object.
So, I have nested objects(relations). And now I need to use loop, that to take nested object and combine them to one output object again.

you could use a for each loop, and in the for each loop use array_push or array_merge to merge the current iteration of the loop into a new array.
array_push docs = http://php.net/manual/en/function.array-push.php
array_merge docs = http://php.net/manual/en/function.array-merge.php

Definitely take a look at fractal's transformers. There are really nice features, including yours: http://fractal.thephpleague.com/transformers/
class MyTransformer extends TransformerAbstract
{
public $defaultIncludes = ['prototype'];
public function transform($obj)
{
return [
'id' => (int) $obj->id,
'name' => $obj->name
]
}
public function includePrototype($obj)
{
return $this->collection($obj->_prototypes()->get(), new PrototypeTransformer);
}
}

Related

Get value of dynamic sub-array, in multidimensional array

Not sure if my question is clear, but here's what I'm trying to achieve. Let’s say I have a multidimensional array like so:
$arr['client1']**['dog']['Jack']**
$arr['client2']['cat']['Stacy']
How can I get the second portion of the array (between **), knowing it can be anything. For client 3, it could be a crocodile. For Client 4, it could be a car.
So I'm looking to "build" the structure of the array, dynamically. Something like so:
$arr['client1']{partBetweenThe**InTheExemple}
{partBetweenThe**InTheExemple} would be constructed "on the fly" (hence, the dynamically).
EDIT: Hopefully some clarifications...
The array changes every time. Basically, I'm building an addon to poll any API on the web. The data structure I'm getting can be anything. So what I need to do is build the key combination "on the fly", with variables.
In the exemple above, my variable would be something like $query = ['dog']['Jack'] and to get the value, I would poll it like so (from a logistic perspective, I know this doesn't work):
$arr['client1'][$query] or $arr['client1']$query or $arr['client1']{$query}
You can define the query as an array with each level as an element. Then we can iterate through that and check if we find a matching key in the response:
function findInArray(array $query, array $data)
{
foreach ($query as $key) {
if (!array_key_exists($key, $data)) {
// The key was not found, abort and return null
return null;
}
// Since the key was found, move to next level
$data =& $data[$key];
}
return $data;
}
// Example response
$response = [
'client1' => [
'dog' => [
'Jack' => 'Some value',
],
]
];
// Define the query as an array
$query = ['dog', 'Jack'];
$result = findInArray($query, $response['client1']);
Demo: https://3v4l.org/WjXTn
Edit:
So since the array's structure can't be changed this will return the client if the structure remains ['client']['animal']['name'].
$clients = [
'client1' => [
'dog' => [
'Jack' => []
]
],
'client2' => [
'cat' => [
'Stacy' => []
]
]
];
$animal = 'dog';
$name = 'Jack';
foreach ($clients as $client => $options) {
if (
array_key_exists($animal, $options) &&
array_key_exists($name, $options[$animal])
) {
echo $client;
break;
}
}

Difference between $object->attribute and $object['attribute'] in Laravel

I'm developing with DataTables in Laravel and trying to make an object manually using collect() to create a collection. When I push the collection into the DataTable, there is something wrong, and I can't call my object with this $object->attribute.
After I get the error with that, I already tried to call an attribute with $object['attribute'], and it works well.
Can someone give me insight about the differences and how I can convert $object['attribute'] into $object->attribute?
This is my query to create object
$result = collect();
$item = collect([
'row' => ($key+1),
'item_id' => $value->uid,
'item' => $value->nama_item,
'sub_kategori' => $value->sub_jenis_item->sub_jenis_item,
'kategori' => $value->jenis_item->jenis_item,
'gudang_id' => $id_gudang
]);
$result->push($item);
Accessing $object['attribute'] means $object is an array and accessing $object->attribute means $object is an object.
To convert array to object:
$object = (object) $object;
Additionally, to convert object to array:
$object = (array) $object;
DataTables calls internally toArray() on the collection items when you build the table. This happens during transformation of the data. It will also flatten nested objects (e.g. loaded Eloquent relations in case of an EloquentDataTable) into an array with depth 1 (per row of the table).
You can try the following way,
$result = collect();
$item = collect([
'row' => ($key+1),
'item_id' => $value->uid,
'item' => $value->nama_item,
'sub_kategori' => $value->sub_jenis_item->sub_jenis_item,
'kategori' => $value->jenis_item->jenis_item,
'gudang_id' => $id_gudang
]
);
$result->push($item);
$resultObj = json_decode($result);
foreach($resultObj as $obj){
echo $obj->row;
}

(Laravel 5.3) How to add new key and value to existing sub array in existing Collection?

I am using Laravel 5.3.
existing Collection $a is
$a = collect(
[
0 =>[
'firstName' => 'John',
'lastName' => 'Doe'
],
1 =>[
'firstName' => 'Mary',
'lastName' => 'Jane'
]
]);
and desired result is as below:
$a = collect(
[
0 => [
'firstName' => 'John',
'lastName' => 'Doe',
'occupation' => 'engineer'
],
1 => [
'firstName' => 'Mary',
'lastName' => 'Jane',
'occupation' => 'accountant'
]
]);
I tried to test ->push(), ->put(), ->prepend() but no success. Please let me know the best way to do this.
You can use transform method which iterates over the collection and calls the given callback with each item in the collection. The items in the collection will be replaced by the values returned by the callback:
$a->transform(function ($item, $key) {
$item['occupation'] = 'some_value';
retrun $item;
});
Then check the value of $a:
dd($a);
Note that you have a collection of arrays, not a collection of collections. Hence, you can't use push(), put(), etc., in the sub-arrays.
The easiest way is probably just to treat it as an array:
$a[0]['occupation'] = 'engineer';
But you can also access at least the first element through the getter if you'd like:
$a->get(0)['occupation'] = 'engineer';
If you have an existing collection then you can get all the arrays from it using something like this:
$items = $existingCollection->all();
Now, you have an array of arrays in $items. So you can add key/value using something like this:
$item[0]['occupation'] = 'engineer';
$item[1]['occupation'] = 'accountant';
Now, you've modified the arrays so if you want to turn it back into a collection then you can do it easily using this:
$existingCollection = collect($items);
You could've also used map on the collection directly, for example:
$existingCollection->map(function ($person) {
$person['occupation'] = 'engineer';
return $person;
});
In this case, you can see that, all the person's occupation is going to be same but you can find out a way to make the difference but I can't give you more precise solution because I don't know much about your situation (You didn't share much).

PHP array loop and format

I am very new to PHP, learning fast but not fast enough! I am also learning Laravel 5.1.
I am trying to build a HTML select list array from an Eloquent query output, in the correct format for form builder (Form::select).
I have the following call to Eloquent to pull the data:
// Get list of States for address select
$states = State::all()->toArray();
It returns the following array:
array:8 [▼
0 => array:2 [▼
"id" => "1"
"state" => "ACT"
]
1 => array:2 [▼
"id" => "2"
"state" => "NSW"
]
...
];
I want to loop through it and generate the following output:
array = [
'' => 'State', <-- This is the default for the select list
'1' => 'ACT',
'2' => 'NSW',
...
];
I am using Laravel 5.1, so I am using the included array_add() function in my helper.
I call my function like this:
$states = create_select_list($states, 'State');
I next want to format the output so it is ready for the Form::select statement. I have tried the code below (as the final try from a few iterations!) but unsuccessfully.
function create_select_list($data, $default)
{
// Declare array and set up default select item
$container = ['' => $default];
// Loop through data entries and build select list array
foreach($data as list($entry, list($key, $value))) {
$container = array_add($container, $key, $value);
}
// Return the select list array
return $container;
}
All help or suggestions are appreciated!
This answer is not about loop fix. I think previous comment should help you.
Just another idea. You can try use array_map instead foreach for this case.
For example:
$states = ['' => 'State'];
array_map(function($item) use (&$states) {
$states[$item['id']] = $item['state'];
}, State::all()->toArray());
Loop like below:
foreach($data as $key => $keyArr ) {
$container = array_add($container, $keyArr['id'], $keyArr['state']);
}
You don't need to use list() in your foreach loop, instead try:
foreach($data as $key => $value) {
$container = array_add($container, $key, $value);
}
The PHP documentation gives a good overview of what list() actually does.

How use json in php with a 'complex' structure?

i want use json + php for my data. I read more document to do this, and the basic function are json_decode() and json_encode(). My problem is that, read more document and read different example of structure have created in me a lot of doubts.
I want create a structure like this begine from the basic to the container:
there is a Base, that have 2 property: id and value
there is a Operations that can have multiple Base
there is a Command that can have multiple Operations (and if possible a property callad name)
the structure in my mind is like this...
[ //The start of Commands
//Can make a property name here like "name":"puls1"
[ //Operation1
{ //Base1
"id":"22398",
"value":"255"
},
{ //Base2
"id":"22657",
"value":"80",
},
{ //Base3
"id":"7928",
"valore":"15"
}
],
[ //Operation2
{ //Base1
"id":"22398",
"value":"0"
},
{ //Base2
"id":"22657",
"value":"0",
},
{ //Base3
"id":"7928",
"valore":"0"
}
],
] //The close of Commands
But i have put the [ and { in the not correct order i think...
How can i make a json structure like this? And after set a command to insert a new Operation or remove Operation?
Thank's at all..
//Ok by answer of i made this code
class Base
{
var $i;
var $value;
function __construct($i,$v)
{
$this->id = $i;
$this->value = $v;
}
}
$a = new Base('1','11');
$b = new Base('2','10');
$c = new Base ('3','20');
$d = new Base ('4','30');
class Operation
{
var $name;
var $values = Array();
function __construct($a)
{
$this->name = $a;
}
public function addArray($a)
{
array_push($this->values,$a);
}
}
$oper1 = new Operation("op1");
$oper1->addArray($a);
$oper1->addArray($b);
$oper2= new Operation("op2");
$oper2->addArray($c);
$oper2->addArray($d);
$commands = Array($oper1,$oper2);
echo json_encode($tot);
Now the problem is how can i make the revert operation? Such a use of json_decode and incapsulate in its appropriate structure?
The json list type [] is equal to a array without keys in php.
The json dictionary type {}is equal to a keyed array in php.
What you want is something like this:
$json = array(
array(
array('id' => $num, 'value' => $val), // Base 1
array('id' => $num_1, 'value' => $val_1), // Base 3
array('id' => $num_2, 'value' => $val_2), // Base 2
),
array(...),
array(...),
);
If you're working with PHP I would construct the objects from native PHP Classes (json_encode works with php objects as well):
class Base {
var $id;
var $value;
}
Then it's just a matter of putting these objects in various arrays, which you can also abstract with methods like addToOperation($baseObj) and addToCommands($operationObj).
You're dealing with native data structures (Arrays), so you can use native methods to remove (array_pop) and add (array_push) data.
Something like this should work
// Build up your data as a mulitdimensional array
$data = array(
'operations' => array(
0 => array(
'bases' => array (
0 => array(
'id' => '22398',
'value' => 'whatever'
),
1 => array(
'id' => 'id goes here',
'value' => 'value goes here'
),
1 => array(
//data for operation 2
)
);
// Then use json_encode
$json = json_encode($data);
My syntax may not be perfect but that should give you the idea. To access it then you would use code like
$operations = json_decode($data);
foreach ($operations as $op) {
foreach ($op->bases as $base) {
//Logic goes here
}
}
Hope this helps.

Categories