I want to make a whitelist of id that can be created, but for some reason it doesn't work
protected function prepareForValidation(){
$WhiteListes = WhiteList::all();
foreach ($WhiteListes as $WhiteList){
if ($WhiteList->server_id == $this->id) {
$this->merge(['id' => $this->id]);
} else {
$this->merge(['id' => null]);
}
}
}
This returns null. Although it should return an $this->id
I've already tried doing this
foreach ($WhiteListes as $WhiteList){
$test = $WhiteList->server_id == $this->id;
dd($test);
}
This returns True to me
Why does it work so crookedly? And how do I do it right
Related
I have following function which helps me get category name.
public function getParent($categoryId, $keepData) {
$parentCategory = Category::select('category_id', 'parent_id', 'title')
->where('category_id', $categoryId)->first();
if($parentCategory->parent_id > 0) {
$parent = Category::select('category_id','parent_id','title')
->where('category_id',$parentCategory->parent_id)
->first();
$keepData[$parent->category_id] = $parent->title;
$this->getParent($parent->category_id, $keepData);
} else {
//print_r($keepData);
return $keepData;
}
}
When I do print_r inside function it prints an array.
array:2 [▼
3 => "Stock Boxes"
1 => "Boxes"
]
but calling this function from other function as,
$keepData = array();
$breadcrumb = $this->getParent($categoryId, $keepData);
print_r($breadcrumb);
then it returns null.
What is the step I am missing. any help would be great.
Apparently this condition
if ($parentCategory->parent_id > 0) {
// ...
}
evaluates to true, and in this block you are not returning anything, that's why the method invocation effectively returns null.
Adjust the method to
public function getParent($categoryId, array $keepData = [])
{
$parentCategory = Category::select('category_id', 'parent_id', 'title')->where('category_id', $categoryId)->first();
if ($parentCategory->parent_id > 0) {
$parent = Category::select('category_id','parent_id','title')->where('category_id',$parentCategory->parent_id)->first();
$keepData[$parent->category_id] = $parent->title;
return $this->getParent(
$parent->category_id,
$keepData
);
}
return $keepData;
}
and invoke like this (note how $keepData is turned into an optional parameter and defaults to an empty array):
$breadcrumb = $this->getParent($categoryId);
I'm struggling to pass a value from a recursive function into an array in a different method. I have written my recursive function below.
function get_parent_basket_id($parent_id) {
if($parent_id==NULL){
return false;
}
$baskets = $this->Model_cds_clients->clients($parent_id)->result();
if(count($baskets)==0){
return false;
}
foreach ($baskets as $row) {
if($row->parent_id==0){
return $row->id;
} else {
$this->get_parent_basket_id($row->parent_id);
}
}
}
My Model_cds_clients code is below
function clients ($parent_id) {
$this->db->select('endpoint, parent_id');
$this->db->from('cds_clients');
$this->db->where('parent_id', $parent_id);
$this->db->where('active', 1);
$result = $this->db->get();
return $result;
}
My table structure for my model looks like below
id - int(11)
name - varchar(255)
endpoint - varchar(64)
active - tinyint(1)
parent_id - int(11)
Below is my function where I need to pass the variable into the client_id under the endpoints array.
public function __construct() {
parent::__construct();
$this->load->model('Model_story');
$this->get_parent_basket_id($parent_id);
$data = array(
'basket_id' => $this->basketId,
'story_id' => $this->storyId,
'payload' => $this->xmlString,
'endpoints' => array(
array(
'client_id' => XXXX,
'endpoint_url' => 'http://www.example.com/consume.php'
), )
);
$json_payload = json_encode($data);
Please help.
I'm not sure if this is what you are looking for, but it's what sticks out to me
Change:
foreach ($baskets as $row) {
if($row->parent_id==0){
return $row->id;
} else {
$this->get_parent_basket_id($row->parent_id);
}
}
to:
foreach ($baskets as $row) {
if($row->parent_id==0){
return $row->id;
} else {
return $this->get_parent_basket_id($row->parent_id);
}
}
in your recursive function. This way the id will actually get passed back.
Then, in your controller, assign the result to a variable i.e.
$parent_basket_id = $this->get_parent_basket_id($parent_id);
However, it doesn't look like you're declaring/passing $parent_id to __construct() so I'm not sure how this is meant to work.
Hope this help!
Your tail recursion's base case doesn't look quite right. Your direct call needs to return the results. I have re-factored your method as follows:
function get_parent_basket_id($parent_id) {
if(!$parent_id){
return false;
}
// Your method chaining is missing brackets on $this->Model_cds_clients()
$baskets = $this->Model_cds_clients()->clients($parent_id)->result();
if(!count($baskets)){
return false;
}
foreach ($baskets as $row) {
if(!$row->parent_id){
return $row->id;
} else {
// Add a return here
return $this->get_parent_basket_id($row->parent_id);
}
}
}
I hope the preceding code helps you. :)
I have one PHP class as below (part of the code):
class myclass{
private static $arrX = array();
private function is_val_exists($needle, $haystack) {
if(in_array($needle, $haystack)) {
return true;
}
foreach($haystack as $element) {
if(is_array($element) && $this->is_val_exists($needle, $element))
return true;
}
return false;
}
//the $anInput is a string e.g. Michael,18
public function doProcess($anInput){
$det = explode(",", $anInput);
if( $this->is_val_exists( $det[0], $this->returnProcess() ) ){
//update age of Michael
}
else{
array_push(self::$arrX, array(
'name' => $det[0],
'age' => $det[1]
));
}
}
public function returnProcess(){
return self::$arrX;
}
}
The calling code in index.php
$msg = 'Michael,18';
myclass::getHandle()->doProcess($msg);
In my webpage says index.php, it calls function doProcess() over and over again. When the function is called, string is passed and stored in an array. In the next call, if let's say same name is passed again, I want to update his age. My problem is I don't know how to check if the array $arrX contains the name. From my own finding, the array seems to be re-initiated (back to zero element) when the code is called. My code never does the update and always go to the array_push part. Hope somebody can give some thoughts on this. Thank you.
There is a ) missing in your else condition of your doProcess() function, it should read:
else{
array_push(self::$arrX, array(
'name' => $det[0],
'age' => $det[1]
)); // <-- there was the missing )
}
Here is a complete running solution based on your code:
<?php
class myclass{
private static $arrX = array();
private function is_val_exists($needle, $haystack) {
if(in_array($needle, $haystack)) {
return true;
}
foreach($haystack as $element) {
if(is_array($element) && $this->is_val_exists($needle, $element))
return true;
}
return false;
}
//the $anInput is a string e.g. Michael,18
public function doProcess($anInput){
$det = explode(",", $anInput);
if( $this->is_val_exists( $det[0], $this->returnProcess() ) ){
//update age of Michael
for ($i=0; $i<count(self::$arrX); $i++) {
if (is_array(self::$arrX[$i]) && self::$arrX[$i]['name'] == $det[0]) {
self::$arrX[$i]['age'] = $det[1];
break;
}
}
} else{
array_push(self::$arrX, array(
'name' => $det[0],
'age' => $det[1]
));
}
}
public function returnProcess(){
return self::$arrX;
}
}
$mc = new myclass();
$mc->doProcess('Michael,18');
$mc->doProcess('John,23');
$mc->doProcess('Michael,19');
$mc->doProcess('John,25');
print_r($mc->returnProcess());
?>
You can test it here: PHP Runnable
As I said in comments, it looks like you want to maintain state between requests. You can't use pure PHP to do that, you should use an external storage solution instead. If it's available, try Redis, it has what you need and is quite simple to use. Or, if you're familiar with SQL, you could go with MySQL for example.
On a side note, you should read more about how PHP arrays work.
Instead of array_push, you could have just used self::$arrX[] = ...
Instead of that, you could have used an associative array, e.g. self::$arrX[$det[0]] = $det[1];, that would make lookup much easier (array_key_exists etc.)
Can you try updating the is_val_exists as follows:
private function is_val_exists($needle, $haystack) {
foreach($haystack as $element) {
if ($element['name'] == $needle) {
return true;
}
return false;
}
PROBLEM
I have a function that takes in a nested array where the structure and nesting of the array is unknown at run-time. All that is known is some of the target fieldnames and desired values of some of the leafs.
QUESTIONS
1) I am hoping to modify this unknown structure and still have the code be readable and easily understood by fellow programmers. What (if any) solution will allow me to do things like this in PHP?
// Pseudo-code for things I would like to be able to do
// this is kinda like the same thing as XPATH, but for native PHP array
// find *every* fname with value of "Brad" and change it to "Brian"
$mydata->find_all('*:fname')->where_value_eq('Brad')->set_equal_to('Brian');
// find *the first* fave_color and set it to "Green"
$mydata->find('*:fave_color')->get(0)->set_equal_to('Green');
2) If there is nothing out there that will let me do this, is there something, anything, that at least comes close to the spirit of what I am hoping to accomplish here?
SAMPLE ARRAY
$mydata = array(
'people' => array(
array('fname'=>'Alice'),
array('fname'=>'Brad'),
array('fname'=>'Chris'),
),
'animals' => array(
array('fname'=>'Dino'),
array('fname'=>'Lassie'),
array('fname'=>'Brad'),
),
'settings' => array(
'user_prefs'=>array(
'localhost'=>array(
'fave_color'=>'blue',
),
),
),
'places' => array(
array('state'=>'New york',
'cities'=>array(
'name'=>'Albany',
'name'=>'Buffalo',
'name'=>'Corning',
),
'state'=>'California',
'cities'=>array(
'name'=>'Anaheim',
'name'=>'Bakersfield',
'name'=>'Carlsbad',
),
),
),
);
Although I maintain that you should stick with explicit manipulation as in my previous answer, boredom and intrigue got the better of me ;)
It probably has holes (and clearly lacks docs) but if you insist on this route, it should get you started:
class Finder {
protected $data;
public function __construct(&$data) {
if (!is_array($data)) {
throw new InvalidArgumentException;
}
$this->data = &$data;
}
public function all() {
return $this->find();
}
public function find($expression = null) {
if (!isset($expression)) {
return new Results($this->data);
}
$results = array();
$this->_find(explode(':', $expression), $this->data, $results);
return new Results($results);
}
protected function _find($parts, &$data, &$results) {
if (!$parts) {
return;
}
$currentParts = $parts;
$search = array_shift($currentParts);
if ($wildcard = $search == '*') {
$search = array_shift($currentParts);
}
foreach ($data as $key => &$value) {
if ($key === $search) {
if ($currentParts) {
$this->_find($currentParts, $value, $results);
} else {
$results[] = &$value;
}
} else if ($wildcard && is_array($value)) {
$this->_find($parts, $value, $results);
}
}
}
}
class Results {
protected $data;
public function __construct(&$data) {
$this->data = $data;
}
public function get($index, $limit = 1) {
$this->data = array_slice($this->data, $index, $limit);
return $this;
}
public function set_equal_to($value) {
foreach ($this->data as &$datum) {
$datum = $value;
}
}
public function __call($method, $args) {
if (!preg_match('/^where_?(key|value)_?(eq|contains)$/i', $method, $m)) {
throw new BadFunctionCallException;
}
if (!isset($args[0])) {
throw new InvalidArgumentException;
}
$operand = $args[0];
$isKey = strtolower($m[1]) == 'key';
$method = array('Results', '_compare' . (strtolower($m[2]) == 'eq' ? 'EqualTo' : 'Contains'));
$ret = array();
foreach ($this->data as $key => &$datum) {
if (call_user_func($method, $isKey ? $key : $datum, $operand)) {
$ret[] = &$datum;
}
}
$this->data = $ret;
return $this;
}
protected function _compareEqualTo($value, $test) {
return $value == $test;
}
protected function _compareContains($value, $test) {
return strpos($value, $test) !== false;
}
}
$finder = new Finder($mydata);
$finder->find('*:fname')->where_value_eq('Brad')->set_equal_to('Brian');
$finder->find('*:fave_color')->get(0)->set_equal_to('Green');
$finder->find('places:*:cities:*:name')->where_value_contains('ba')->set_equal_to('Stackoton');
print_r($mydata);
There's certainly no native solution for this and the syntax is rather strange. If you want the code to "be readable and easily understood by fellow programmers" please stick to methods that we're used to working with ;)
foreach ($mydata as $type => &$data) {
foreach ($data as &$member) {
if (isset($member['fname']) && $member['fname'] == 'Brad') {
$member['fname'] = 'Brian';
}
}
}
It's admittedly more verbose, but there's much less chance of confusion.
So currently I am using a pattern to grab a data entry (record). It works great for me if I only need to work with one record. However if more than one record is involved it gets more complicated.
Here is my base pattern, using a contacts table:
class Contacts_Entry {
private $_entry = Array('contact_id' => false,
'name' => false,
'email' => false,
'phone' => false,
'type' => false );
private $_entryKey = Array('contact_id' => 'i',
'name' => 's',
'email' => 's',
'phone' => 's',
'type' => 'i' );
public function __call($_method, $_arguments)
{
/* API: Get */
if (substr($_method, 0, 3) == 'get') {
return $this->_getElement(camelCaseToUnderscore(substr($_method, 3)));
}
/* API: Set */
if (substr($_method, 0, 3) == 'set' && count($_arguments) == 1) {
return $this->_setElement(camelCaseToUnderscore(substr($_method, 3)), $_arguments[0]);
}
unset($_method,$_arguments);
return false;
}
private function _getElement($_element)
{
if (!array_key_exists($_element, $this->_entry)) { return false; }
if ($this->_entryKey[$_element] == 's') {
if (!strlen($this->_entry[$_element])) { return false; }
} elseif ($this->_entryKey[$_element] == 'i') {
if (!strlen($this->_entry[$_element]) || !is_numeric($this->_entry[$_element])) { return false; }
} elseif ($this->_entryKey[$_element] == 'a') {
if (!count($this->_entry[$_element])) { return false; }
} else {
return false;
}
return $this->_entry[$_element];
}
private function _setElement($_element, $_data)
{
if (!array_key_exists($_element, $this->_entry)) { return false; }
if ($this->_entryKey[$_element] == 's') {
if (!strlen($_data)) { return false; }
} elseif ($this->_entryKey[$_element] == 'i') {
if (!strlen($_data) || !is_numeric($_data)) { return false; }
} elseif ($this->_entryKey[$_element] == 'a') {
if (!count($_data)) { return false; }
} else {
return false;
}
if ($this->_entry[$_element] = $_data) { return true; }
return false;
}
public function load($_entryId)
{
// Code to load an entry into $this->_entry;
}
public function save()
{
// Code to save an entry from $this->_entry;
}
}
As you can see, this works very well for single records. I can even pass this object to Smarty, and use the getMethod()s inside a template.
But what I need help thinking up, is a good way to take this kind of implementation and make it work for multiple records, in a clean manner.
You're reinventing the wheel. Have a look at existing ORM's (or at the ORM article in the wikipedia) first, before deciding that you need to implement one yourself.
Why don't you simply use it as a list of objects (array). So you can iterate through the array. Each array node has its own object. That's all.