Combine three "complex" PHP conditions in one perfect php snippet - php

I'm stuck in Drupal Panels / PHP Access plugins.
At least, now I found the three conditions to create my final snippet. the purpose of it is to return TRUE; if "condition1 is TRUE" OR "condition2 is TRUE" OR "condition3 is TRUE". I found a lot of similar questions, but the last condition force me to post here to find the right way to do this.
Condition 1:
// At least $view1->result has result.
$view1 = views_get_view('sp_onglet_videos');
$view1->set_display('views-tab-embed_1');
$output1 = $view1->preview();
if ($view1->result) {
return TRUE;
}
Condition 2 (same thing):
// At least $view2->result has result.
$view2 = views_get_view('sp_onglet_audio');
$view2->set_display('views-tab-default');
$output2 = $view2->preview();
if ($view2->result) {
return TRUE;
}
Condition 3 is more complex:
// Checks for content in the field field_txt_videos.
if (isset($contexts['argument_nid_1']->data-> field_txt_videos)) {
$field = $contexts['argument_nid_1']->data-> field_txt_videos;
if (is_null($field)) {
return FALSE;
}
if (is_array($field)) {
foreach ($field as $key => $val) {
if (is_array($val)) {
$field[$key] = array_filter($val);
}
}
$field = array_filter($field);
return count($field);
}
if (is_string($field) && trim($field) == '') {
return FALSE;
}
if ($field) {
return TRUE;
}
return FALSE;
}
I would like to have something clean (and functional) like this:
if ($view1->result && $view2->result && $field) {
return TRUE;
}
But it's to tricky for my php knowledge. Need a little help !

You want to save the result of the 3rd condition (into a variable) and use this result to run your final condition/query. But you can query the 3rd condition if it is a function.

It is better to properly space your code and use plenty of newlines.
However, PHP does have some pretty cool tricks to do assignment inside conditional statements.
if(($view1 = views_get_view('sp_onglet_videos')) AND $view1->set_display('views-tab-embed_1') AND ($output1 = $view1->preview()) AND $view1->result) return TRUE;
However, as you can see this code is a mess - don't do it unless your assignment is really small. Take this simple security check at the top of a PHP file:
<?php defined('BASE_PATH') OR die('Not Allowed');

Related

While loop on multi-dimensional array

So I have a function that currently has a foreach and it works amazing, but I'm being forced to change it to a while loop:
PLEASE NOTE: The developers at my company don't want to use the foreach and they think that a while loop would be more efficient, but I'm not understanding how that would be executed, so I need some help.
So I have the following function ($post_blocks is an array of arrays):
public function parse_block_data(string $block_name, string $selector, $post_id)
{
if (!has_blocks($post_id)) {
return false;
}
$post_blocks = parse_blocks(get_the_content('', false, $post_id));
foreach ($post_blocks as $block) {
if ($block_name != $block['blockName']) {
continue;
}
if (!isset($block['attrs']['id'])) {
return false;
}
if (isset($block['attrs']['data'][$selector])) {
return $block['attrs']['data'][$selector];
} else {
break;
}
}
return false;
}
It uses the parameters to build up an array as shown below:
Output
So I started building a while loop inside the function, but I'm clueless on how to achieve it without using a foreach or if it's even possible, so I replaced the foreach with:
// I get the 9 counts of $post_blocks correctly.
$block = 0;
while ($block < count($post_blocks))
// If the $block_name doesn't match `blockName` value inside the multi-dimensional array, then continue iterating until the end and then return false.
// If ['attrs']['id'] is not set, return false.
// At last, if we have a blockName and a ID and the selector is set, return ['attrs']['data'][$selector]
}
All help will be appreciated! It makes no sense to me, but if someone can assist, I'd be forever grateful!
It's basically the same as your foreach loop, you just set the iteration variable by indexing the array, and increment the index manually.
$block_num = 0;
while ($block_num < count($post_blocks)) {
$block = $post_blocks[$block_num];
if ($block_name == $block['blockName']) {
if (!isset($block['attrs']['id'])) {
return false;
}
if (isset($block['attrs']['data'][$selector])) {
return $block['attrs']['data'][$selector];
} else {
break;
}
}
$block_num++;
}
I'm not sure why your colleagues think this is preferable.
If there's a company coding style they want you to follow, why don't you ask them what it should be?

How to call a function with other function as argument

