Using custom table for jsTree without hardcoding - php

Am using jsTree + PHP, and I would like to load up two different trees from two different database tables, depending on what user type the logged in user is.
I tracked down the code to the "class.tree.php" file,
class json_tree extends _tree_struct {
function __construct($table = 'tree', $fields = array(), $add_fields = array("title" => "title", "type" => "type")) {
parent::__construct($table, $fields);
$this->fields = array_merge($this->fields, $add_fields);
$this->add_fields = $add_fields;
}
Where the $table = 'tree' is hard-coded. I tried removing it (so just $table), and passing 'tree' through as
$jstree = new json_tree('tree');
but that didn't work. Any ideas/help would be greatly appreciated!

To those curious, I had completely forgotten that server.php also includes a jstree (I had also initiated it in my left menu). For those interested, or who need a conditional based tree, what I did was:
removed the $table = 'tree' in the __construct as above, which becomes
function __construct($table, $fields = array(), $add_fields = array("title" => "title", "type" => "type"))
added a session to the config.php (session_start())
I have a log in, which allows me to get the condition
in server.php, I did the following
if($_SESSION['condition'] == 1) { $jstree = new json_tree("tree");}
else { $jstree = new json_tree("tree_users");}
I hope this helps someone!

Related

How to store data from dynamically added lines with multiple inputs

I created a form containing info about the user (doctors). Besides the default info, they now want to add opening hours from their office.
In the current form I added a form-group with 3 input elements:
select name="dayofweek[]"
input name="timeblock[]"
select name="type[]"
There is a button for the user to add an extra line with the same fields so he can create multiple opening hours (per day/timeblock).
All is stored with the submit-button from the form.
After saving my data looks like this:
"dayofweek" => ["monday", "monday", "tuesday", ...]
"timeblock" => ["10-12h", "14-18h", "10-16u", ...]
"type" => ["by appointment", "free", "free", ...]
Now I want to save these in my table with fields [ID, DayOfWeek, TimeBlock, Type].
To do so I have to rearrange the data received from the form-submit before I can save them row by row. This is how I do it now:
public static function prepareData($dayofweek = [], $timeblock = [], $type = []) {
$prepared = [];
$i = 0;
while($i < count($dayofweek)) {
$a = $dayofweek[$i];
$b = $timeblock[$i];
$c = $type[$i];
$record = ['dayofweek' => $a, 'timeblock' => $b, 'type' => $c];
array_push($prepared, $record);
$i++;
}
return $prepared;
}
To show the data on the form when editing, I have to do the inverse.
I was wondering if there is any other easier and cleaner way to do this?
Unfortunately, the native data type like array and string can have only one format and structure. If your use case uses the same data in different formats or different data structure, it is recommended to create a data object. A data object is an object that holds the data in its fields and has many inputs and output methods to allow to use the data in different formats and structures.
This is an OOP approach, in this case, it will make your code much cleaner and understandable and much more easy to expand or alter in the future. But note that this will not reduce the amount of code. The format conversion function is required anyway.
According to the description, we have a data object named Appointment with the data {DayOfWeek, TimeBlock, Type}. However, the input and output functions that are described referring to a list of Appointments, therefore, those functions do not belong to Appointment object. They refer to another data object, AppointmentList which contain an array of Appointments and input and output functions.
This object will look like this:
class Appointment
{
public $dayofweek;
public $timeblock;
public $type;
public function __construct($record)
{
$this->dayofweek = $record['dayofweek'];
$this->timeblock = $record['timeblock'];
$this->type = $record['type'];
}
}
class AppointmentList
{
public $appointmentArray = [];
function setData($data)
{
$prepared = [];
$i = 0;
while ($i < count($data['dayofweek'])) {
$a = $data['dayofweek'][$i];
$b = $data['timeblock'][$i];
$c = $data['type'][$i];
$record = ['dayofweek' => $a, 'timeblock' => $b, 'type' => $c];
$prepared[] = new Appointment($record);
$i++;
}
$this->appointmentArray = $prepared;
}
function getData() {
$data = ['dayofweek' => [],'timeblock' => [],'type' => []];
foreach ($this->appointmentArray as $appointment){
$data['dayofweek'][] = $appointment->dayofweek;
$data['timeblock'][] = $appointment->timeblock;
$data['type'][] = $appointment->type;
}
return $data;
}
}
Then when you receive $data from the form run:
$al = new AppointmentList();
$al->setData($data);
The you can use the array $al->appointmentArray to access the appointments one by one and store them in the table.
And afterward when you need to fill the form again simply use $al->getData()
Note that this is only an example. Usually different techniques are used to store the data object into the table automatically.
Hope this helps. Good luck.

How to merge data in elasticsearch

i want to merge some data in Elasticsearch, but every time it is replacing my previous data and not merging it.
Suppose when i new is created it should add with the previous data, not replacing previous data. So Suppose there is a user exists in the "update_field" named "Christofer" so when i array_merge($usernames) where $usernames contains one or couple of usernames it is always replacing previous data.
I am working on PHP.
$usernames= array ("Johanna", "Maria");
$doc = array();
$doc['update_field'] = array_merge($usernames);
$u_params = array();
$u_params['id'] = 'my_id';
$u_params['index'] = 'my_index';
$u_params['type'] = 'my_type';
$u_params['body'] = array('doc' => $doc);
$client->update($u_params);
For being more clear, as a example let's say in the usernames field there are couple of username exists- like - "Christofer", "Henrik", "Eric".
So now i want to add more user like - "Johanna", "Maria", ...
Now every time i merge and update documents it is replacing the data, like ("Christofer", "Henrik", "Eric") is getting replace by ("Johanna", "Maria").
I want them to be added not replaced.
Do any body knows how can i merge the new data, or just the new data in other process. Thanks in advanced.
You need to use partial update. Try this instead, i.e. you need to send a doc hash in the body with the fields to marge (i.e. update_fields):
$params = [
'index' => 'my_index',
'type' => 'my_type',
'id' => 'my_id',
'body' => [
'doc' => [
'update_field' => array_merge($usernames)
]
]
];
$client->update($params);
UPDATE
That's right, core values and arrays are getting replaced.
You may want to try scripted partial update then
$usernames= array ("Johanna", "Maria");
$script = array();
$script['script'] = 'ctx._source.update_field += new_value';
$script['params'] = array('new_value' => array_merge($usernames));
$u_params = array();
$u_params['id'] = 'my_id';
$u_params['index'] = 'my_index';
$u_params['type'] = 'my_type';
$u_params['body'] = $script;
$client->update($u_params);
And make sure that scripting is enabled in your elasticsearch.yml config file:
script.disable_dynamic: false

Cakephp ClassRegistry::init

I have this code:
$userObj = ClassRegistry::init('User');
$userObj->contain();
$conditions = "User.studio_id = '".$studioID."' AND User.usergroup_id = 5";
$studioAdmin = $userObj->find($conditions);
The one that is causing the error is this line:
$studioAdmin = $userObj->find($conditions);
When I say error, it does not print anything or any warning of error, it just stops the code below it, I noticed that one because when I try to echo a code above it, it prints it, but when I try to echo a code below it, it does not print anything,
What is the problem here. Your help will be greatly appreciated! Thanks! :)
The better practice way of loading models in components is to go via the controller, and use loadModel()
In your component, set up the initialize()
function initialize($controller, $settings) {
$this->Controller =& $controller;
}
Then in your component function, use loadModel to load the model
$this->Controller->loadModel('Modelname');
$this->Modelname->save($data);
and also for find condition
$users = $this->Modelname->find('all', array(
'conditions' => array(
'User.studio_id' => $studioID,
'User.usergroup_id' => 5
)
));
You should be doing this:
$studioAdmin = $userObj->find('all', array( 'conditions' => $conditions ) );
Do you have PHP error messaging turned on? Did you check your logs to see what the specific error is?
Also, by cake standards, it is better to build your conditions clause this way:
$conditions = array(
"User.studio_id" => $studioID,
"User.usergroup_id" => 5"
);

