help me with save json to db. Table field type - text.
I have Model with cast array
class Salesteam extends Model
{
protected $casts = [
'team_members' => 'array'
];
}
I want get json like this {"index":"userId"} and store it to db.
Example:
{"1":"7","2":"14","3":"25","4":"11"}
I have Salesteam Model and 'team_members' column in db to saving all user id's belong to this team.
My code find team by id, get all 'team_members' attribute and add new user to this team. I want store all users in json format and incrementing index when add new user id.
Salesteam attributes:
"id" => 20
"salesteam" => "Admin"
"team_leader" => 0
"invoice_target" => 884.0
"invoice_forecast" => 235.0
"team_members" => "[1,66,71]"
"leads" => 0
"quotations" => 0
"opportunities" => 0
"notes" => ""
"user_id" => 1
"created_at" => "2017-09-22 09:13:33"
"updated_at" => "2017-09-22 13:10:25"
"deleted_at" => null
Code to add new user to team:
$salesTeam = $this->model->find($salesTeamId);
$teamMembers = $salesTeam->team_members;
$teamMembers[] = $userId;
$salesTeam->team_members = $teamMembers;
$salesTeam->save();
But it stores to db array and without index
"team_members" => "[1,34,56]"
From Laravel documentation - Array & JSON Casting "array will automatically be serialized back into JSON for storage"
Where i'm wrong?
To make a json string like this
{"1":"7","2":"14","3":"25","4":"11"}
In php, you must pass a key, when you're pushing elements to array. e.g.
$teamMembers = [];
$teamMembers['1'] = 7;
$teamMembers['2'] = 14;
...
If you don't make it an associative array, php will consider it as json array when converting to json string..
Tip: You may pass only one key and it will work too.
e.g.
$test = [1, 2, 3, 4, 5, 6];
$test['10'] = 56;
echo json_encode($test);
Output:
"{"0":1,"1":2,"2":3,"3":4,"4":5,"5":6,"10":56}"
PHP-Reference
Simply use
$teamMembers = json_encode($salesTeam->team_members);
That should do be all.
if you get this "[1,34,56]" just do json_decode($team_members)
and you will have this:
array:3 [▼
0 => 1
1 => 34
2 => 56
]
Simple Solution
$books = App\Book::all();
$user->books = $books->toJson();
$user->save(); //example: userid -> 2
$user = App\User::find(2);
$userBooks = json_decode($user->books, true); // to generate object again
Related
How do i get data based on the id in the array
array:60[
3 => array:3[
"id" => 4
"name" => james
"sex" => male
],
3 => array:3[
"id" => 5
"name" => mulan
"sex" => female
]
]
I use laravel, and I use code like the following, but what is filtered is index array not based on id
$response = Curl::to('127.0.0.2:8000/user/data')->get();
$data = json_decode($response, true);
$outputData = $data["data"];
dd($outputData[$request->id]);
You could put that array in a Collection and use the where method to return the item based on id:
$collection = collect($thatArray);
$item = $collection->where('id', 5);
You could also key the collection by the 'id', then you can use get:
$collection = collect($thatArray)->keyBy('id');
$item = $collection->get(5);
Laravel 6.x Docs - Collections - Available Methods - where
Laravel 6.x Docs - Collections - Available Methods - keyBy
Laravel 6.x Docs - Collections - Available Methods - get
How to put value on first element in laravel collection ? Something like that $collection->put('foo', 1) but adding value to the first element.
Collection {#376
#items: array:1 [
0 => array:9 [
"id" => 83
"status" => "offline"
"created_date" => "Oct 31, 2018"
// add foo => 1 here
]
]
}
I suspect there's a cleaner way to do this, but this is the best I could come up with at the moment. You could also use map or transform with a comparison run on the key value that gets sent to their closures, but that would end up cycling through all elements of the array despite you knowing the specific one you want to target.
$collection = collect([
[
'id' => 83,
'status' => 'offline',
'created_date' => 'Oct 31, 2018'
]
]);
$firstKey = $collection->keys()->first(); //This avoids the unreliable assumption that your index is necessarily numeric.
$firstElement = $collection->first();
$modifiedElement = array_merge($firstElement, ['foo1' => 1]);
$collection->put($firstKey, $modifiedElement);
use this
$data = Model::all();
$data[0]->foo = 'your data here';
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
]
)
I got the following array:
"task" : {
"author_id" : 150,
"created_at" : somedate,
"status_id" : 2,
"assignee_id" : 100,
"updated_at" : somedate_too
and I got 2 more associative arrays where I store names for IDs in the following way:
"100" => Mike,
"150" => Bob //etc..., the same for statuses
I need to check for the IDs in the first array and replace numbers with names for the corresponding arrays in the most effective way. I tried the following:
if(isset(task['status_id'])){$row = array_merge($row, [$status_ids[
task['status_id']]]);}else{$row = array_merge($row, '');}
if(isset(task['author_id'])){row = array_merge($row, [$users[// note the different array here
task['author_id']]]);}else{$row = array_merge($row, '');}
if(isset(task['assignee_id'])){$row = array_merge($row, [$users[
task['assignee_id']]]);}else{$row = array_merge($row, '');}
In my resulting array ($row) I cannot miss the index and replace it with another value. If there is no value in the first array, I need to insert an empty string to get the following, for example:
['in progress', '', 'Mike']
if there is no author_id in the first array. I believe there should be a better way to do it with foreach loop, but I cant find out how because for different fields I get the data from different arrays. I dont think a separate if clause for every field is the most suitable here.
Any help would be welcome. Thank You.
You could map your special keys to their array counterparts using references and use that mapping when populating $row, like this:
$users = [
"100" => "Mike",
"150" => "Bob",
];
$status_ids = [
1 => "Foo",
2 => "Bar",
];
// Define output format and array mapping
$mapping = [
"author_id" => &$users, // Mapped to $users array
"created_at" => null, // Not mapped, keep $task value
"status_id" => &$status_ids,
"assignee_id" => &$users,
"updated_at" => null,
];
$task = [
"author_id" => 150,
"created_at" => "Some date",
"status_id" => 2,
// "assignee_id" => 99999, // Oops, missing key/value => empty string in $row
"updated_at" => "Some other date",
];
foreach ($mapping as $key => $mappedArray) {
#$row[] = $mappedArray
? $mappedArray[$task[$key]] ?: ''
: $task[$key];
}
print_r($row);
Output:
Array
(
[0] => Bob
[1] => Some date
[2] => Bar
[3] =>
[4] => Some other date
)
It should work (I didn't try it, but it should give you the general idea):
<?php
$fields = array("author_id", "assignee_id", "status_id");
$aliases = array("users", "users", "status_ids");
foreach ($task as $key=>&$value) {
$alias = str_replace($fields, $aliases, ${$key});
if (is_array(${$alias}) {
$value = array_key_exists($value, ${$alias}) ? ${$alias}[$value] : "";
}
}
unset($value);
And then you can fill up your $row as you planned, directly from the $task array.
Why is this array count returning 1 instead of 2?
Shouldn't it return 2?
$join = [
'JOIN' => ['coins','users.id','user_id'],
'JOIN' => ['coins','users.id','user_id']
];
echo count($join);
You are creating an associative array, which means that each element is associated to one unique key. Therefore, in an array, each key can only appear once. A key appearing twice means that the value will be overwritten.
If you try to var_dump your array, it would have this output:
array(1) {
["JOIN"]=>
array(3) {
[0]=>
string(5) "coins"
[1]=>
string(8) "users.id"
[2]=>
string(7) "user_id"
}
}
As seen from this result, only one line exists.
If you need to have 'JOIN' in every element, maybe you want to change your array structure into this:
$join = [
['JOIN' => ['coins','users.id','user_id']],
['JOIN' => ['coins','users.id','user_id']]
];
This will carry the information 'JOIN' in every element. However, I cannot imagine why you would need such a thing.
Instead, maybe you want to have multiple elements under the 'JOIN key:
$join = [
'JOIN' => [
['coins','users.id','user_id'],
['coins','users.id','user_id']
]
];
As per your comments, maybe you eventually want to have a structure like this:
$join = [
'JOIN' => [
['coins','users.id','user_id'],
['coins','users.id','user_id'],
],
'INNER JOIN' => [
['coins','users.id','user_id'],
['coins','users.id','user_id'],
]
];
According to your comments, it might be more desirable if you do this through object-oriented programming instead:
class Join{
const JOIN = 0;
const INNER_JOIN = 1;
// we are using constants to prevent bugs caused by typos
public $type;
public $coins;
public $usersDotId; // I don't really know what you are trying to do here
public $userId;
}
Then you can use it like this:
$joins = [];
$join = new Join();
$join->type = Join::INNER_JOIN;
$join->coins = "some_value";
$join->usersDotId = "some_value";
$join->userId = "some_value";
$joins[] = $id;
$join = [
'JOIN' => ['coins','users.id','user_id'],
'JOIN' => ['coins','users.id','user_id']
];
echo count($join);
how may I modify this array to have 2 keys, without changing the key name?
In order to not need to change this key name, make JOIN an array of numeric values so structurally you want:
array:
----> [Join] :
\---> [0]
\---> coins
|---> users.id
|---> user.id
This can be achieved with this syntax (clarified for understanding):
$join = [
'JOIN' => [0] => ['coins','users.id','user_id'],
[1] => ['coins','users.id','user_id']
];
(simplified for ease):
$join = [
'JOIN' => ['coins','users.id','user_id'],
['coins','users.id','user_id']
];
gives you a $join array with a count of 1, which contains (the one) an array with a count of 2, each of those containing 3 elements.
Without addressing the more specific problem that appeared in the comments, and acknowledging that you've already accepted an answer that works for your purposes, here is a more theoretical explanation for why you can't have two of the same key. This may be not be useful for you, but hopefully it could help someone who does not intuitively grasp this concept.
Regardless of whether you assign your own string keys ($array = ['key' => 'value'];), assign your own integer keys ($array = [42 => 'the answer'];), or let PHP automatically assign integer keys ($array[] = 'something';), the keys must be unique.
According to the PHP manual for arrays:
An array in PHP is actually an ordered map. A map is a type that associates values to keys.
Most programming languages have something like this. This association of values to keys means that by definition, keys must be unique. If a language allowed you to create a "map" with multiple identical keys pointing to different values, looking up a value by key would be impossible (or at least would produce ambiguous results), so the map would be fairly useless.
PHP will let you write things like:
$example = [
'a' => 1,
'b' => 2,
'a' => 3,
];
var_dump($example);
without giving any errors, but the result of that will be:
array (size=2)
'a' => int 3
'b' => int 2
where 'a' => 3 has overwritten the previously defined value of the 'a' key. This allows the map to continue to work, so that $example['a'] will always yield the same value. If you actually could have
array (size=3)
'a' => int 1
'b' => int 2
'a' => int 3
Then what would be the result of $example['a']? Any defined behavior (first instance of 'a', etc.) would mean that some values of 'a' would be inaccessible.
Because you are using same array key to both the element
try this,
<?php
$join = [
'JOIN1' => ['coins','users.id','user_id'],
'JOIN2' => ['coins','users.id','user_id']
];
echo count($join);
?>
Or with same key try following
$join = [
['JOIN' => ['coins','users.id','user_id']],
['JOIN' => ['coins','users.id','user_id']]
];