Null values in FactoryMuffin define - php

I am using PhPUnit, FactoryMuffin and Faker for testing in Laravel, with a PostgreSQL db. In the previous version of FactoryMuffin (Zizaco\FactoryMuff) I could assign null values to columns both in the static factory array and when calling FactoryMuff::create.
However this no longer works - if I use the following define:
FactoryMuffin::define('MyModel', array(
'name' => 'word',
'empty' => null,
'another' => 'word'
));
when I call FactoryMuffin::create instead of passing NULL to the SQL INSERT statement it leaves the value blank, so I get:
INSERT INTO my_table ("name", "empty", "another") VALUES ('Ralph', , 'Someone');
which PGSQL doesn't allow. The same thing happens using
FactoryMuffin::create('MyModel', array('empty' => null));
Any ideas how to get round this, beyond instantiating the model and then assigning null to the field?

Since FactoryMuffin 2.1 (and 3.*) you can take advantage of the callback functionality, e.g.:
FactoryMuffin::define('MyModel', array(
'name' => 'word',
'empty' => null,
'another' => 'word'
))->setCallback(function ($object, $saved) {
$object->empty = null;
});
In FactoryMuffin 2.1 the callback is set as the third parameter of the define:
FactoryMuffin::define('MyModel', array(
'name' => 'word',
'empty' => null,
'another' => 'word'
), function ($object, $saved) {
$object->empty = null;
});

Related

How to insert an array of values into a particular column and fetch it

So, I want to insert an entire array of values into a particular column and I don't know exactly what to do. Everything I have tried gives me the "Array to string conversion" error.
Here is my controller code:
public function processInternationaTransfer(Request $request)
{
$international_info = Validator::make($request->all(),
[
'beneficiary_name' => 'required',
'beneficiary_acc_num' => 'required|numeric',
'beneficiary_bank' => 'required',
'beneficiary_swiftcode' => 'required',
'routing_transit_no' => 'required|numeric',
'currency' => 'required',
'amount' => 'required|numeric',
'note' => 'required',
]
);
if($international_info->fails())
{
return response()->json(['errors'=>$international_info->errors()->all()]);
}
$info = $international_info->validated();
$balance = $info['currency'].'_balance';
if(user_details()->$balance < InternationalAmount($info['amount']))
{
return response()->json(['insufficient_amount'=>'Insufficient Amount']);
}
else
{
TransactionLog::create([
'username' => user()->username,
'type' => 'Exchange',
'cred_deb' => 'Debit',
'time'=> Carbon::now('Africa/Lagos')->format('l, d F, Y g:i A'),
'status' => 2,
'amount'=>InternationalAmount($info['amount']),
'currency'=>$info['currency'],
'reason' => $info['note'],
'inter_details' => $info,
'transaction_id' => rand(100000000, 999999999),
]);
return response()->json(['success'=>'Transaction Processed, Awaiting Confirmation']);
}
}
How do I insert that array of values into the inter_details column?
I tried inserting it as it is above, and it gives me "array to string conversion" error.
I want to be able to fetch it after inserting it.
First of all you need to make sure that the inter_details can accept many characters the best way to do that is to use the json() in migrations
$table->json('inter_details'); //it will create a longText column in database so that it can accept many characters.
then add a casts to the TransactionLogs Model
protected $casts = [
'inter_details' => 'array',
]
in this way you can access the inter_details as an array when you fetch it from the database you don't need to use json_encode() and json_decode(). if you want to casts it in other types there are many more from the documentation
Eloquent: Mutators & Casting - Attribute Casting
To insert an array of values into a particular column, you need to use the DB facade's insert method. The insert method takes an array of values as its first argument and the table name as its second argument.
For example, if you want to insert an array of values into the inter_details column, you can do the following:
$inter_details = [
'beneficiary_name' => 'John Doe',
'beneficiary_acc_num' => '12345678',
'beneficiary_bank' => 'Bank of America',
'beneficiary_swiftcode' => 'ABC123',
'routing_transit_no' => '123456789',
'currency' => 'USD',
'amount' => '1000',
'note' => 'This is a test transaction',
];
DB::table('transaction_logs')->insert([
'inter_details' => json_encode($inter_details),
]);
The json_encode() function is used to convert the array into a JSON string, which can then be stored in the database.
To fetch the array of values from the database, you can use the DB facade's select method. For example:
$inter_details = DB::table('transaction_logs')->select('inter_details')->get();
$inter_details = json_decode($inter_details, true);
The json_decode() function is used to convert the JSON string back into an array. The second argument of the function is set to true, which tells the function to return an associative array instead of an object.
Now you have the array of values stored in the $inter_details variable, which you can use as you wish.