Choose duplication vs. string based variable (object property) creation

I have code like this:
$something_type = $this->db
->where('something_type_id', $something->something_type_id)
->get('something_types')
->row();
if(!$something_type) {
$something->type = lang('data_not_specified');
} else {
$something->type = $something_type->something_type_name;
}
// everything is exactly the same here except for one word
$something_category = $this->db
->where('something_category_id', $something->something_category_id)
->get('something_categories')
->row();
if(!$something_category) {
$something->category = lang('data_not_specified');
} else {
$something->category = $something_category->something_category_name;
}
...
// and so on, about four times
One solution I thought of was:
$classfications = array('type', 'category');
foreach ($classifications as $classification) {
$id_property = "something_{$classificiation}_id";
$something_classification = $this->db
->where("something_{$classification}_id", $something->$id_property)
->get("something_{$classification}s")
->row();
if(!$something_classification) {
$something->$classification = lang('data_not_specified');
} else {
$name_property = "something_{$classificiation}_name";
$something->$classification = $something_classification->$name_property;
}
}
Of course, reading that will probably result in someone having the fits, so what do I do about this? This is probably a very common problem but I can't name it so having trouble Googling it.
Are you looking for Inflection?
The biggest challenge with the code snippet in the question is that the classifications you have provided have different pluralized forms (e.g., "type" becomes "types", yet "category" becomes "categories"). In order to structure this data without inflection, you could create a nested array hash, e.g.,
$classifications = array(
'type' => array(
'plural' => 'something_types',
'id' => 'something_type_id',
),
// etc.
);
foreach ($classifications as $singular => $data) {
/*
* Produces:
* $singluar = 'type';
* $data['plural'] = 'something_types';
* $data['id'] = 'something_type_id';
*/
}
However, most of the PHP frameworks I have used include an Inflector class (or similar) to handle the nuances in language that make using singular and plural names together problematic (and would avoid the need for a nested data structure, as described above).
Have a look at CodeIgniter's Inflector Helper to get an idea of what this entails. If you are already using a framework (your use of a $db helper suggests you might be) then also be sure to see if it supports ORM, which handles this kind of scenario automatically.

