Hi all! I've been working on adding some functions to my game that lean more on the simulation side. This is a farming game that actually ends up being harvestable items for the player! I finally got it working, so I wanted to share.
There are three functionalities here:
You will need the following images. I recommend itch.io. My images were either purchased or commissioned specifically for me and my game, and I cannot redistribute them.
I've attached my farmcontroller.php which goes into /controller/main/, and farmview.php which goes into /view/main/. My site is called Visit Riverton, so be sure to replace all URLs with your own or else it won't work!
First, create the table in your database that you'll have to pull plots from: {prefix}_users_plants with these columns:
pid is the plot ID, which every plot will receive. Plot IDs will not rewrite previous numbers; pids will continue to go up even after the crop has been harvested and the line no longer exists in the database.
Second, add a column in your {prefix}_users table:
You should now create your items in ACP and upload your images of your related items: 1 seed bag and the final harvested crop. In this example, we'll use carrots. I created the folder path /images/items/farming/Carrot (note the capital letter). In this same folder, include your images for 6 growth stages for crops.
Under that folder, I have my images:
The final harvested crop is carrot.png, lowercase to signal to myself that it's the final harvested item, but you do not have to keep it lowercase if you like things tidy. The filenames for the growth stages will need to follow a structure that can be repeated.
The tedious part here is repeating that process for every crop and creating the items in ACP. You are only creating two sets of items in the ACP: seed bags and the final harvested crop. Be sure to note item IDs of your seed bags and harvested crops.
Upload farm.php to your /model/domainmodel folder.
Next, you'll need to edit farmview.php to plug in your item IDs, item names, and image path. Change any mention of adopts_ to your prefix_.
At the top of the file is the seed name and ID matching:
Please note that the 'Carrot' name part is case-sensitive to your file structure. You can keep adding as many seeds and final harvested crop items as you'd like, using the same format of that line. The name as you enter it will be used in the $cropName variable used in a moment.
On Line 111, find the query for fetching seed names:
32, 33, 34, 35, ... are my IDs for my individual seed bags. 32 is a bag of carrot seeds. 33 is a bag of bell pepper seeds. You will need to change these IDs to match the seed bag items you've created. Once you match up the IDs, names, etc., in the farmview.php file with your item data, you should not have to touch the $imagePath on Line 134. You should be able to continually add new seeds and crops by adding to the $seedToHarvestMap above, as long as you maintain the file structure: /images/items/farming/{$cropName}/Plant_{$cropName}_GrowthStage{$plantStage}.png.
If you want to change that structure, be sure to include the $cropName and $plantStage variables in the URL itself on Line 134 or else this won't work.
Next, in your /model/domainmodel folder, open member.php.
Add this near the top under all the protected $variables:
Then, add these two functions after the getFriends() function (or around there if you've edited your member.php file before):
The last thing you have to do is attach some CSS to your website in order to render the plots correctly. I have this in my theme's style.css, but there are multiple places in the Admin Control Panel that you can include this. Wherever is easiest for you!
Finally, for the error and success messages, you can also include this into your CSS:
I hope this is helpful. I'm still learning PHP, so I may be able to help with some troubleshooting. Let me know if anything else needs to be explained or if I can help.
Optional "Just Planted" for New Plants:
I decided I wanted to change it so that newly planted crops don't give the "Water" button since they will get an error message anyway. Instead, I wanted it to say "Just Planted." If you want to do that as well, find the line if ($plantStage < 6), and you can replace it with this:
There are three functionalities here:
- Players have to have a Watering Can/required item in their inventory to access the farm, specified in Line 31.
- Players will have a Farm Stage attribute in their User table that will determine how many plots they have on their farm. You can either manually adjust this in the database or create additional functionality to upgrade their farm to the next stage for more plots.
- Players will be able to water their farm once a day, meaning they will be able to harvest after 6 days of continual watering. If this is too long, feel free to adjust so players can either water twice a day or reduce the amount of growth stages.
You will need the following images. I recommend itch.io. My images were either purchased or commissioned specifically for me and my game, and I cannot redistribute them.
- A mount of dirt or plot
- A bag of seeds
- 1st stage of growth
- 2nd stage of growth
- 3rd stage of growth
- 4th stage of growth
- 5th stage of growth
- 6th stage of growth
- Harvested crop
Caveat: I have not been able to figure out how to merge harvested items, so every time a player harvests a crop, each grouping of crop will be a separate line in their inventory, even if it's the same type of item. If you know how to do that, please let me know!

I've attached my farmcontroller.php which goes into /controller/main/, and farmview.php which goes into /view/main/. My site is called Visit Riverton, so be sure to replace all URLs with your own or else it won't work!
First, create the table in your database that you'll have to pull plots from: {prefix}_users_plants with these columns:
Name | Type | Collation | Null | Default | Extra |
---|---|---|---|---|---|
pid | int | No | None | AUTO_INCREMENT | |
uid | int | No | None | ||
crop | varchar(100) | utf8mb4_general_ci | Yes | NULL | |
wateredday | varchar(20) | utf8mb4_general_ci | No | 0 | |
cropstage | int | No | No | 0 | |
plantwatered | int | No | No | 0 |
pid is the plot ID, which every plot will receive. Plot IDs will not rewrite previous numbers; pids will continue to go up even after the crop has been harvested and the line no longer exists in the database.
Second, add a column in your {prefix}_users table:
Name | Type | Null | Default |
---|---|---|---|
farmstage | int | No | 0 |
You should now create your items in ACP and upload your images of your related items: 1 seed bag and the final harvested crop. In this example, we'll use carrots. I created the folder path /images/items/farming/Carrot (note the capital letter). In this same folder, include your images for 6 growth stages for crops.
Under that folder, I have my images:

The final harvested crop is carrot.png, lowercase to signal to myself that it's the final harvested item, but you do not have to keep it lowercase if you like things tidy. The filenames for the growth stages will need to follow a structure that can be repeated.
The tedious part here is repeating that process for every crop and creating the items in ACP. You are only creating two sets of items in the ACP: seed bags and the final harvested crop. Be sure to note item IDs of your seed bags and harvested crops.
Upload farm.php to your /model/domainmodel folder.
Next, you'll need to edit farmview.php to plug in your item IDs, item names, and image path. Change any mention of adopts_ to your prefix_.
At the top of the file is the seed name and ID matching:
PHP:
private $seedToHarvestMap = [
32 => ['id' => 17, 'name' => 'Carrot'], // 32 is the ID of the seed item players need to have. 17 is the ID of the final harvested crop item.
// Add more
];
Please note that the 'Carrot' name part is case-sensitive to your file structure. You can keep adding as many seeds and final harvested crop items as you'd like, using the same format of that line. The name as you enter it will be used in the $cropName variable used in a moment.
On Line 111, find the query for fetching seed names:
PHP:
$query = "SELECT {prefix}_inventory.item, {prefix}_inventory.quantity, {prefix}_items.itemname
FROM {prefix}_inventory
JOIN {prefix}_items ON {prefix}_inventory.item = {prefix}_items.id
WHERE {prefix}_inventory.owner = :owner AND {prefix}_inventory.item IN (32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42) AND {prefix}_inventory.quantity > 0";
$stmt = $mysidia->db->prepare($query);
$stmt->execute(["owner" => $uid]);
return $stmt->fetchAll();
}
32, 33, 34, 35, ... are my IDs for my individual seed bags. 32 is a bag of carrot seeds. 33 is a bag of bell pepper seeds. You will need to change these IDs to match the seed bag items you've created. Once you match up the IDs, names, etc., in the farmview.php file with your item data, you should not have to touch the $imagePath on Line 134. You should be able to continually add new seeds and crops by adding to the $seedToHarvestMap above, as long as you maintain the file structure: /images/items/farming/{$cropName}/Plant_{$cropName}_GrowthStage{$plantStage}.png.
If you want to change that structure, be sure to include the $cropName and $plantStage variables in the URL itself on Line 134 or else this won't work.
Next, in your /model/domainmodel folder, open member.php.
Add this near the top under all the protected $variables:
PHP:
protected $farmstage;
Then, add these two functions after the getFriends() function (or around there if you've edited your member.php file before):
PHP:
public function setFarmStage($farmstage){
$this->farmstage = $farmstage;
}
public function getFarmStage(){
return $this->farmstage;
}
The last thing you have to do is attach some CSS to your website in order to render the plots correctly. I have this in my theme's style.css, but there are multiple places in the Admin Control Panel that you can include this. Wherever is easiest for you!
CSS:
.farmplots {
display: flex;
flex-flow: row wrap;
width: 95%;
max-width: inherit;
gap: 10px;
}
.singleplot {
width: 150px;
}
.singleplot img {
width: 150px;
}
@media (max-width: 800px) {
.farmplots {
flex-direction: column;
}
}
Finally, for the error and success messages, you can also include this into your CSS:
CSS:
.errormessage {
position: relative;
top: 0;
background-color: #FFCCCC;
opacity: 0.8;
color: #8B0000;
margin: 0 auto;
font-size: 110%;
width: 50%;
text-align: center;
z-index: 999;
}
.successmessage {
position: relative;
top: 0;
background-color: #a9f971;
opacity: 0.8;
color: #028f1e;
margin: 0 auto;
font-size: 110%;
width: 50%;
text-align: center;
z-index: 999;
}
I hope this is helpful. I'm still learning PHP, so I may be able to help with some troubleshooting. Let me know if anything else needs to be explained or if I can help.
Optional "Just Planted" for New Plants:
I decided I wanted to change it so that newly planted crops don't give the "Water" button since they will get an error message anyway. Instead, I wanted it to say "Just Planted." If you want to do that as well, find the line if ($plantStage < 6), and you can replace it with this:
PHP:
if ($plantStage < 6) {
if (($plantWatered == 1) && $wateredDay == $currentDay) {
$action = "Watered";
} elseif ($plantStage == 1 && $plantWatered == 0 && $wateredDay == $currentDay) { // Handle newly planted seeds
$action = "Just Planted";
} else {
$action = "Water";
}
$this->renderActionForm($document, $action, $plot['pid']);
} else {
$this->renderActionForm($document, "Harvest", $plot['pid']);
}
} else {
$document->add(new Comment("<div class='singleplot'>"));
$document->add(new Comment("<img src='images/items/farming/dirtmound.png' alt='Empty Plot'>"));
$this->renderPlantForm($document, $seedsAvailable, $plotNumber);
}
$document->add(new Comment("</div>"));
}
Attachments
Last edited: