Check if all model attributes are filled - php

Hello I've a model that is additionalInfo for a user, so if the user fills this additional info it will get a reward, so I'll need to check if all values from this additional info is filled. My question is, do I need to check it per every value? I mean do I need to check it like this per attribute using $clientAdditionalInfo\['adress'\] then I will check the next $clientAdditionalInfo\['city'\] then $clientAdditionalInfo\['province'\] etc...
Or should I do something like this.
public function isCompleted() {
$user = auth()->user();
$clientAdditionalInfo = $user->client->additionalClientInfo->where('client_id', $user->client->id)->get()->first();
if($clientAdditionalInfo){
$attributes = $clientAdditionalInfo->getAttributes();
foreach($attributes as $attribute) {
// HERE I COULD CHECK IF EVERY ATTRIBUTE IS FILLED?
}
}
}
Tried iterating per attribute and maybe I should check per attribute if isset and then if all are set is that all additionalInfo is set and give the reward. But once all attributes are set how can I check that ALL attributes are set?
What I'm seeing if when I loopon the attributes, there's a last value which is null (after the updated_at) but on the database there's no more values after the database, it could be a thing of the foreach? There's only one row on the database and filled all the values, if I dump($key) & dump($attribute) on the foreach I get the following:
^ "id"
^ 1
^ "address"
^ "Calle test 123"
^ "city"
^ "Barcelona"
^ "province"
^ "Barcelona"
^ "postal_code"
^ "08010"
^ "web"
^ "https://www.test.com"
^ "phone"
^ "123456789"
^ "activity"
^ "Social"
^ "number_of_employees"
^ 150
^ "interest"
^ "Test"
^ "client_id"
^ 8
^ "created_at"
^ "2023-02-08 10:48:56"
^ "updated_at"
^ "2023-02-08 11:53:43"
^ null
I dont know where this null is coming from, it shouldn't...
Okay my bad, I was checking it badm I should check it from $request->all(). This way I'll be able to check just the values without the created_at & updated_at so I can be more specific and check it better.

The simplest approach is to have a loop like you suggested in the question:
$attributes = $clientAdditionalInfo->getAttributes();
foreach ($attributes as $key => $value) {
//Check whether the attribute is set properly
}
Yet, this is not always easy. Sometimes you have a default value for an attribute that's not null and which is set as a default. For example, you might have values such as 'NOTSET', 'UNINITIALIZED', 'INITIALIZED', 'FINALIZED'. In such cases you need to check whether the value is 'NOTSET'. Also, your attribute might default to 0 whereas proper values are strictly positive (prices, for example). So, you might have further functions/criterias to evaluate the different kinds of attributes you may have.
Also, it's quite possible that you have a null value somewhere, but it's perfectly fine and properly initialized. For example, a date of death is unknown, i.e. null for people who are currently alive.
Furthermore, it's quite possible that you have a composite attribute, like some items which is an array of items and each item has its own attributes, in which case you will need to loop for them, so it makes sense to implement a function for iterable collections such as arrays or StdClass objects.
Finally, you may have some object instances which need to be specially evaluated as attributes of additional info. For example, if health status is part of additional info, health status might be an object on its own right.
You can json_encode such objects and then json_decode into an array and handle it as an attribute array (nested or not) in your evaluation. Or, you could create an array of expected attributes for your class and loop that. The latter has the advantage of allowing some attributes to be uninitialized if you wish, but, the disadvantage is that you will need to keep an eye on that and possibly adjust it. You can do that semi-automatically as well, by tracking new attributes upon each build/deploy and assume the new attributes to be required.
But, returning to the simplest approach, it looks like this:
foreach ($attributes as $attribute) {
if ((!isset($yourObject->{$attribute}))) {
return false; //something was not initialized
}
}
return true; //we reached this point after looping everything and finding everything being initialized
The above was not tested, you may need to perform it in a slightly different way in your case, depending on how your objects and collections look alike, but the idea is to loop the attributes, see for each of them whether they are properly set, return false if not. Once everything was checked and found to be initialized properly, return true.

Use array_filter
if(!array_diff($attributes, array_filter($attributes))) {
echo 'All attributes are filled';
}
If no callback is supplied, all entries of array equal to FALSE deleted.

Related

if statement evaluates to true on NULL variable when using is_null()

So I've got a form with a modal, that modal has 3 rows with 2 text fields each, if the user (me in this prod case) fills out only 2 rows, and leave the other row empty, that 3rd value should be NULL.
In my script I've got:
if (!is_null($_POST['packageDependencies']['bundle'][2])) {
$packageDependency3 = $_POST['packageDependencies']['bundle'][2] . "|" . $_POST['packageDependencies']['version'][2] . "|" . $_POST['packageDependencies']['repository'][2];
$depends = "<key>dependencies</key>
<array>
<string>$packageDependency1</string>
<string>$packageDependency2</string>
<string>$packageDependency3</string>
</array>
";
}
So I'm checking if (!is_null($3rdRow)) { //Do this }, but the variable $_POST['packageDependencies']['bundle'][2] is in fact NULL, as I use var_dump($_POST['packageDependencies']['bundle'][2]); and I get NULL printed to the page, but the if statement is still processing as if it isn't NULL.
$depends gets fwrite() to an XML file, and when I open it, I only see || and but that shouldn't be there as the variable is NULL as I entered no values into those input fields.
Given my advice, a more complete solution would be:
if (!empty(trim($_POST['packageDependencies']['bundle'][2]))) {
NULL is a specific state of a variable that involves the way PHP associates the name of a variable with a variable location. You can think of it like a flag, that indicates a variable name exists, but there is no storage location associated with it. There are a number of situations that empty with trim will catch that will bypass a check against null.
Even though !empty() did the trick, I've decided to use == to be less ambiguous. The answers found here are quite intuitive.
EDIT: As per #gview, adding (!empty(trim($var))) is the best bet as if a user accidentally presses the space key after a tab, it will avoid any errors.

Null Value in Database causing undefined index using PHP and MSSQL

I have data that was imported from our mainframe and the last column in the table has null values. (varchar, allow nulls checked. obv.) The field name is all in caps (a result of the mainframe data dump... this is an important clue). When I try to retrieve and echo the data from that field, I get an "UNDEFINED INDEX" error if the field value is Null. If the field has data, I'm fine.
HOWEVER: if i rename the field to something with a lower case letter at the beginning, it works fine, nulls or not.
NOTE: if i put a number at the beginning of the field it doesn't work either.
Trying to find a way around this since I'm dealing with a LOT of tables that are going to get dumped and re-created on an almost daily basis from these mainframe extracts, id rather not have to change the field names. Any help would be GREATLY appreciated!
EDIT: I tried to use "isset" but you cannot check isset on a $XXX->fields('fieldname') line of code. Tried using if(!($XXX->fields('fieldname')) also doesn't work.
In the absence of your ability to use isset(), you can compare if it is exactly NULL with three equals signs (identical operator):
if ( $XXX->fields('fieldname') === NULL ) {
// NULL value, do something else...
} else {
// Not NULL, try something...
}
That doesn't solve your undefined index problem, however. Did you write the class that produces ->fields('fieldname')? If so, or even if not, you can modify the class function fields() to check isset() there and return NULL if not set, or the value if set.
Based on your code in the comments, you might try replacing:
return $this->fields[$this->bind[strtoupper($colname)]];
with:
return ( isset( $this->fields[$this->bind[strtoupper($colname)]] ) ? $this->fields[$this->bind[strtoupper($colname)]] : NULL );
This checks if $this->fields[ ... ] is set, and if so, returns it, and if not, returns null.
But, if that doesn't work, try replacing the same with:
return ( isset( $this->bind[strtoupper($colname)] ) ? $this->fields[$this->bind[strtoupper($colname)]] : NULL );
This checks if $this->bind[ ... ] is set, and if so, returns it, and if not, returns null.

Assign array value to a field

I am working with migration and I am migrating taxonomy terms that the document has been tagged with. The terms are in the document are separated by commas. so far I have managed to separate each term and place it into an array like so:
public function prepareRow($row) {
$terms = explode(",", $row->np_tax_terms);
foreach ($terms as $key => $value) {
$terms[$key] = trim($value);
}
var_dump($terms);
exit;
}
This gives me the following result when I dump it in the terminal:
array(2) {
[0]=>
string(7) "Smoking"
[1]=>
string(23) "Not Smoking"
}
Now I have two fields field_one and field_two and I want to place the value 0 of the array into field_one and value 1 into field_two
e.g
field_one=[0]$terms;
I know this isn't correct and I'm not sure how to do this part. Any suggestions on how to do this please?
If you are only looking to store the string value of the taxonomy term into a different field of a node, then the following code should do the trick:
$node->field_one['und'][0]['value'] = $terms[0];
$node->field_two['und'][0]['value'] = $terms[1];
node_save($node);
Note you will need to load the node first, if you need help with that, comment here and will update my answer.
You are asking specifically about ArrayList and HashMap, but I think to fully understand what is going on you have to understand the Collections framework. So an ArrayList implements the List interface and a HashMap implements the Map interface.
List:
An ordered collection (also known as a sequence). The user of this interface has precise control over where in the list each element is inserted. The user can access elements by their integer index (position in the list), and search for elements in the list.
Map:
An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value.
So as other answers have discussed, the list interface (ArrayList) is an ordered collection of objects that you access using an index, much like an array (well in the case of ArrayList, as the name suggests, it is just an array in the background, but a lot of the details of dealing with the array are handled for you). You would use an ArrayList when you want to keep things in sorted order (the order they are added, or indeed the position within the list that you specify when you add the object).
A Map on the other hand takes one object and uses that as a key (index) to another object (the value). So lets say you have objects which have unique IDs, and you know you are going to want to access these objects by ID at some point, the Map will make this very easy on you (and quicker/more efficient). The HashMap implementation uses the hash value of the key object to locate where it is stored, so there is no guarentee of the order of the values anymore.
You might like to try:
list($field_one, $field_two) = prepareRow($row);
The list function maps entries in an array (in order) to the variables passed by reference.
This is a little fragile, but should work so long as you know you'll have at least two items in your prepareRow result.

null does not mean it's not set does it? - PHP objects

I have a php object that has a key=>value with something like [ipAddress] = 'NULL'
and if I do:
if(isset($object->ipAddress)){
echo "I am set!!!";
}
It never echoes. because apparently it's not "Set." I was under them impression that it is set, because oft he word NULL.
Is there a away to get around this to say, you are set? with out actually giving it a value? I ask because I attempted to write a function like this: (Don't mind the debugging, its the debugging that lead me to this question)
private function checkForColumnInModelObject($modelObject, $column, $custom_name){
$relationship = array();
foreach($modelObject as $model){
if(isset($model->$column)){
$value_returned = $model->$column;
var_dump($column);
var_dump($custom_name);
var_dump($value_returned);
//$relationship[$custom_name] = $value_returned;
}
}
//return $this->toObj($relationship);
}
So what I am trying to do here is check for a column in a model object. Now you might be given an array of columns, which we walk through in a function that calls this one, and an array of different model objects. were trying to see if the model object has that column.
So for example:
Does equipmentModel have ipAddress Column? yes? fetch me the value.
and the way we do this is by saying "is the column on this model set". The problem is, we might have columns with NULL value ... hypothetically their set, their value is just null, but PHP's isset() is all like NO, you are not set.
Any ideas on how I could write this to keep the same logic, BUT allow values of null to pass through assuming that model has that particular column?
If you want to know if an object property exists, regardless of its value, you can use property_exists.
if (property_exists($model, $column) {
...
}
isset returns true whenever you do an assignment to some variable. When you do $somevar=NULL; (In this case it is an assignment), if(isset($somevar) { echo "Inside"; } , The "Inside" will never print. Since NULL is never considered a value.

PHP Arrays, ordered or not?

I have an Array of product types in PHP, it looks pretty much like this:
$types = [
0 => "cars",
1 => "motorbikes",
2 => "boats",
3 => "airplanes"
];
So that when then user wants to get or save it, I can use the ID of the category to insert or get it from the database, like this:
select * from items where type = 0;
now, My doubt is the following: if I am using integer index keys, would it not be the same to use the following?
$types = ["cars", "motorbikes", "etc."];
Since PHP will give an integer auto-ordering.
Which one would you consider to be best practice in this case? The advantage of the first example seems to only be the fact that I can assign different keys, like for private categories or such, but I don't know really.
It is also important to consider that the values will need to be translated so, should I consider even just using IDs? like
$types = ["t1", "t2", "etc."];
and then insert the translation somewhere else?
There are 2 possible options.
Your current option 1 with manually set indexes.
A way better one - a table in the DB, holding these categories, which allow editing categories without losing the association between keys and names.
Your current option 2 is not an option at all - it will break the order the same moment you insert or delete a category
Here you set the index:
$types = [
3 => "airplanes"
index ^ ^ value
So, if you delete cars from the list, the index remain associated with it's value:
$types = [
1 => "motorbikes",
2 => "boats",
3 => "airplanes"
];
While if you don't set indexes manually
$types = ["motorbikes", "boats", "airplanes"];
airplanes will lose it's association, and become boats. It's not ht magic we expect from the web application
It all depends on the project. If I'm working with an array of items from the database I like the key to be the id from the database so it's available should I need it. If there's no need for the ids then there is no need to define a key. It will start at 0 anyways.
I think your first approach is a good one. You could even do it as default translation:
$types["en"] = []
Of course if you have a default language variable, you can use it from the start, and it will be much easier in the future to translate it further and expand
The arrays will be seen as the same so you can order it and take key as ID but it's not the best practice, all depends on how you design your relationship between arrays, php and database.
I might be missing your question but the array in PHP is ordered hash map basically. So ["cars", "motorcycles", "etc."] is guaranteed to preserver ordering (and have keys 0, 1, 2). But you might instead consider do the following
class AutoTypes {
const TYPE_CAR = 0;
const TYPE_MOTORCYCLE = 1;
const TYPE_BOAT = 2;
public static function getLabels() {
return array(self::TYPE_CAR => 'Car', self::TYPE_MOTORCYCLE => 'Motorcycle', self::TYPE_BOAT => 'Boat');
}
}
This way you can refer to the auto type by AutoTypes::CONSTANT. Because if you want to remove motorcycle at some point, not using clear indexes in the array, removing an item will brake your logic.
In my opinion, in this circumstance it's better to use
$types = ["cars", "motorbikes", "etc."];
As you say, PHP automatically assigns integer indexes starting from 0; so there's no need to specify the index that it would be assigned anyway.
It's up to you however, if you feel that it isn't clear enough just to declare an array without specifying the indexes manually then that's up to you. But personally I feel that it's obvious to any competent programmer and so therefore it's a waste of time and hard disk space to manually specify those indexes.

Categories