Map Reduce To Get Most popular tags

I have a problem that I need some help on but I feel I'm close. It involves Lithium and MongoDB Code looks like this:
http://pastium.org/view/0403d3e4f560e3f790b32053c71d0f2b
$db = PopularTags::connection();
$map = new \MongoCode("function() {
if (!this.saved_terms) {
return;
}
for (index in this.saved_terms) {
emit(this.saved_terms[index], 1);
}
}");
$reduce = new \MongoCode("function(previous, current) {
var count = 0;
for (index in current) {
count += current[index];
}
return count;
}");
$metrics = $db->connection->command(array(
'mapreduce' => 'users',
'map' => $map,
'reduce' => $reduce,
'out' => 'terms'
));
$cursor = $db->connection->selectCollection($metrics['result'])->find()->limit(1);
print_r($cursor);
/**
User Data In Mongo
{
"_id" : ObjectId("4e789f954c734cc95b000012"),
"email" : "example#bob.com",
"saved_terms" : [
null,
[
"technology",
" apple",
" iphone"
],
[
"apple",
" water",
" beryy"
]
] }
**/
I am having a user savings terms they search on and then I am try to get the most populars terms
but I keep getting errors like :Uncaught exception 'Exception' with message 'MongoDB::__construct( invalid name '. does anyone have any idea how to do this or some direction?
First off I would not store this in the user object. MongoDb objects have an upper limit of 4/16MB (depending on version). Now this limit is normally not a problem, but when logging inline in one object you might be able to reach it. However a more real problem is that every time you need to act on these objects you need to load them into RAM and it becomes consuming. I dont think you want that on your user objects.
Secondly arrays in objects are not sortable and have other limitations that might come back to bite you later.
But, if you want to have it like this (low volume of searches should not be a problem really) you can solve this most easy by using a group query.
A group query is pretty much like a group query in sql, so its a slight trick as you need to group on something most objects share. (An active field on users maybe).
So, heres a working group example that will sum words used based on your structure.
Just put this method in your model and do MyModel::searchTermUsage() to get a Document object back.
public static function searchTermUsage() {
$reduce = 'function(obj, prev) {
obj.terms.forEach(function(terms) {
terms.forEach(function(term) {
if (!(term in prev)) prev[term] = 0;
prev[term]++;
});
});
}';
return static::all(array(
'initial' => new \stdclass,
'reduce' => $reduce,
'group' => 'common-value-key' // Change this
));
}
There is no protection against non-array types in the terms field (you had a null value in your example). I removed it for simplicity, its better to probably strip this before it ends up in the database.

Categories