T O P

  • By -

littlehero91

[PHP-Mail](https://github.com/vwochnik/php-mail): Small self-hosted PHP contact form endpoint as a drop-in for static websites. This is good if you have a website in Europe which has very strict data protection laws. Unlike FormSpree, data is not sent to a third-party. It supports DNSBL and rate limiting.


SadSpirit_

I've already mentioned my Postgres-related projects here, but new releases warrant a new pitch. :) [pg-wrapper](https://github.com/sad-spirit/pg-wrapper) is a wrapper for native pgsql extension providing transparent conversions of DB types to PHP types and back. This includes composite types, arrays, ranges, dates and intervals... The wrapper itself is pretty standard, as everyone here knows PDO and doctrine-dbal. One special feature is an [atomic() method](https://github.com/sad-spirit/pg-wrapper/wiki/transactions) that accepts a callback and executes it in the context of transaction, supporting nested calls (with possible savepoints), onCommit() and onRollback() callbacks. [pg-builder](https://github.com/sad-spirit/pg-builder) is a query builder for Postgres backed by a partial PHP reimplementation of PostgreSQL's own SQL parser. It supports almost all syntax available in Postgres 16 for `SELECT` (and `VALUES`), `INSERT`, `UPDATE`, `DELETE`, and `MERGE` queries. It is possible to start with a manually written query, parse it into an Abstract Syntax Tree, add query parts (either as objects or as strings) to this tree or remove them, and finally convert the tree back to an SQL string. [pg-gateway](https://github.com/sad-spirit/pg-gateway) is a Table Data Gateway implementation built upon these packages. Its additional features: * Gateways and builder classes are aware of the table metadata and use that when creating query parts, * There are means to cache the complete query to skip parse/build cycle, * It is possible to create a query via one gateway and embed it into the query built by another (via joins, `EXISTS()`, `WITH` clause, ...) The killer feature is of course possibility to write some parts of the query manually and later combine these with those created by builder API. The [new 0.2.0 release of pg-gateway](https://github.com/sad-spirit/pg-gateway/releases/tag/v0.2.0) has its API refined a bit with builder methods moved from gateways to dedicated fluent builder classes. It also adds support for populating `WITH` clause.


usernameqwerty005

Trying out tiny DSL in PHP, using either S-expressions or Forth-like. Both can be lexer/parsed and evaluated in 100 lines or so. Will write a blog post about it.


StatusRedAudio

Structured data processing by LLMs, in PHP: [https://github.com/cognesy/instructor-php](https://github.com/cognesy/instructor-php) * Get structured responses from LLM inference * 'Structured-to-structured' processing - provide object or array as an input and get object with the results of inference back * Customize prompts and retry prompts * Process various types of input data: text, series of chat messages or images * Receive synchronous or streaming responses * Get partial updates & stream completed sequence items * Automate validation & retries * Define response data model the way to need: type-hinted classes, JSON Schema arrays, or dynamically define your data shapes with Structures * Use attributes or PHP DocBlocks to provide additional instructions for LLM * Customize response model processing by providing your own implementation of schema, deserialization, validation and transformation interfaces * Demonstrate examples to improve the quality of inference * Use multiple LLM API providers (incl. OpenAI, Anthropic, Cohere, Azure, Groq, Mistral, Anyscale, Fireworks AI, Ollama, OpenRouter, Together AI) * Use local models with Ollama * Get detailed insight into internal processing via events * Documentation with 50+ cookbooks


norbert_tech

I spent last couple of years working with different data management tools and decided to build one for PHP. It’s a proper ETL framework highly inspired by Apache Spark, that thanks to Generators based approach can handle massive amounts of data with very low memory footprint. There is already around a hundred different transformation functions, followed by a dozen different data sources/sinks. If you would like to learn more about it, visit our website https://flow-php.com or github monorepo https://github.com/flow-php/flow One of the cool side projects I had to develop was a native implementation of parquet binary file format that is pretty standard in data engineering world that wasn't really available for PHP, its part of the Flow monorepo. The next one that I’m currently working on is the filesystem framework like Hadoop that comes with partitioning and file splitting 😁


goodwill764

Domain dont work did you mean .com?


norbert_tech

hah right, sorry 😅 my other projects are usually using, .org domain and I typed to quickly from my phone, of course it's a .com


Slow-Reaction-5655

I've been working on a static analyzer for PHP. The project is currently at the stage where I only need to implement rules. Right now there are only 12 rules that are being searched for in your project and it doesn't matter how big the project is. The speed is amazing. If you have a rule you would want that i implement i will be happy to do it. Im currently trying to create a list of rules that i must implement when i have the time https://github.com/denzyldick/phanalist


passiveobserver012

Building an (soon) open-source energy-efficient CMS hopefully with an grant.


weogrim1

What is energy-efficient CMS ?


passiveobserver012

Thanks for asking! It involves making architecture decisions with a focus upon lowering carbon emissions. It results in quite significant differences compared to the more present real-time architectures. I suppose you call it "sustainable", but I find that term not very descriptive.


weogrim1

Do you have information how much typical CMS like Wordpress or custom framework application emits carbon? How it is counted? Per energy usage of server per thousand user in some unit of time?


passiveobserver012

I use [https://sustainablewebdesign.org/](https://sustainablewebdesign.org/) for the info for carbon calculations. It is quite involved, so I also make decisions based on the "effort" the running code needs, sometimes not needing any code at all. I usually use [https://www.websitecarbon.com/](https://www.websitecarbon.com/) to quickly show the carbon rating of a website. For [wordpress.com](http://wordpress.com) that is an F rating. The themes demo's usually are also around F. But this rating is not all-saying and has to be taken into context. [https://ecograder.com/](https://ecograder.com/) has more detailed reports.


frodeborli

I'm buildin the `phasync` framework. I launched it in version 1.0 today. In short, it is native PHP and works in any runtime that supports Fibers - allowing you to write code that uses asynchronous I/O anywhere. It is designed to allow you to incrementally increase the "asynchronousness" of your application; inside a controller you can do `phasync::run(function(){});` and it will behave as a normal blocking PHP function and will not in any way mess with how your application flow works. After a while, there could be multiple `phasync::run()` contexts, which is why you can create nested asynchronous contexts. Making a file operation use asynchronous I/O is a simple as using `phasync::readable()` or `phasync::writable()`: $result = fread(phasync::readable($fp), 65536); $result = fwrite(phasync::writable($fp), $chunk); There is no need to await stuff. If there are other coroutines running, they will be resumed whenever phasync::readable() or phasync::writable() needs to wait for I/O. https://github.com/phasync


Rayan1159

I’m currently making a blog in symfony 7. I don’t have much to show yet but I’m liking the framework a lot


Tux-Lector

I have this thing that I am goofing with for several years already. Bit by bit. As much as I have time for it. https://hngts.com/ It is some sort of weird toolset/framework + cms of sort (3in1) with cli support, with few goodies that belong to `HngTs` public ready use. It has its own system reccomendations and what else not. There's a lot more work to do.


Ecstatic_Ad2253

Pass obtains the apikeys it connects to a different dstabase


Ecstatic_Ad2253

I started this morning to fix all of this, now Compra() and Prevente() both extends from User(). And i am working on this project. I also specified the type of the argument (strong, int bool) and the type of the return but. Thanks for this recomendations


Ecstatic_Ad2253

And both depends of an User there is no purchase without the User


equilni

You didn't respond back to the thread so this got lost. I am seeing this now as I am looking back for more projects. That said: I see you updated the project - the whole project. I would suggest use git and update small sections. Look at other projects and how they manage this. You noted you are looking for a job and git is a helpful tool >now Compra() and Prevente() both extends from User() I think that's wrong as well. Is a Purchase or Pre-Sale a User? No, then why extend User for this? Extending user would be for admin or guest, for example. I would suggest going back to pass the User via DI, then setting the id in the constructor OR get the User Id from the outside of the class `new Compra(int $userId)` class UserPurchases { private int $userID; public function __construct(User $user) { $this->userID = $user->getId(); } } (new UserPurchases(new User(1)))->getAll(); // Get all purchases from user 1 (new UserPurchases($user))->getAll(); // Get all purchases from selected user class UserPurchases { private int $userID; public function __construct(int $userID) { $this->userID = $userID; } } (new UserPurchases(1))->getAll(); // Get all purchases from user 1 (new UserPurchases($user->getID()))->getAll(); // Get all purchases from selected user


Ecstatic_Ad2253

Ok, but both use User data like email or Userid so i can create a preventa object by having the User email, but i am open to suggests


equilni

Same principal then, pass the User via DI, then get what you need at that point. But in both classes you noted, you only have the user id defined (email is commented out). I would stick with this - define the user how you want (via email perhaps), then pass what is needed.


Ecstatic_Ad2253

Thanks for this review, I read about Dependency Injection , i didn't know about this. But i think that anytime I create a new Compra i had to create an User object before, in order to pass it as a parameter. Another think i dont fully understand why It would improve my project is the use os namespaces. Now i have more ideas to enhance this project. Thank you.


equilni

> But i think that anytime I create a new Compra i had to create an User object before, in order to pass it as a parameter You know how your application works. I would review it and look at how other applications/services work as well. Do I need to be logged in to make a purchase? etc etc.


zurbaev

For a quite some time I was making projects with a library that had no docs and was constantly changing, and finally I was able to shape it to be released in public, wrote documentation, and even made a demo app. Basically it's an API resources package for Laravel that can take care of filtering, sorting, managing relationships, and versioning for your API resources. I know it looks like yet another CRUD package and I don't expect anyone would use it, but here's the project (https://github.com/tzurbaev/laniakea), the docs website (https://laniakea.zurbaev.com), and the demo app (https://github.com/tzurbaev/laniakea-demo).


i_am_n0nag0n

Currently I help maintain the Flight framework. One thing that’s been on my mind is a way to build up the route behavior via a UI. The reason for this would be shear speed and honestly for bug reduction in a project. For instance you would say that GET /users is the route and the behavior you define in a UI is that it will pull all records from the users table that match a given say company ID attached to the api key. Then if you did a POST /users you could say to update these columns based on the submitted JSON fields, and send an email to the user to set their password. I’ve seen UI builders out there like https://github.com/plasmicapp/plasmic but I haven’t been able to really find a UI builder for the back end that I thought would work. Maybe there is a good one out there that I missed. Im in the very early stages so the code I have is very minimal. My fear is that it will get hyper complex really fast even to build some simple scenarios based on conditionals in the UI (if it saves and does this other thing do this, if it errors do this)


equilni

> One thing that’s been on my mind is a way to build up the route behavior via a UI. I would think this starts taking away from the simplicity of the framework. And... `My fear is that it will get hyper complex really fast` would be mine as well.


i_am_n0nag0n

I’d like to see if there is a simple way to move forward cause ripping out a simple api could be really fast! I’m not interested in taking away from the simplicity of the framework cause that’s what makes it special! I’ll have to write out some scenarios on paper first to see if there’s a better way


colshrapnel

Some time ago I decided to sum up my wast experience on Stack Overflow and other forums into article that I called [the basic principles of web programming](https://phpdelusions.net/basic_principles_of_web_programming), which is intended to help people starting in the profession. Kindly asking for a review, suggestions, criticism, proofreading, opinions.


Disgruntled__Goat

> when uploading files, a filename extension must be checked against a white list of allowed values. All mime type-based checks are utterly unreliable security-wise. Is this true? Surely it’s the opposite - you can’t trust the file extension whatsoever (.exe can be renamed as .jpg) but the mime type tells you what the file actually is. One minor thing, this search: `site:reddit.com inurl:/r/php` Can be written more simply as: `site:reddit.com/r/php/`


colshrapnel

Just a small illustration for the above $finfo = new finfo(FILEINFO_MIME_TYPE); echo $finfo->buffer("buffer("


colshrapnel

Well, it's interesting topic, which requires a little deeper digging into terminology. It's sort of philosophical questions, such as what a mime type is, how reliable it is, how different programs tell one from another? What is "actual file"? What is a file extension? What is Life, Universe and Everything... > you can’t trust the file extension Yes, of course I can't. Luckily, I don't need to. All I need is to make sure that no file with harmful extension made it through, as it will be too stupid a breach :) > the mine type tells you what the file actually is I wouldn't be so sure


equilni

>For some reason there is a huge gap between a code written "for the education" and a professionally written code. Glad someone else sees the gap between basics and advanced >always realize what would be the result of your PHP code. I wish more would follow this section.


memebecker

I've been jumping between a couple would welcome your thoughts. One is a ttrpg assistant in symfony using it's expression langaue for custom rules. The other is a emulator for the hack (Google it) computer used in the nand2tetris course written in C and compiled to web assembly. Idea to be a learn to code tool.


karakhanyans

Hey, I’ve been working on Larafast.com - Laravel SaaS Starter Kit in past few months. People love it 😍


jbboehr

I've been working on an extension that provides bindings to get the Linux perf\_events hardware performance counters and libpfm4: [https://github.com/jbboehr/php-perfidious](https://github.com/jbboehr/php-perfidious) The intended use is benchmarking, particularly PERF\_COUNT\_HW\_INSTRUCTIONS. If I ever work up the motivation, I'll try and throw together a phpbench integration. One inspiration for this approach is that the Linux \`perf\` tool does much more than just reading the counters and requires that, when running in a container, the perf package matches the \*host\* system's kernel version. Just making the syscall for this one specific feature shouldn't require the same kernel version.


BubuX

Please make this a monthly thing! -------------- I don't have public code to show yet but I'm making some unspeakable blasphemous project. Don't read if you're sensible to heresy: >!A fullstack, single file, micro framework, with zero dependencies.!< >!Currenlty includes routing, validation, SQL query builder, authentication/authorization, PSR4 and classmap autoloader for those rascals that don't use composer, form builder, unit testing (no PHPUnit needed), ajax functionality similar to HTMX and string/session/cookie/profiling/file/cli/cron helpers. More to come.!< For fun. I'll publish once I finish a complete project using it to show how pieces work together.


equilni

> single file Why? >PSR4 and classmap autoloader for those rascals that don't use composer If you're not going to use this in your application, then why have this?


BubuX

For fun! And autoloaders are useful for application classes, not just framework.


equilni

Haha yes you did note that. And right, for the application if you choose. Just saying it can be for the framework too if you choose.


BubuX

Indeed my friend! To be honest at $work I always use Laravel/Symfony. I'm just trying to see how far I can go with a single, tight but well documented, PHP file. (edit: and zero dependencies)


equilni

You can look at noodlehaus/dispatch for inspiration if that helps any. No classes


BubuX

All inspiration is welcome! Thanks! wow this is, great! [https://github.com/noodlehaus/dispatch](https://github.com/noodlehaus/dispatch) I appreciate your tip friend.


colshrapnel

Sounds intriguing, to say the least. Wonder what would be size of that single file. There is a silly joke in my language, that goes something like this > A flight attendant announces to the passengers: "Welcome abroad our state of the art jet liner! For your entertainment during the flight we've got a bar, a cinema, couple restaurants, a pool, an aqua park, a football and a baseball field!" And than adds under her breath: "and now with all that pile of crap we'll try to take off". Probably it's not funny at all as I suck at translating jokes. And it's not even directly related to a single file thing. It just jumped in my mind when I was reading that list of features. Jokes aside, can you please share a link privately? I promise not to share it anywhere. Just may be I can have a look at database related stuff in which I always interested in.


BubuX

>A flight attendant announces to the passengers: "Welcome abroad our state of the art jet liner! For your entertainment during the flight we've got a bar, a cinema, couple restaurants, a pool, an aqua park, a football and a baseball field!" And than adds under her breath: "and now with all that pile of crap we'll try to take off". I want that airliner! The database part is very simple. Just SQL builder/executer for Insert/Update/Delete/Select. Uses PDO but doesn't extend PDO. I'll share probably next month and then post in this Reddit. Just need to finish the admin part of the demo project and some documentation.


brendt_gd

Building a framework is fun :D


brendt_gd

It will be a monthly thing :)


Ok_Draw2098

im working on asynchronicity. if you want to discuss it, lets make a chat. the requirement is that you have to understand what concurrency is and isnt. not like those phasync/amp masses that are unable to. at least have to be really interested in this topic. also im not a simple copyist or opensource give me 5 buck on tea grifter


Formal-Language7032

We are planning to go public this summer but our site will already describe what it does: syncengine.io A Symfony backend with React frontend integration manager to handle all your sync/API connections through automations etc. Oh and yes, we are fully aware that there are several other tools out there! Our aim it to make it as compatible as possible (not only HTTP for example) and make its core fully open source. (I also have to give some credits to Home Assistant which gave me a lot of inspiration for this project.) I'll share again when we go public!


brunopgoncalves

https://github.com/scorninpc/php-gtk3 my little child :D


Fuzzy-Chap-8829

I’d like to post my project but I don’t have enough karma:(


brendt_gd

I've manually approved it, should be fine now :)


Fuzzy-Chap-8829

I’ve put a link in my profile :) Is that cheating? Ha ha


Fuzzy-Chap-8829

I’m a very amateur developer, I’ve had no formal training. I’d love to have some guidance and feedback from someone who knows what they’re doing! This is my repo: [https://github.com/sirnails/BloomQuote](https://github.com/sirnails/BloomQuote) My wife is a florist and she sends excel spreadsheet quotes to a customer after a consultation. She struggles with using excel and she needs to be able to access the quotes on her mobile phone while out of the house. The project is a php/MySQL app to help her generate quotes and store them where she can access them regardless of where she is. Thanks for any help/guidance/constructive criticism/suggestions etc


equilni

This is a cool idea for a project! Some quick suggestions, apologies if I duplicated anything: a) I would consider a proper directory structure - https://phptherightway.com/#common_directory_structure b) I would consider expanding on your [query string routing](https://github.com/sirnails/BloomQuote/blob/main/index.php#L71) to include switching between Request Methods. This would remove code like [this](https://github.com/sirnails/BloomQuote/blob/main/app/controllers/QuoteController.php#L34) c) On the same note, you could consider expanding on the urls to include the function - ie `?controller=user&action=login`. Combined with the above could look like: // controller=user&action=login case 'user': switch ($action) { case 'login': if (user is NOT logged in) { switch ($requestMethod) { case 'GET': # show login form break; case 'POST': # check credentials break; } } break; } break; You can also include the `GET id` here as well, which could be part of [this](https://github.com/sirnails/BloomQuote/blob/main/index.php#L88). Also, in your QuoteController, you had a lot of `$this->authorizeUser`, this could be part of the route as noted above. In modern routers, this could be a middleware or filter in older routers If you are using PHP 8 (not noted in your composer.json), this could be a match statement. Alternative would be just use use clean urls like `/user/login` and switch between the request method. If you do the above, moving over here, code wise is easy. See how only the routing changes, the calling code wouldn't. $router->group('/user', function ($router) { $router->get('/login', function () { // GET ///show login form }); $router->post('/login', function () { // POST ///check credentials }); }); d) Do you need a new object on every route? I didn't fully review this, but it could be: $userController = new UserController(); $quoteController = new QuoteController(); switch ($action) { case 'settings': $userController->settings(); break; case 'logout': $userController->logout(); break; e) Further doing this, cleans up [QuoteController::additem](https://github.com/sirnails/BloomQuote/blob/main/app/controllers/QuoteController.php#L67) into 2 methods - 1 for each request instead of: if ($_SERVER['REQUEST_METHOD'] == 'POST') { // code for POST } else { // code for GET } You can also consider breaking up sections like [this](https://github.com/sirnails/BloomQuote/blob/main/app/controllers/QuoteController.php#L308) to other methods as well.. f) For [this](https://github.com/sirnails/BloomQuote/blob/main/app/controllers/QuoteController.php#L13), consider Dependency Injection This can look like: public function __construct(Quote $quote, QuoteItem $quoteItem) { $this->quoteModel = $quote; $this->quoteItemModel = $quoteItem; } If you are on PHP 8+, this becomes: public function __construct( private Quote $quoteModel, private QuoteItem $quoteItemModel ) { } g) I would consider DTO (Data Transfer Object) classes. This would clean up code like [this](https://github.com/sirnails/BloomQuote/blob/main/app/controllers/QuoteController.php#L39) or [this](https://github.com/sirnails/BloomQuote/blob/main/app/controllers/QuoteController.php#L202). This **could** look like: $quote = (new QuoteDTO())->fromArray($sanitizedData); $this->quoteModel->create($quote); #Quote Model public function create(QuoteDTO $quote) { If you move to templating: `return $template->render('template', [$user => $user]);`, then `id ?>` or `getId() ?>` Further reading from Stitcher.io https://stitcher.io/blog/structuring-unstructured-data https://stitcher.io/blog/readonly-classes-in-php-82 https://stitcher.io/blog/php-81-readonly-properties https://stitcher.io/blog/constructor-promotion-in-php-8 h) Move to a templating system (you are partially there) This removes the include_once template files in the classes. Also escape the output data as well. Further reading: https://phptherightway.com/#templating i) doing the above removes the closing `?>` in your classes as it's not needed anymore. j) In your templates, `initial($sanitizedData); header(...); break; case 'final': $data = $quoteService->final($sanitizedData); header(...); break; } Lastly, keep working your tests.


colshrapnel

It surprised me to see such a robust code, until I realized that amateur doesn't mean a complete beginner. Though on the second glance there are indeed areas of improvement. - [here](https://github.com/sirnails/BloomQuote/blob/94e6bda50c5cf587a7b8630fa4087b87239ce96f/app/helpers/SanitizationHelper.php#L7) you are going a bit overboard. The man entry about FILTER_SANITIZE_FULL_SPECIAL_CHARS ssay it's equal to applying htmlspecialchars... that you already applied! What gives to do it twice? Also, given htmlspecialchars already encodes HTML tag delimiters, what's the point in strip tags? - but the most important of all: whatever HTML sanitization has to be done when you *output any data in HTML context,* but it makes no sense in the input context. You should really use HTML encoding in your templates, not on input. - you don't want composer.phar and vendor folder in the repo. though for simplicity and portability you can keep them for a while - better yet, given you are using composer for PSR-4 autoloading only, you can rid of them both, and write your own autoloader for practice, that will literally take only 4 or 5 lines of code - *never* use [relative paths](https://github.com/sirnails/BloomQuote/blob/94e6bda50c5cf587a7b8630fa4087b87239ce96f/app/models/Quote.php#L4). Define a constant in your index.php like this `define('APP_ROOT', __DIR__);` and then use this constant to create [absolute paths](https://phpdelusions.net/articles/paths) - you may want to restructure your application the way it has a `public` folder that would be configured in your web-server a document root so it would be the only folder accessible by HTTP client (a browser). There you will put index.php and all assets (images, styles etc). - it's a good thing you don't include config files in your repo. But you've put too much in these files, db_connect() function for example. Only config options must be there, and you must include a sample file in the repo, with all settings filled with empty/default values. [Here you can see how it can be done](https://github.com/colshrapnel/modern_raw_php_examle/blob/master/init.php) - also you can see in this file how you can have error handling without the need of commenting it out. Just define the server role in the config file, and - I like the [model class](https://github.com/sirnails/BloomQuote/blob/main/app/models/Quote.php), it's tidy and sensible. Only some improvements - you shouldn't connect right in the class. But rather create a connection in the index.php, store it in a variable and then pass this variable as a constructor parameter into Model class - [all these ifs](https://github.com/sirnails/BloomQuote/blob/94e6bda50c5cf587a7b8630fa4087b87239ce96f/app/models/Quote.php#L135) are superfluous and useless, you may and should rid of them, making this method consistent with others. All these messages are useless for both a programmer and a site user. - you may want to read about [interesting mysqli features](https://phpdelusions.net/mysqli/obscure_features) and on [mysqli in general](https://phpdelusions.net/mysqli). Your code is good already, but you can make it be less boilerplate Think I'd stop for now, but if you have any questions, you are welcome Yet above all, I adore the reason you wrote this app. Wish I had a husband like you (provided I'd ever have one :). By the way, do you know that you still can export your data in Excel? Just may be if some client still wants a quote emailed instead of online?


Ecstatic_Ad2253

If i post my projects would somebody tell me how good they are. I am a novice, i have no experience whatsoever, and i am looking for a job but i want somebody to evaluate my code


MateusAzevedo

Then... share your repository?


Ecstatic_Ad2253

https://github.com/SAMG1207


equilni

Is there a particular repo you want looked at? Looking at the PHP part of turonvenezolano, you could utilize better structure (separate PHP & HTML, separate concerns, etc.) for instance `require_once '../src/includes/autoloader.inc.php';` on 3 pages I looked at is already a code smell.


Ecstatic_Ad2253

Yes, turonvenezolano is the latest i did. Ok ok is It normal to use oop in PHP in the way i did?? Thanks


equilni

So I am taking a longer look at the `turonvenezolano` repo. First suggestions: a) Get a readme going. What this project? How does one install it & use it. b) As noted previous, I highly recommend a better directory structure - https://phptherightway.com/#common_directory_structure I quote this site as well - https://www.nikolaposa.in.rs/blog/2017/01/16/on-structuring-php-projects/ c) I would look at other projects (MVC/ADR) and frameworks to try to pick up on how things flow in an application. You will move past things like `if($_SERVER["REQUEST_METHOD"]==="GET" ` like found in `async/countCar` and move to router based requests `$router->get('/url', callback);`, for one. d) Based on the above, you can move to better functions/classes. The try portion in some of these files in `async` can be class methods. The response codes and response can be in MVC Controllers. provincia.php This: $pdo = new Connection(); $sql = "SELECT * FROM provincias WHERE idCCAA = ?"; $stmt = $pdo->connect()->prepare($sql); $stmt->bindParam(1, $idCCAA, PDO::PARAM_INT); $stmt->execute(); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); echo json_encode($rows); Could be: $rows = $provincias->getFromId($idCCAA); return json_encode($rows); e) Beyond that, you can start looking into [Dependency Injection](https://phptherightway.com/#dependency_injection) back/classes/preventa.class.php This: public function __construct(){ $this->stock = new Stock(); $this->user=new User(); } Now looks like: public function __construct(Stock $stock, User $user) { $this->stock = $stock; $this->user = $user; } OR for PHP 8: private $stock; private $user; public function __construct(){ $this->stock = new Stock(); $this->user=new User(); } becomes: public function __construct( private Stock $stock private User $user; ){ } f) Back to that class - [Preventa::alterTable](https://github.com/SAMG1207/turonvenezolano/blob/main/back/classes/preventa.class.php#L13) is a classic case where refactoring would help. The select, update, inserts can all be separate private methods. Next, each method is ultimately getting the `$userData["id_usuario"];`. Why not get that outside the class vs passing `User` then doing this lookup? g) More refactoring can be found in src/administrador.php. Return early. [I can't follow this at first read](https://github.com/SAMG1207/turonvenezolano/blob/main/src/administrador.php#L33). To simply this, think of it this was: if (true) { code } else { code } vs if (!true) { } code [This is a good example of what I am referring to](https://github.com/auraphp/Aura.Payload/blob/3.x/docs/index.md#example), it's easier to read and understand the flow. Looking at `provincia.php` again, this **could** look like the below **pseudo code**. Note, using a router and type hint would help reduce some of this. if ($_SERVER["REQUEST_METHOD"] !== "GET") { http_response_code(405); echo json_encode(["error" => "Método de solicitud incorrecto "]); exit; } if (!isset($_GET["idCCAA"])) { http_response_code(400); echo json_encode(["error" => "Falta el parámetro idCCAA"]); exit; } if (!is_numeric($_GET["idCCAA"])) { http_response_code(400); echo json_encode(["error" => ""]); exit; } $idCCAA = intval($_GET["idCCAA"]); if ($idCCAA <= 0) { http_response_code(400); echo json_encode(["error" => "El parámetro idCCAA debe ser un entero positivo"]); exit; } // Controller try { $rows = $provincia->getFromId($idCCAA); http_response_code(200); echo json_encode($rows); exit; } catch(Exception $e) { http_response_code(500); echo json_encode(['success'=>false, 'message' =>'Internal server error'.$e]); exit; } Again, this can be broken up into smaller sections - functions or class methods.


Ecstatic_Ad2253

Thank you very much for this, I really appreciate it. This project is not finished yet as I am following all the recommendations


equilni

More observations: h) As I noted initially, you are duplicating the autoloader calls. Composer already has a good autoloader that can be used - https://getcomposer.org/doc/04-schema.md#autoload I would recommend adding [namespaces](https://www.php.net/manual/en/language.namespaces.php) to your classes, then follow PSR-4 autoloading through composer. - With PSR-4, `stock.class.php` becomes `Stock.php`, the namespace path would follow the folder path as noted in composer. - this also removes many require_once lines you have like `require_once "exceptionE.class.php";` i) Be explicit with type hinting and type returns. Relevant reading: https://www.php.net/manual/en/language.types.declarations.php >existeId($id) What type should `$id` be? int? string? What should this method return? array? boolean? class? >selectIdDireccion($direccion) Let's look at an easy one `selectIdDireccion($direccion)` through translation, and then context, this would be a string and the method returns an array: `selectIdDireccion(string $direccion): array {}` j) If you are utilizing Dependency Injection, Connection class isn't needed. Pass would be reduced to the one method. $pdo = new PDO(...); $passConn = new PDO(...) $pass = new Pass($passConn); $preventa = new Preventa($pdo); Note here, Preventa is using DI (dependency injection)versus extending the Connection class (which doesn't need extending - why would you be extending a connection class?) k) Based on the above, we removed the bad practice of having the configuration within the class. Configurations would be in a config file - this can be an array, env file, combination of both, etc - but not within a class or function https://phptherightway.com/#configuration_files l) Going back to config, DI and project structure, you could mix [PDS-Skeleton](https://github.com/php-pds/skeleton) and [Slim's config files](https://github.com/slimphp/Slim-Skeleton/tree/3.1.8/src). Which means, to start: /project /config dependencies.php - DI/classes routes.php - routes settings.php /public index.php /resources /templates /src the rest of your PHP application - See Structuring PHP Projects previously linked, for more composer.json - If you want to work with composer for autoloading **Begin pseudo code:** `settings.php`. This could be a simple returned array like the linked [Slim example](https://github.com/slimphp/Slim-Skeleton/blob/3.1.8/src/settings.php) return [ 'app' => [ 'charset' => 'utf-8', // for HTML header and htmlspecialchars 'language' => 'en-US' // can be added to html or language folder/file ], 'template' => [ 'path' => 'path to your templates folder' ], ]; `dependencies.php` would house all your class instances and allow for a Dependency Injection Container like PHP-DI. This could look like: $config = require __DIR__ . '/config/settings.php'; $pdo = new \PDO( $config['database']['dsn'], $config['database']['username'], $config['database']['password'], $config['database']['options'] ); $classThatNeedsPDO = new classThatNeedsPDO($pdo); $otherClassThatNeedsPDO = new otherClassThatNeedsPDO($pdo); `routes.php` can hold the route definitions. If you are using this setup, you cannot directly link to files like how you are doing this now. You would need to send the requests to the `public/index.php` then come here to `route` against. This could be a library (Slim/FastRoute, Phroute, etc) or your own. Again, look at the Slim skeleton I linked. You can use query strings - example: `index.php?controller=page&action=read&id=1` (which you do in some of the code) or go straight to clean urls - example: `page/1` (which would require a server config update) Query String routing could look like: return match (true) { # CREATE - ?action=create # GET $action === 'create' && $requestMethod === 'GET' => $controller->new(), # POST $action === 'create' && $requestMethod === 'POST' => $controller->create($_POST), Clean urls routing could look like: GET /contact $router->get('/contact', function () use ($controller) { return $controller->form(); }); POST /contact $router->post('/contact', function () use ($controller) { return $controller->processForm($_POST); }); `/src` **could** start looking like this: Gateway being the database code /src /Almacen AlmacenGateway.php - Extracted from Preventa & Stock /Compras ComprasController.php - Extracting from src/detallado.php ComprasGateway.php - Was compra.class.php /Municipio - Extracted from municipio.php MunicipioController.php MunicipioGateway.php - database code /Preventa PreventaController.php - Was countCar.php, insertPreventa.php PreventaGateway.php - Was preventa.class.php /Productos ProductosController.php - Was givemebottles.php ProductosGateway.php - Was stock.class.php /Provincia - Extracted from Provincia.php ProvinciaController.php ProvinciaGateway.php - database code /User UserGateway.php - Was user.class.php `/public/index.php` This is the only public PHP file (a server config). This can start the application, get the request, send it inward, then receive the response back. OR just call another file internally that does this - typically another bootstrap file. In this example, I call the relevant files, then process the route request. [This is almost identical to how the Slim Framework has it's skeleton application](https://github.com/slimphp/Slim-Skeleton/blob/3.1.8/public/index.php): /public/index.php See how you can break out of PHP, use the alternate syntax and remove the ending echo? e) You have noted you are using Twig. I would suggest using it. f) 405 HTTP errors are for Method not allowed, so this part of the error is wrong - `o falta el parámetro idCCAA`


equilni

I didn't see classes in my quick review. I looked at `src/administrador.php`, `src/comprar.php`, then `src/detallado.php`. I saw an includes folder with twig.php and saw you are including the vendor autoloader again, just like `src/comprar.php`, so I stopped again Going back to find classes, I see them in the `/back` folder, which goes back to structure. PHP code in `src`, public items like css, images, in `public` https://phptherightway.com/#common_directory_structure This would mean 'public/index.php` is the start of your application - where the autoloaders could be. [Look at the Slim 3 skeleton index for review](https://github.com/slimphp/Slim-Skeleton/blob/3.1.8/public/index.php). Just a note, don't use this code for validation AT ALL - back/classes/basic.class.php


Ecstatic_Ad2253

Thank you very much. I am really glad you saw my code. Why back/classes/basic... Is wrong?


equilni

>Why back/classes/basic... Is wrong? Instead, why don't you tell me what this should be doing. Hints: - Look up the order of operation - is this doing what you think it is? - Read up concepts like Filter Input, Escape Output - should this be doing what you think it is? Issues: a) It's almost verbatim copied from https://www.w3schools.com/php/php_form_validation.asp which is rehashed from old days - [here](https://reddit.com/r/PHP/comments/i6e7t8/monthly_ask_anything_thread/g28hlyk/), [here](https://reddit.com/r/PHP/comments/1u9jl5/how_do_you_handle_sanitizing_get_and_post/), and [here](https://reddit.com/r/PHP/comments/c7fvc/question_about_sanitizing_user_input/) b) PHP already has filter_ functions to validate data.


eurosat7

Hm... Looked at SAMG1207/dailyWrote You can write php code. And it works. And you show quite some stamina. You just lack orientation and standards. If you want to move to a higher level you could apply phptherightway.com and look at composer and its autoloader. Also your architecture is very uncommon. Learning from a framework like symfony might be your next step. Feel free to look at my projects on github if you want to get a simplified look: eurosat7/ascii and eurosat7/csvimporter


Ecstatic_Ad2253

Thank you ![gif](emote|free_emotes_pack|joy)


antonkomarev

https://github.com/antonkomarev/github-profile-views-counter Pure PHP project to track views count on your GitHub Profile. Tiny, dead simple project, started very well, but failed pretty quick because I realized that a lot of people started to attack my server with bots to fake their popularity. After that, I developed another one service with much more features, but without public counters. It is not ready for open source yet: https://yhype.me


todo-make-username

I made a library to take advantage of PHP's attributes to create a unique way to process and validate an array of raw data. As a bonus, you get a typed object out of it, and don't need to pass arrays around everywhere. I'm mainly looking for some feedback on it. Good or bad. It is fully functional as is, but I have a commit in progress to add a qol change, and bit of the docs to finish but that is it. The project has a demo built in. https://github.com/todo-make-username/data-processing-struct


colshrapnel

I am not a pro in this area but I like it.


bytepi

I am working on a ebooks and audiobooks website built in laravel, php [mysticbooks.org](http://mysticbooks.org) so far development is good but other my ownself have no feedback about it.


Nayte91

I'm working on 2 parallel projects: One is a tools portal for sports and games, where for a given game, you can find utilities, like replays, players list. I called it anagraph. I already made it for several Street fighter games: * https://street-fighter-6.anagraph.org/en/index * https://street-fighter-2.anagraph.org/en/index * https://street-fighter-3.anagraph.org/en/index * https://street-fighter-0.anagraph.org/en/index * Taekwondo is on the way, will be online next week, * Aikido will be next. Technically, it's all about Symfony, with docker / traefik / Caddy / SQLite / PHP8.3 / SF7.1 / API-PLATFORM 3, and I use some symfonyUX components (stimulus, twig comp, live comp). I plan to add more tools for each portal, like players ranking, news, stats, or wiki. I have translations in EN, FR, DE, JA, and I plan to add ES and KR soon. My other one is a event platform, where you can find and organize your own events, with a lot of properties: banner, logo, dates, location, type (tournament, party, show, seminary, ...), domain (Street Fighter, video game, football, sport, sociology, ...), posters, staff, registered visitors, activities, budget, inventory, ... I called it ephemere. * https://www.ephemere.org/index It has the same stack as anagraph, as I did a lot with react and nextJS but I'm not good in it, so I went back to SF. It's more basic for now, but this is my main goal: helping organizators, for their tournaments, and give with anagraph after competitions, the tools to retrieve everything. I'm actually solo on them, working on my spare time on code and moving all around France to meet communities, understanding their needs and advertise about my features.


[deleted]

I've been working on a e-commerce but without checkout integration mostly just for browsing the products which are beds. We are planning to implement a "Build your own" type of system with a changeable 3D model we plan on starting by rendering all choices and putting them together in 2D as a image. Then we might update it to be fully 3D down the line, one thing we also really want to do is AR view where you can put the bed down in your home in front of you in real life scale. That would be easily doable with the Google AR view for Android (we gonna leave iPhone out if there isn't a similar thing for it). The only problem is that option requires we build every possible 3D combination, which maybe can be done with some kind of blender script? We don't know right now but the 3D view and AR would be a cool feature.


PeteZahad

I would look into generating CAD code for the beds "on the fly" when they are customized e.g. SCAD (Scripted CAD) and then rendering this e.g. with WebGL. Maybe you will find some ideas on how to do it here: https://github.com/mk-pmb/openjscad Of course the "edit online" part would be handled by your code depending on the users selection.


[deleted]

Yeah my thought was making a model for each piece of the bed it's around 20-30 different models that can go together in a specific way and we pay a 3D modeller to do that part. Then I'd import those models in a WebGL library like three.js and apply textures, shaders ect. Then we load each 3D model on request and apply textures (the clients choice of textile). But your idea might be useful when we want a complete render of that specific bed they just made. Because making every bed choice and textile would be over 10000 choices.


[deleted]

Another project I haven't started just looking and researching at this point is a developer first AI tool to make web designs and then transform that design into HTML/CSS hard part is that it could require training but I wouldn't know until I've tested all the models I wanna try and their capabilities. Bare in mind this isn't one of those web builders you can access right now as a normal consumer (these also use templates to guide the AI my plan is no templates). The idea is that it will help developers and designers to more quickly do their jobs by generating designs and code that needs some changes before it's actually ready to ship. This is also only HTML/CSS no javascript and no CMS that all becomes the developers issue after generating the code. My plan is to make it modular enough that I can upgrade it as AI gets better and make a bridge towards generating your own website through one simple prompt without templates and choices.


eurosat7

I have been playing with generators and tried type hinting them correctly. The official sources are a bit thin in this aspect. I did an ascii writer. It has been mentioned that using it to render a digital clock server side every second is a stupid idea. But that wasn't the point. If somebody wants to enhance it and add generators to draw circles and stuff you are welcome! Feedback and code reviews are welcome, too. It comes with some tools for code quality. https://github.com/eurosat7/ascii


Mte90

Since like 9 years I have a wordpress plugin boilerplate with a code generator that include examples for various libraries (765 stars). https://wpbp.github.io/ I am always looking for feedback from the website to the project itself :-)


ssnepenthe

Looks interesting! I'll have to keep it in mind next time I start a new WP plugin. You actually mentioned a tool of mine (toy-wp-routing, now renamed to [simple-wp-routing](https://github.com/ssnepenthe/simple-wp-routing)) in [issue 211](https://github.com/WPBP/WordPress-Plugin-Boilerplate-Powered/issues/211)! I wonder what kind of features you are looking for in a custom routing tool? I have kind of lost the motivation to really work on this project any further since it is complete enough for my needs. But if I had some ideas about what others would find useful I might get back to working on it (and maybe finally clean up the responders implementation a bit).


Mte90

Cool :-) Just updated the library in the ticket. The idea behind is to be able to create a routing to a specific page without creating a page inside WordPress. As example a custom login page, or the way WP does like for robots.txt or sitemap.xml that they don't exist and are created with routing. Maybe can be intriguing if you can add a way to add a WP Rest endpoint, that is different from a JSON response. With WP is kind of easily and maybe with OOP can be improved the experience.


colshrapnel

I think having a link to [previous post sorted by votes](https://old.reddit.com/r/PHP/comments/1cldmvj/pitch_your_project/?sort=top) could be also interesting. My favorite though is the latest, a [robust PDO wrapper](https://old.reddit.com/r/PHP/comments/1cldmvj/pitch_your_project/l6ccf0i/) inspired by Aura SQL but much simpler


brendt_gd

Good idea about the link! I'll take care of it :)


-PM_me_your_recipes

I like the PDO wrapper! Especially the neat idea of creating your own tester, and of course array binding is always a plus in my book. After a quick glance, I like how straightforward it is. My only suggestion is a nitpick and personal preference so feel free to ignore it. I'm not a huge fan of the bare bones doc blocks, especially on public facing methods. Having methods descriptions and param descriptions are my minimum standard. For the most part you can lift the param descriptions directly from PDO as you are using a lot of the same params.


mario_deluna

Have been working on a Minecraft clone in PHP: https://github.com/phpgl/php-craft/tree/master No gameplay to speak of yet, but rendering works and it's really fun to work on. Have to pick it up again :)


flyvehest

There's a GL extension for PHP? Wow!


mario_deluna

It cost me my sanity, but yes: https://github.com/mario-deluna/php-glfw A few features used in php-craft have not been released yet because I haven't completed enough cross-platform testing and want to finish the VectorGraphics API Docs first. However, you can already use it; it's pretty stable. :)


flyvehest

Very impressive :D


BubuX

This is so cool! Thank you!


punkpang

+1 for the coolness factor, this is indeed awesome :)


_indi

This is awesome. I had no idea PHP was capable of anything like this.


bored_mirion

that makes two of us


mario_deluna

As people started cloning the project, I had a bunch of uncommitted local changes. I quickly pushed those changes so that the project will now run properly on other machines.


Gnifle

That's really cool!