Output null string from API

So I'm using the following array to pass in $record params , but I'm getting errors when a particular return from the API is null.
Here is the array:
$office->load([
'post_title' => $record->office,
'location_id' => $record->location_id,
'location' => $record->location,
'business_unit' => $record->business_unit,
'type_id' => $record->type_id,
'brand_id' => $record->brand_id,
]);
My $record->brand_id is being returned as null and it crashes my whole script, is there a way that I can output null as a string and wrap the $record->brand_id in something?
Update:
I ended up configuring the needed brand_id as $record->brand_id ?? $default_value which worked great!
If you know which values may be null and have no impact on API output you can try operators checking null values, like null coalescing operator (??).
$default_value = 'default';
$office->load([
'post_title' => $record->office,
'location_id' => $record->location_id,
'location' => $record->location,
'business_unit' => $record->business_unit,
'type_id' => $record->type_id,
'brand_id' => $record->brand_id ?? $default,
]);

Firebase PHP Adding Map to Array

I'm trying to use the Firebase PHP API to update/append a document field's array with a map
I have the following code in Python that works fine
ref = db.collection(u'jobs').document(jobId)
ref.update({
u'messages': firestore.ArrayUnion([{
u'category': u'0',
u'message': u'TEST',
u'sender': u'TEAM',
}])
})
Though when I try to replicate it in PHP, it doesn't work. I tried a lot of different ways to view the errors, but all I get is 500 INTERNAL SERVER ERROR.
require 'vendor/autoload.php';
use Google\Cloud\Firestore\FirestoreClient;
use Google\Cloud\Firestore\FieldValue;
$firestore = new FirestoreClient([
'projectId' => 'XXX-XX',
'credentials' => 'key.json'
]);
$jobId = "XXXX";
$docRef = $firestore->collection('jobs')->document($jobId);
$docRef->update([
'messages' => FieldValue::arrayUnion([{
'category' : '0',
'message' : 'TEST',
'sender' : 'TEAM',
}])
]);
I looked up samples of Array Union in PHP, adding data with PHP. I've tried a lots of variations of : or => or arrayUnion([]) or arrayUnion({[]}) to no avail.
Any idea what is causing this?
Looks like there's a few things going wrong here.
First, PHP uses arrays for both maps and "normal" arrays. There is no object literal ({}) in PHP. Array values are specified using the => operator, not :.
Second, DocumentReference::update() accepts a list of values you wish to change, with the path and value. So an update call would look like this:
$docRef->update([
['path' => 'foo', 'value' => 'bar']
]);
You can use DocumentReference::set() for the behavior you desire. set() will create a document if it does not exist, where update() will raise an error if the document does not exist. set() will also replace all the existing fields in the document unless you specify merge behavior:
$docRef->set([
'foo' => 'bar'
], ['merge' => true]);
Therefore, your code can be re-written as either of the following:
$jobId = "XXXX";
$docRef = $firestore->collection('jobs')->document($jobId);
$docRef->set([
'messages' => FieldValue::arrayUnion([[
'category' => '0',
'message' => 'TEST',
'sender' => 'TEAM',
]])
], ['merge' => true]);
$jobId = "XXXX";
$docRef = $firestore->collection('jobs')->document($jobId);
$docRef->update([
[
'path' => 'messages', 'value' => FieldValue::arrayUnion([[
'category' => '0',
'message' => 'TEST',
'sender' => 'TEAM',
]])
]
]);
One final thing to note: arrayUnion will not append duplicate values. So if the value you provide (including all keys and values in the nested map) already exists, it will not be appended to the document.
If you haven't already, turn up error reporting in your development environment to receive information about why your code is failing. PHP will inform you about the parse errors your snippet included, and the Firestore client will give you errors which can often be quite useful.
From Firebase Documentation:
$cityRef = $db->collection('cities')->document('DC');
// Atomically add a new region to the "regions" array field.
$cityRef->update([
['path' => 'regions', 'value' => FieldValue::arrayUnion(['greater_virginia'])]
]);
I would assume you would like something like this:
$docRef = $firestore->collection('jobs')->document($jobId);
// Atomically add new values to the "messages" array field.
$docRef->update([
['path' => 'messages', 'value' => FieldValue::arrayUnion([[
'category' : '0',
'message' : 'TEST',
'sender' : 'TEAM',
]])]
]);