im just learning php
Im trying to add a log with comments to my functions output.
Right now it looks like this:
//the function
function add1($x){
if($GLOBALS['logging'] === 'on'){ $log[] = 'Adding 1 to '.$x;};
$a = $x + 1;
if($GLOBALS['logging'] === 'on'){
$return[] = $a;
$return[] = $log;
return $return;
}else{ return $a; };
};
//calling the function
if($GLOBALS['logging'] === 'on'){
$return = add1($x);
$number = $return[0];
$log = $return[1];
}else{ $number = add1($x); };
Im kinda annoyed by the fact i need to retype this if statement.
So i made a seperate function for returning the function
which looks like this:
//function
function log_return($data = 'x', $log = 'x'){
if($GLOBALS['logging'] === 'on'){
if($data !== 'x') $return[] = $data;
if($log !== 'x') $return[] = $log;
return $return;
} return $data;
};//function end
And returning it with:
return $return = isset($log) ? log_return($data, $log) : log_return($data);
Now my quastion is: Is there a way to call a function with function..
like:
call_function(add1($x));
so i can return it either with log or without..
Given the answer https://stackoverflow.com/a/2700760/5387193 - this should work:
function add1($a)
{
// add1 code goes here
}
function call_function($name, $param)
{
$name($param);
}
call_function('add1', $x);
On a side note, your variable and function names aren't very intuitive. Perhaps you should study how to write good quality readable code. I recommend reading chapter 9 of Refactoring by Martin Fowler, it's quite good. You can find a PDF version on the web.
Another note, your return statement return $return = isset($log) ? log_return($data, $log) : log_return($data); has a unnecessary assignment to $return. The code should simply read
return isset($log) ? log_return($data, $log) : log_return($data);
Yes, it is possible. To simplify:
function first($x) {
return $x+1;
}
function second($y) {
return $y+1;
}
echo second(first(1)); // Returns 3, ie. 1+1+1
As gview said in his comment, don't use global variables. Argument lists exist for several reasons, included but not limited to making code easier to read, edit, and debug. The same goes for function and variable names.
Moreover, your code is very messy. It can be consolidated:
function addTo($currentValue, $valueToAdd, $logging = 0)
{
if ($logging) {
logWrite('addTo', "Adding $valueToAdd to $currentValue");
return $currentValue + $valueToAdd;
} else {
return $currentValue;
}
}
function logWrite($operation, $message)
{
$log = getLog(); // maybe it's a file, or DB record or something
// perform the write, depending on your implementation
}
$number = addTo($someStaringValue, $someOtherValue, 1);
All of this said, logging should not control program flow. In other words, whether something is logged by the system or not should have no bearing on what your code is trying to do. I really think you need to take a broader view of what you're trying to do and break it up into components.
At best, your code should tell a logger to log info, and the logger itself should determine if logging is actually turned on. If it is, the info is logged. If not, then the code that calls on the logger still works and goes about its business.

Toplevel equivalent in PHP of "return" keyword outside function block?

Toplevel equivalent in PHP of "return" keyword outside function blocks ?
A nice, useful property of the return keyword is that when it is invoked,
it exits the main function block in which it is, no matter how many other
nested blocks may surround it.
I am not aware of any equivalent for the toplevel scope. And I would like
to have a systematic way of "expanding" a function
call into an equivalent list of statements, and for that I need to know
a systematic way to deal with all the return ’s in the code.
Consider for example
function seekAUnicorn()
{
for($i=1;some_test($i);$i++) {
for($j=1;some_test($j);$j++) {
for($k=1;some_test($k);$k++) {
if(unicorn_test_for_three_parameters($i,$j,$k)) return(array($i,$j,$k));
}
if(unicorn_test_for_two_parameters($i,$j)) return(array($i,$j));
}
if(unicorn_test_for_one_parameter($i)) return(array($i));
}
}
The expansion of $searchResult=seekAUnicorn(); might look something like this :
for($i=1;some_test($i);$i++) {
for($j=1;some_test($j);$j++) {
for($k=1;some_test($k);$k++) {
if(unicorn_test_for_three_parameters($i,$j,$k)) {
$searchResult = array($i,$j,$k);
break 3;
}
}
if(unicorn_test_for_two_parameters($i,$j)) {
$searchResult = array($i,$j);
break 2;
}
}
if(unicorn_test_for_one_parameter($i)){
$searchResult = array($i);
break;
}
}
But to do it this way, you need to count the number of nested blocks
around each nested return, which becomes painstaking and error-prone for
longer and more complicated code. Is there a simpler way ?
In your case, you can either use goto (since PHP 5.3) or by adding another simple check.
$loopcheck = true;
for($i=1;some_test($i) && $loopcheck;$i++) {
for($j=1;some_test($j) && $loopcheck;$j++) {
for($k=1;some_test($k) && $loopcheck;$k++) {
if(unicorn_test_for_three_parameters($i,$j,$k)) {
$searchResult = array($i,$j,$k);
$loopcheck = false;
break;
}
}
if(unicorn_test_for_two_parameters($i,$j)) {
$searchResult = array($i,$j);
$loopcheck = false;
break;
}
}
if(unicorn_test_for_one_parameter($i)){
$searchResult = array($i);
$loopcheck = false;
}
}

