My question is regarding the use of the file system as a database to simply hold JSON files.
I have came up with this following code, not perfect at all. which I found very easy to store and extract data, using JSON files.
My question is, will this DB be good for any large projects? will it work fast? or is the limitation to use this kind of approach is simply security related?
Is there some kind of built-in solution by PHP for this kind of things?
Any input on this matter from people who know will be appreciated...
class JDB{
public $path;
function JDB( $path = __DIR__.'/jdb/' ){
$this->path = $path;
if( !file_exists($this->path) ) mkdir($this->path);
}
function p($t){
return $this->path.$t.'.json';
}
function get($t){
return json_decode(file_get_contents( $this->p($t) ));
}
function set($t,$c){
return file_put_contents( $this->p($t), json_encode($c,JSON_PRETTY_PRINT) );
}
function create( $t, $d = [] ){
$s = file_put_contents( $this->p($t), json_encode($d) );
return $s;
}
function destroy(){
$files = glob($this->path.'*'); // get all file names present in folder
foreach($files as $file){ // iterate files
if(is_file($file))
unlink($file); // delete the file
}
}
function delete( $t ){
$s = unlink( $this->p($t) );
return $s;
}
function insert( $t, $d = null ){
if($d) $d['__uid'] = $t.'_'.$this->uid();
$c = $this->get($t);
array_push($c,$d);
$s = $this->set($t,$c);
if($s) return $d['__uid'];
}
function update($t,$conditions,$u){
$c = $this->get($t);
$this->search($c,$conditions,function($object) use (&$c,$u){
foreach ($u as $key => $value) {
$object->$key = $value;
}
});
$this->set($t,$c);
}
function remove($t,$conditions){
$c = $this->get($t);
$this->search($c,$conditions,function($object,$key) use (&$c){
unset($c[$key]);
});
$this->set($t,$c);
}
function search( $c, $conditions = [], $fn ){
$l = count($conditions);
foreach ($c as $key => $object) {
$f = 0;
foreach ($conditions as $k => $v) {
if( property_exists($object,$k) && ($object->$k == $v) ){
$f++;
if( $f==$l ) $fn($object,$key);
}else break;
}
}
}
function select( $t, $conditions = [] ){
$c = $this->get($t);
$r = [];
$this->search($c,$conditions,function($object) use (&$r){
array_push($r,$object);
});
if (count($r) == 0) return false;
if (count($r) == 1) return $r[0];
return $r;
}
function count($t){
$c = $this->get($t);
return count($c);
}
function uid($length = 20) {
$c = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$cl = strlen($c);
$uid = '';
for ($i = 0; $i < $length; $i++) {
$uid .= $c[rand(0, $cl - 1)];
}
return $uid;
}
}
very simple, the question if this is even possible...
How To Use
$db = new JDB();
$db->create('users');
$db->create('pages');
$user_uid = $db->insert('users',[
'name' => 'a',
'password' => 'hello world',
'pages' => []
]);
$user_uid = $db->insert('users',[
'name' => 'b',
'password' => 'hello world',
'pages' => []
]);
$page_uid = $db->insert('pages',[
'name' => 'page 1',
'content' => 'hello world',
'users' => [$user_uid]
]);
$user = $db->select('users',['name' => 'a']);
$page = $db->select('pages',['users' => [$user_uid]]);
$db->update('users',['name' => 'b'],['pages' => [$page->__uid]]);
$db->remove('users',['name' => 'a']);
Related
I have a list of strings that each contain dot notated values. I want to convert this list into an associative array with each segment of the dot notation as a key in the appropriate nesting level. The deepest level of nesting should have a value of boolean true. There's no limit to the number or dot segments a string can contain so the code needs to do some kind of recursion to achieve the goal.
Input example:
[
'foo.bar',
'foo.bar.baz',
'foo.bar.qux',
'foo.qux',
'foo.quux',
'bar.baz',
'bar.qux',
'qux.quux',
]
Required output:
[
'foo' => [
'bar' => [
'baz' => true,
'qux' => true,
],
'qux' => true,
'quux' => true,
],
'bar' => [
'baz' => true,
'qux' => true,
],
'qux' => [
'quux' => true
]
]
foreach only solution.
function convert(array $input)
{
$r = [];
foreach ($input as $dotted) {
$keys = explode('.', $dotted);
$c = &$r[array_shift($keys)];
foreach ($keys as $key) {
if (isset($c[$key]) && $c[$key] === true) {
$c[$key] = [];
}
$c = &$c[$key];
}
if ($c === null) {
$c = true;
}
}
return $r;
}
If you call your starting array of strings $input, the $output array in the code below is what you want
$input=[...]; //original array
$output=[]; //holds the results;
foreach ($input as $line){
$keys = explode('.',$line);//break each section into a key
$val = true; //holds next value to add to array
$localArray = []; //holds the array for this input line
for($i=count($keys)-1; $i>=0; $i--){ //go through input line in reverse order
$localArray = [$keys[$i]=>$val]; //store previous value in array
$val = $localArray; //store the array we just built. it will be
//the value in the next loop
}
$output = array_merge_recursive($output,$localArray);
}
Live demo
You can do this using pointer and some logic.
<?php
$test = [
'foo.bar',
'foo.bar.baz',
'foo.bar.qux',
'foo.qux',
'foo.quux',
'bar.baz',
'bar.qux',
'qux.quux',
];
class Test
{
public $result = [];
public function check($array){
foreach ($array as $value) {
$this->change($value);
}
}
public function change($string)
{
$explodedValues = explode('.',$string);
$pointerVariable = &$this->result;
foreach ($explodedValues as $explodedValue) {
if(!is_array($pointerVariable)){
$pointerVariable = [];
$pointerVariable[$explodedValue] = true;
$pointerVariable = &$pointerVariable[$explodedValue];
} else if(isset($pointerVariable[$explodedValue])){
$pointerVariable = &$pointerVariable[$explodedValue];
} else {
$pointerVariable[$explodedValue] = true;
$pointerVariable = &$pointerVariable[$explodedValue];
}
}
}
}
$obj = new Test();
$obj->check($test);
print_r($obj->result);
Hope this will help
function convert($aa) {
$zz = [];
foreach( $aa as $value ) {
$bb = explode('.',$value);
$cc = count($bb);
for( $ii = 0, $yy = &$zz; $ii < $cc ; $ii++ ) {
$key = $bb[$ii];
if ( array_key_exists($key,$yy) === false || is_array($yy[$key]) === false ) {
$yy[$key] = [];
}
$yy = &$yy[$key];
}
$key = $bb[$cc-1];
if ( array_key_exists($key,$yy) === false ) {
$yy[$key] = true;
}
}
return $zz;
}
I'm looking for the way to combine 2 foraech loops into one (merge 2 functions):
The result function should return both: ($is - boolean & $d - array).
Traversable data in both functions - the same.
Is it possible? What will be a good solution for that?
public function func1($p, $c) {
$is = 0;
if (!empty($p)) {
foreach($p as $k=>$v) {
if ((!empty($c['prod']) && $c['prod'] == $v['ref'] && $c['status'])) {
$is = 1;
break;
}
}
}
return $is;
}
public function func2($p) {
$d = [];
if (!empty($p)) {
foreach($p as $k=>$v) {
$prod = [
'name' => $v['name'],
'price' => $v['price'],
'reference' => $v['ref']
];
$d[] = $prod;
}
}
return $d;
}
Thanks.
My take, but not tested.
public function func3($p, $c) {
$is = 0;
$d = [];
if (!empty($p)) {
foreach($p as $k=>$v) {
$d[] = [
'name' => $v['name'],
'price' => $v['price'],
'reference' => $v['ref']
];
if ($is === 0 && (!empty($c['prod']) && $c['prod'] == $v['ref'] && $c['status'])) {
$is = 1;
}
}
}
return [$is, $d];
}
I have a list of strings that each contain dot notated values. I want to convert this list into an associative array with each segment of the dot notation as a key in the appropriate nesting level. The deepest level of nesting should have a value of boolean true. There's no limit to the number or dot segments a string can contain so the code needs to do some kind of recursion to achieve the goal.
Input example:
[
'foo.bar',
'foo.bar.baz',
'foo.bar.qux',
'foo.qux',
'foo.quux',
'bar.baz',
'bar.qux',
'qux.quux',
]
Required output:
[
'foo' => [
'bar' => [
'baz' => true,
'qux' => true,
],
'qux' => true,
'quux' => true,
],
'bar' => [
'baz' => true,
'qux' => true,
],
'qux' => [
'quux' => true
]
]
foreach only solution.
function convert(array $input)
{
$r = [];
foreach ($input as $dotted) {
$keys = explode('.', $dotted);
$c = &$r[array_shift($keys)];
foreach ($keys as $key) {
if (isset($c[$key]) && $c[$key] === true) {
$c[$key] = [];
}
$c = &$c[$key];
}
if ($c === null) {
$c = true;
}
}
return $r;
}
If you call your starting array of strings $input, the $output array in the code below is what you want
$input=[...]; //original array
$output=[]; //holds the results;
foreach ($input as $line){
$keys = explode('.',$line);//break each section into a key
$val = true; //holds next value to add to array
$localArray = []; //holds the array for this input line
for($i=count($keys)-1; $i>=0; $i--){ //go through input line in reverse order
$localArray = [$keys[$i]=>$val]; //store previous value in array
$val = $localArray; //store the array we just built. it will be
//the value in the next loop
}
$output = array_merge_recursive($output,$localArray);
}
Live demo
You can do this using pointer and some logic.
<?php
$test = [
'foo.bar',
'foo.bar.baz',
'foo.bar.qux',
'foo.qux',
'foo.quux',
'bar.baz',
'bar.qux',
'qux.quux',
];
class Test
{
public $result = [];
public function check($array){
foreach ($array as $value) {
$this->change($value);
}
}
public function change($string)
{
$explodedValues = explode('.',$string);
$pointerVariable = &$this->result;
foreach ($explodedValues as $explodedValue) {
if(!is_array($pointerVariable)){
$pointerVariable = [];
$pointerVariable[$explodedValue] = true;
$pointerVariable = &$pointerVariable[$explodedValue];
} else if(isset($pointerVariable[$explodedValue])){
$pointerVariable = &$pointerVariable[$explodedValue];
} else {
$pointerVariable[$explodedValue] = true;
$pointerVariable = &$pointerVariable[$explodedValue];
}
}
}
}
$obj = new Test();
$obj->check($test);
print_r($obj->result);
Hope this will help
function convert($aa) {
$zz = [];
foreach( $aa as $value ) {
$bb = explode('.',$value);
$cc = count($bb);
for( $ii = 0, $yy = &$zz; $ii < $cc ; $ii++ ) {
$key = $bb[$ii];
if ( array_key_exists($key,$yy) === false || is_array($yy[$key]) === false ) {
$yy[$key] = [];
}
$yy = &$yy[$key];
}
$key = $bb[$cc-1];
if ( array_key_exists($key,$yy) === false ) {
$yy[$key] = true;
}
}
return $zz;
}
I have a loop which increments the limit of the content which is showing on a website (json content).
The problem is that the loop stops at 50. The links that are generated with the incrementation are working fine when I'm calling them in the browser. The content is shown.
But I store only the content of the first 50 and then it stops.
public static function getAllCustomers() {
$rest = Rest::getInstance();
$spaces = self::getSpaces();
$customers = array();
$path = SpacePath::buildPath();
for ($i = 0;
; $i += Paths::$MAX_CONTENT_LENGTH) {
$temp = $path . '?start=' . $i . '&limit=50';
$content = Helper::toArray($temp);
print_r($temp);
// print_r(empty($content['results']));
if (!empty($content['results'])) {
foreach ($content ['results'] as $space) {
if (!preg_match('|^(.*?)-([0-9]+)|i', $space ['name'], $matches)) {
continue;
}
$customer = (object) array(
'name' => $matches [0],
'ident' => $matches [1],
'id' => $matches [2],
'space_key' => $space ['key'],
'options' => array()
);
$customers [] = $customer;
}
break;
}
}
print_r($customers);
return $customers;
}
Here, let me reformat your code so you can see what relates to what...
public static function getAllCustomers()
{
$rest = Rest::getInstance();
$spaces = self::getSpaces();
$customers = array();
$path = SpacePath::buildPath();
for ($i = 0; ; $i += Paths::$MAX_CONTENT_LENGTH)
{
$temp = $path . '?start=' . $i . '&limit=50';
$content = Helper::toArray($temp);
print_r($temp);
//print_r(empty($content['results']));
if (!empty($content['results']))
{
foreach ($content ['results'] as $space)
{
if (!preg_match('|^(.*?)-([0-9]+)|i', $space ['name'], $matches))
{
continue;
}
$customer = (object) array('name' => $matches [0]
,'ident' => $matches [1]
,'id' => $matches [2]
,'space_key' => $space ['key']
,'options' => array()
);
$customers [] = $customer;
}
break; // oops
}
}
print_r($customers);
return $customers;
}
You'll notice I added a comment to your break statement. ;)
I was trying to access GCD from inside Algorithm but it's not letting me and I'm not sure why. What am I doing wrong here?
public function gcd($x,$y)
{
do {
$rest=$x%$y;
$x=$y;
$y=$rest;
} while($rest!==0);
return $x;
}
public function algorithm()
{
$alpha = array(
'c' => str_split('bcdfghjklmnpqrstvwxz'),
'v' => str_split('aeiouy')
);
$i=$k=0;
foreach ($this->output as $item) {
$cnt = 0;
$this->digits[$i] = array();
foreach ($item as $part) {
$this->digits[$i][$cnt] = array();
$new = array();
foreach ($part as $str) {
$v = count(array_intersect(str_split($str), $alpha['v']));
$c = count(array_intersect(str_split($str), $alpha['c']));
$t = strlen(str_replace(' ', '', $str));
$new = ($cnt == 0)
? array('v' => $v, 'c' => $c, 't' => $t, 'm' => ($t%2) ? $v * 1.5 : $c)
: array('v' => $v, 'c' => $c, 't' => $t);
$this->digits[$i][$cnt][] = $new;
}
$cnt++;
}
$i++;
}
$h=$a=0;
foreach($this->digits as &$etc) {
foreach($etc[0] as &$r){
foreach($etc[1] as $k) {
foreach($k as $x=>$y) {
$tmp[$h] = (gcd($y,$r['t']) != 1) ? ++$a:'';
}
$tmp[$h] = $r['m']*$a*1.5;
$h++;
$a=0;
}$h=0;
$r['f'] = $tmp;
$tmp='';
}
}
foreach($this->digits as &$u){unset($u[1]);}
}
judging by your use of the public identifier, I would guess your two functions are in a class.
To refer to methods on the same object, use $this->methodname()
from your code:
$tmp[$h] = (gcd($y,$r['t']) != 1) ? ++$a:'';
should be:
$tmp[$h] = ($this->gcd($y,$r['t']) != 1) ? ++$a:'';
...
$this->gcd()?
But really, since gcd doesn't use any member variables, it should be a free function.
You're missing $this->gcd inside algorithm
just tryng to acces it direct
:)