Dot syntax and nested html forms. Unable to fetch data during testing

I am new to the Laravel. I have not tried this in browser I am using tests for this.
I have test that looks like this:
public function testStoreRequestValid()
{
$data = [
'name' => 'New Item',
'parameter.count' => '3',
'parameter.0.parameter_id' => '4',
'parameter.0.value_id' => '',
'parameter.0.value' => 'text',
'parameter.1.parameter_id' => '1',
'parameter.1.value_id' => '2',
'parameter.1.value' => 'Yes',
'parameter.2.parameter_id' => '2',
'parameter.2.value_id' => '',
'parameter.2.value' => '10'
];
$response = $this->call('post', '/item', $data);
// ...
}
When I try to fetch data using:
$parameterCount = $request->input('parameter.count');
I get null value (if I use has method it gets false).
When I have tried to use square brackets I have got the results, but I want the API to be usable with JSON too without too much hastle in the JS.
How do I solve this in the most clean way?
Dot in Laravel has a special meaning so you can't really use arrays which have dots in their keys. You should declare your data as follows:
<?php
$data = [];
array_set($data,'name','New Item');
array_set($data,'parameter.count','3');
array_set($data,'parameter.0.parameter_id','4');
array_set($data,'parameter.0.value_id','');
array_set($data,'parameter.0.value','text');
array_set($data,'parameter.1.parameter_id','1');
array_set($data,'parameter.1.value_id','2');
array_set($data,'parameter.1.value','Yes');
array_set($data,'parameter.2.parameter_id','2');
array_set($data,'parameter.2.value_id','');
array_set($data,'parameter.2.value','10');

How do I create a CGridView with custom columns from a CArrayDataProvider?

I have an array of models that looks something like this. The models are extensions of the base Yii model class (BazClass), so that's a little bit of a custom solution, but I don't see why it shouldn't work.
$list = array
(
0 => FooClass#1
(
[BazClass:_attributes] => array
(
'FOO_ATTRIBUTE' => '4567'
'BAZ_ATTRIBUTE' => '1234'
'NAME' => 'FOO BAR'
)
[BazClass:_related] => array()
[_md] => null
[CModel:_errors] => array()
[CModel:_validators] => null
[CModel:_scenario] => ''
[CComponent:_e] => null
[CComponent:_m] => null
),
)
I made this a data provider by doing so:
$dataProvider = new CArrayDataProvider($list, array(
'pagination'=>array(
'pageSize'=>10,
),
));
$dataProvider->setData($list);
And try to render it in the view like so. Basically I'm just trying to show a list of the names, with the column named "Name".
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
'columns'=>array(
array(
'header' => 'Name',
'value' => $data->NAME,
),
),
));
The examples in the CGridView documentation make it look like that is possible, but the error I get is:
Either "name" or "value" must be specified for CDataColumn.
Well, I did specify a value, obviously, but it seems to be null. I also tried $data['NAME'] (because I somewhere read that the CArrayDataProvider doesn't return models), but it still evaluates to null.
I also checked that $dataProvider->getData() returns the same list as I passed it.
What gives?
you should place quotes around your value otherwise it gets interpreted in the wrong context
array( 'header' => 'Name', 'value' => '$data->NAME', ),

Categories