I am having a play around with codeigniter and trying to get my head around the active record system and such like.
I have set up a couple of tables and am attempting to run a join on them, as such:
function GetOrganisationsAndBuildingDetails()
{
$this->db->select('organisations.organisation_name,
organisations.organisation_id,
buildings.building_name,
buildings.address1');
$this->db->from('organisations')->join('buildings', 'buildings.organisation_id = organisations.organisation_id');
$query = $this->db->get();
return $query->result();
}
In my database i have one organisation with two related buildings. The above query returns two objects (one for each building) - however, the organisation is duplicated.
stdClass Object (
[organisation_name] => This is an example org
[organisation_id] => 1
[building_name] => test building
[address1] => 123456 )
stdClass Object (
[organisation_name] => This is an example org
[organisation_id] => 1
[building_name] => teeeest building
[address1] => 123456 )
I suppose I was expecting something along the lines of one return object with a series of nested objects for related buildings. Is this possible?
If not, is their a recommend way of arranging the return data so I can easily loop through it in the view? (foreach org, foreach building etc etc).
Apologies if I'm being a little dense here. Im coming from .net and (linq to SQL in particular) where this stuff is a little different)
The query will inevitably return duplicate data as you say, you have to organize them after you get the result like this
$buildings = array();
foreach ( $result_object as $organization ) {
$building_data = array(
'building_name' => $organization->building_name,
'address' => $organization->address,
);
$buildings[$organization->organization_name][] = $building_data;
}
this way organizations will be "compacted" in the first key of the multidimensional array, and one level deeper you will have info about the buildings. Hope this helps.
Related
This is my first post, I do a lot of reading here, so hopefully I avoid embarrassing myself. I've done a lot of searching on the topic, with little results, given that I am new to PHP it doesn't help either, and documentation is sparse on the topic.
The Discord API for PHP is limited to certain pieces of data which you can request, what I am attempting to do is: fetch the members, check what roles they have, and if they have it, count them.
Currently with the API you can count all members within a guild, however you cannot count all members within a guild with a specific role. My end conclusion is to loop through the snowflake and handle the comparisons myself.
This code returns the snowflake (up to 1000) for a guild:
<?php
$json_options = [
"http" => [
"method" => "GET",
"header" => "Authorization: Bot TOKENREDACTED"
]
];
$json_context = stream_context_create($json_options);
$json_get = file_get_contents('https://discordapp.com/api/guilds/GUILDIDREDACTED/members?limit=1000', false, $json_context);
$json_decode = json_decode($json_get, true);
print_r($json_decode);
?>
And the snowflake I am trying to loop through looks like this:
Array
(
[0] => Array
(
[nick] => nickname
[user] => Array
(
[username] => username
[discriminator] => 7697
[id] => 123456789012345
[avatar] => 32ad726b873445fff9145e47144a9465
)
[roles] => Array
(
[0] => 123456789012345678
[1] => 123456789012345678
)
[mute] =>
[deaf] =>
[joined_at] => 2018-05-18T07:22:49.562000+00:00
)
[1] => Array (annnd repeat for the next member)
As you can see the snowflake is quite complicated in terms of arrays.
What I am trying to do here is loop through each array entry ([0],[1],[2] etc.) then to the roles. If the [user] has the role ID 123456789012345678 (for example) then add that member to a count to print, if there's no match then it'll simply ignore that and move onto the next one. But I'm not really sure where to start with this. Any help or direction is appreciated, thank you.
You can use array-filter and get only the element you need with in-array and then count them using simple count method. Consider the following:
$arr = array_filter($json_decode, function($e) {return in_array("123456789012345678", $e['roles']);});
echo count($arr);
If the your "RoleId" is dynamic you can do:
$myRole = "123456789012345678";
$arr = array_filter($json_decode, function($e) use ($myRole) {return in_array($myRole, $e['roles']);});
If you also want to display the username you can do:
foreach($arr as $e) {echo $e['user']['username'];}
This is probably really, really bad practice, especially for a first post. #wesley murch thank you very much for the direction, I got it now. Also, feel free to reply so I can mark you as the answer. Here is the working code which I would like to share with everyone, and a following explanation of what the code does:
<?php
$json_options = [
"http" => [
"method" => "GET",
"header" => "Authorization: Bot Your-Discord-Bot-Token-Here"
]
];
$json_context = stream_context_create($json_options);
$json_get = file_get_contents('https://discordapp.com/api/guilds/your-guild-id-here/members?limit=1000', false, $json_context);
print_r(substr_count ( $json_get ,'Role-Id-To-Look-For'));
?>
This code will query the API for the snowflake, it then converts that snowflake to a string, and counts the occurrences of which that role is contained in the snowflake. In this case, I have 12 people with this role, I can confirm that it successfully returned a value of 12. In this usage case it wasn't necessarily a matter of parsing the array, I was able to just check the snowflake as a string for the ID I was looking for. This usage case is limited in the fact that it won't necessarily return any details of the members which have the role, so I wouldn't say it completely covers every single usage case.
We are using the Zend Framework in our company and thus we're using Zend_Db_Select.
Now we are building a query with it which is then (pre fetch) passed to a function.
The query is built as follows:
$select = $this->_selectAll()
->setIntegrityCheck(false)
->joinLeft('shop', $conShop, $colShop)
->joinLeft('ptool', $conPtool, $colPtool)
->where('ptool.product_id > 0')
->where('ptool.product_is_from_shop = 0')
;
Where $conShop and $colShop are something like:
$colShop = array('shop_id','shop_channel');
$conShop = "shop.shop_id = ptool.shop_id";
In a new method I want to get all joined tables and their columns that are going to be selected. So the $select gets passed to the method and now I would like to get something like this:
Array
(
['shop'] => Array
(
[0] => 'shop_id',
[1] => 'shop_channel',
...
),
['ptool'] => Array
(
[0] => 'shop_id',
[1] => 'ptool_id',
...
),
...
)
It would be nice if I can get this pre fetch.
The background is that I want to sort by shop_id for example and this table name is used in two joined tables. If I do something like "ORDER BY shop_id" I'd get the error that the column is ambiguous. That's why I need to know which columns belong to which table so that I can do something like "ORDER BY shop.shop_id"
Hope you can help me. Thanks! :)
I'm working on a PHP script to hold a lot of information.
Lets try to explain our situation!
I have actually 33 different stations.
For each of that 33 stations I have 5 different categories.
And for each of that 33 stations with each 5 different categories i have 37 different values per category.
Do I need an 2d of 3d array for store this information in it ?
Thanks you!
Something like this will work, just add more data as needed:
$station_array =
array(
'station1' => array(
'cat1' => array ('val1','val2','val3'),
'cat2' => array ('val1','val2','val3'),
'cat3' => array ('val1','val2','val3')
),
'station2' => array (
'cat1' => array ('val1','val2','val3'),
'cat2' => array ('val1','val2','val3'),
'cat3' => array ('val1','val2','val3')
),
'station3' => array (
'cat1' => array ('val1','val2','val3'),
'cat2' => array ('val1','val2','val3'),
'cat3' => array ('val1','val2','val3')
)
);
Sounds like a job for a relational database!
But you're correct in your initial assumption. You will need a 3-dimensional array to hold your information because your data has 3 tiers: the stations, the categories, and the values.
A php array will be fine for this
$MyArray = array('Station1' => array('Category1' =>
array('Value1'=> 1000,'Value2'=> 1001),
'Category2' => array('Value1' => 2332)), etc...
'Station2' => array('Category1' =>
array('Value1'=> 1000,'Value2'=> 1001),
'Category2' => array('Value1' => 2332)), etc
etc
);
Once you pass more than two dimensions in an associative array, it's good to start considering using objects to store your information. Objects make it a lot easier to understand how things are organized, they can enforce validation restrictions on your data (make sure it's in the form it should be), and you can call functions on the data to manipulate it (instead of having random external functions manipulating your entire array). An example would be:
class CategoryValue {
var $val; // your value
function __construct($val) {
$this->val = $val;
}
}
class Category {
var $values = array(); // an array of CategoryValue objects
function addValue(CategoryValue $val) {
$this->values[] = $val;
}
}
class Station {
var $categories = array(); // an array of Category objects
function addCategory(Category $category) {
$this->categories[] = $category;
}
}
well, all depends on how you want to acheive, if you dont need to loop through the values, but you just want to store data and alway know whay you want to get, you could use hashes for that, the table would look like:
$data = array(
md5('StationX'.'CategoryY'.'PropertyZ') => 'ValueU',
md5('StationA'.'CategoryB'.'PropertyC') => 'ValueQ'
);
This way you can get the data right away and dont have to bother to check if you initialised CategoryB array for StationA when you want to add value for PropertyZ
php stores associative arrays as hastables technically
... thats all if you really insist on not using databases ;)
This is my first question here, so please try to be patient with me :)
I've stumbled upon a weird behavior populating an object.
I started to convert the objectQuery::create()-> ... ->find() methods used in my project to $c = new Criteria(), $c-> ... objectPeer::doSelect($c) since I've been told Queries shouldn't be used when criteria can be.
I have a function, that returns all the prices of items from the shop. Or at least did. The thing that I cannot figure out is this:
the old code:
static public function shopGetPrices($id){
$prices = itemPriceQuery::create()->
addJoin(itemPricePeer::ITEM_ID, itemPeer::ID, Criteria::LEFT_JOIN)->
addJoin(itemPeer::CATEGORY_ID, categoryPeer::ID, Criteria::LEFT_JOIN)->
addJoin(categoryPeer::SHOP_ID, shopPeer::ID, Criteria::LEFT_JOIN)->
add(shopPeer::ID, $id)->find();
return $prices;
}
returns correctly populated PropelObjectCollection object, through which i can go with foreach, and get/set the itemPrice objects and attributes i need.
now, the new code:
static public function shopGetPrices($id){
$c = new Criteria();
$c->addJoin(itemPricePeer::ITEM_ID, itemPeer::ID, Criteria::LEFT_JOIN)->
addJoin(itemPeer::CATEGORY_ID, categoryPeer::ID, Criteria::LEFT_JOIN)->
addJoin(categoryPeer::SHOP_ID, shopPeer::ID, Criteria::LEFT_JOIN)->
add(shopPeer::ID, $id);
return self::DoSelect($c);
}
returns an array of itemPrice objects, but they are populated with item values related to itemPrice objects through join. that means : when I call print_r(self::DoSelect($c)); it prints
Array
(
[0] => ItemPrice Object
(
[startCopy:protected] =>
[id:protected] => 47 <- id of joined item
[item_id:protected] => 9 <-foreign key to category object of joined item
[price:protected] => 0
[unit:protected] => Axe <- name of item, not unit (unit is like 'golden', 'iron', 'wood' or whatever )
[active:protected] =>
[collItemsOrder:protected] =>
[collItemsOrderPartial:protected] =>
[alreadyInSave:protected] =>
[alreadyInValidation:protected] =>
[polozkyObjednavkasScheduledForDeletion:protected] =>
[prisadyPolozkyObjednavkasScheduledForDeletion:protected] =>
[validationFailures:protected] => Array()
[_new:protected] =>
[_deleted:protected] =>
[modifiedColumns:protected] => Array()
[virtualColumns:protected] => Array()
)
[1] => ItemPrice Object
(
...and so on.
There is probably some crucial difference between criteria and query object, that I'm missing. I searched on Google, StackOverflow, and who knows where, but I didn't find anything resembling a solution to this.
This guy/gal had a vaguely similar problem, but I didn't use addSelectColumn with my criteria, so it's been another dead end for me.
Can anyone please point me in the right direction?
I found the problem. It was that I had overriden method do select in itemPricePeer class
public static function doSelect(Criteria $criteria, PropelPDO $con = null){
$critcopy = clone $criteria;
$critcopy->add(self::ACTIVE, 1);
return self::populateObjects(itemPeer::doSelectStmt($critcopy, $con));
}
I switched self/itemPricePeer with itemPeer in populateObjects arguments. silly me :-/ Thanks for your responses anyway j0k.
I have a simple query like this
SELECT hometeam.name AS hometeamName, hometeam.shortname AS hometeamShortName,
roadteam.name AS roadteamName, roadteam.shortname AS roadteamShortName,
smatch.startdate
FROM smatch
JOIN team hometeam
ON smatch.hometeamid = hometeam.uid
JOIN team roadteam
ON smatch.roadteamid = roadteam.uid
which be default returns a one dimensional array, like this:
array(5) {
["homeTeamName"] => "Brasil"
["homeTeamShortName"] => "BRA"
["roadTeamName"] => "Norway"
["roadTeamShortName"]=> "NOR"
["startdate"]=> "1309709700"
}
Question is, is there a mysql-way to let the result be a nested array, with a structure like the following?
result =>
hometeam =>
name
shortname
roadteam =>
name
shortname
startdate
And if not, is there a (php) post processing best practice to do this conversion?
Many thanks,
Robson
I don't think there's a way to directly get the result you want, but to generate that array after the query shouldn't be hard.
Something like this?
foreach($rows as $row) {
$resultArray[] = array(
'hometeam' => array(
'name' => $row['homeTeamName'],
'shortname' => $row['homeTeamShortName']
),
'roadteam' => array(
'name' => $row['roadTeamName'],
'shortname' => $row['roadTeamShortName']
),
'startdate' => $row['startdate']
);
}
MySQL (or any database) has no concept of arrays.
The only way I can think of is that you'd need to do it in a Stored Procedure and serialise the result in some way - essentially creating a serialised string... wich you'd then need to re-construct the array from.
However, would be better doing this in PHP to be honest, the gain from doing it in an SP will be minimal. Will be more efficient to query the main and then query within using loops PHP-side.
You have to fetch the result in PDO::FETCH_CLASS mode.
by specifying the __set()-method respectively you can store the result-field-data how ever you like.
This class should also extend ArrayAccess so you can access it like an array or have it return one.