returning from multiple points in a function

This is more or less a readability, maintainability and/or best practice type question.
I wanted to get the SO opinion on something. Is it bad practice to return from multiple points in a function? For example.
<?php
// $a is some object
$somereturnvariable = somefunction($a);
if ($somereturnvariable !== FALSE) {
// do something here like write to a file or something
}
function somefunction($a) {
if (isset($a->value)) {
if ($a->value > 2) {
return $a->value;
} else {
return FALSE;
} else {
// returning false because $a->value isn't set
return FALSE;
}
}
?>
or should it be something like:
<?php
// $a is some object
$somereturnvariable = somefunction($a);
if ($somereturnvariable !== false) {
// do something here like write to a file or something
}
function somefunction($a) {
if (isset($a->value)) {
if ($a->value > 2) {
return $a->value;
}
}
return FALSE
}
?>
As a matter of practice, I always try to return from ONE point in any function, which is usually the final point. I store it in a variable say $retVal and return it in the end of the function.It makes the code look more sane to me.
Having said that, there are circumstances where say, in your function as the first line you check if a var is null and if yes you are returning. In this case, there is no point in holdin on to that variable, then adding additional checks to skip all the function code to return that in the end.
So...in conclusion, both ways works. It always depends on what the situation is and what you are more comfortable with.

Nested if statements, any possible way of cleaning?

I have checked a few other questions but they don't really give me the answer I expect..
My code is a like this..
private function handle()
{
if()
{
if(!condition)
{
if(!condition)
{
if(!condition)
{
if(!condition))
{
if(!condition)
{
if(!condition)
{
if(!condition)
{
if(!condition)
{
if(!condition)
{
code
}
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
}
In my opinion it is readable but messy, sadly I haven't found really a way of making it look 'pretty'. Any ideas?
EDIT: Each return is different.
EDIT2: Gave an answer of my own, thanks everybody!
Conditions can be merged by a && operator..It works form left to right, which means, as soon as the any one starting from left fails, it stops evaluating the condition..
if($a) {
if($b) {
}
}
can be replaced by
if($a && $b) {
}
Use a variable check, or combine the conditions into fewer IF statements.
Variable check like so:
$execute = TRUE;
// Opposite of what you want, e.g. if you want $a only to be TRUE, do $a !== TRUE
if (condition) {
$execute = FALSE;
}
...
// If all the conditions were met, then everything is OK
if($execute === TRUE) {
// code
}else {
// return
}
Edit:
Variable check can be preferably to combining IF statements if you want more control on what returns, e.g. something specific happens if a certain condition fails, which combining conditions can not always allow for.
Like already posted use
if(condition1&&condition2){}
or if this will not work, you can also use function which stops as soon as a condition is true
function some(){
if(!conditon 1){return 0;}
if(condition 2) {return 1;}
}
this provides more power as second if works only if first doesn't satisfy.
You must choose based on your requirements. Sometimes though nested loops are unavoidable.
I thought it out and have found a nice way of doing it, basically I'll make a method for each basic condition, and I'll call them in an if statement with the bitwise AND operator (&), which don't short-circuit.
/**
* nonsql_condition - It means it doesn't check with the database
*
* sql_condition - It means it does check with the database.
*/
if(!$this->nonsql_condition() & !$this->nonsql_condition() & !$this->nonsql_condition() & !$this->nonsql_condition())
{
if(!$this->sql_condition())
{
return error;
}
if(!$this->sql_condition())
{
return error;
}
code;
}
This allows me to use fewer lines of code in my method, plus also not doing unnecessary queries to my database.

Categories