#

php

(4 articles)

Add essential dotenv support to your wordpress without a plugin

*Original date 2022-10-16T00:00:00.000Z* You may want to start using Environment variables to configure your WordPress application. I did because I needed to install a development environment to my local and did not want to keep separate wp-config.php files. So, how did I that? I am already using `direnv` to manage environment variables dependent on folders. When I work on X project, it automatically loads the required env variables. You can check out at [direnv.net](direnv.net) First, I created a `.envrc` file with that content; ``` dotenv .env ``` It will use variables inside the .env file to configure my environment. This is an example content of the `.env` file. ``` APP_ENV=dev WP_DEBUG=true WORDPRESS_DB_NAME=eresbiotech WORDPRESS_DB_USER=moodif WORDPRESS_DB_PASSWORD=1542bilim WORDPRESS_DB_HOST=db ``` It's a simple key-value file. After that, I allowed the direnv to load that environment with the `direnv allow` command. Then, I updated my `wp-config.php` file to fetch variables from the environment. I've just added database-related configs. You can add salt keys and other configs like this. ```php define('DB_NAME', getenv('WORDPRESS_DB_NAME')); /** MySQL database username */ define('DB_USER', getenv('WORDPRESS_DB_USER')); /** MySQL database password */ define('DB_PASSWORD', getenv('WORDPRESS_DB_PASSWORD')); /** MySQL hostname */ define('DB_HOST', getenv('WORDPRESS_DB_HOST')); ``` You see, easy-peasy. Not much. I expected it to work like a charm, but it didn't because I was using PHP-FPM and Nginx together. There are different ways to allow php-fpm to fetch system environment files, but I loved dotenv too much. There are tons of different scenarios in which you cannot access PHP or server configs (like using hosting) Anyway, I decided to write this simple snippet (there is a [library](https://github.com/vlucas/phpdotenv) to do that, but I do not want to add a library to WordPress yet) ```php <?php if(!getenv('APP_ENV') && file_exists(ABSPATH.'.env')){ $content = file_get_contents(ABSPATH.'.env'); $envs = explode("\n",$content); foreach($envs as $env){ if(empty($env)){continue;} putenv($env); } } ``` Then add that file to the `wp-load.php` file. After the first `if` condition; ```php if ( ! defined( 'ABSPATH' ) ) { //this is the first if condition in the file define( 'ABSPATH', __DIR__ . '/' ); } include(ABSPATH.'/dotenv.php'); //this is our code ``` Then it will be ready to use. `dotenv.php` file reads `.env` file content in your local/prod server, then it will load values. `wp-config.php` file will use that values to configure the WordPress. Let me tell you one more thing before I finish the post. You have to achieve one more step if you are using `wp-cli` in your server. `wp-cli` is using `wp-config.php` to configure the tool itself, but this file does not know how to load `.env` file. We can add this snippet to the top of the `wp-config.php` file to prevent issues. ```php if(!getenv('APP_ENV')){ //for wp-cli include './dotenv.php'; } ``` You did it! You can have separate installations for your WordPress now without changing any code block or installing plugins. Of course, there is a downside to this approach. You have to care `wp-load.php` and `wp-config.php` files after every core update. But it's a tiny downside. I am using git to follow changes, I am just reverting the changes in this file after the update (or I am adding required lines to new versions of this file), and it's done. keep safe kittens > final notice; do not forget to configure the public access to `.env` file from outworld. no one wants to share db password with others. check http://yoursite.com/.env URL, it must return 404. [for apache](https://www.google.it/search?q=how+to+deny+access+to+file+htaccess) , [for nginx](https://www.google.it/search?q=how+to+deny+access+to+file+nginx)

How to write a data mapper with php

*Original date 2019-07-07T00:00:00.000Z* When you develop an API client with PHP, you would need data mapper for mapping data from API to an object. For example, you have requested an API endpoint and you get a response like that: ```json { "user": { "username": "delirehberi", "bio": "carpenter" } } ``` And you have a User class ```php <?php class User{ protected $username; protected $fullname; protected $bio; /** * @return mixed */ public function getUsername() { return $this->username; } /** * @param mixed $username * * @return User */ public function setUsername($username) { $this->username = $username; return $this; } /** * @return mixed */ public function getFullname() { return $this->fullname; } /** * @param mixed $fullname * * @return User */ public function setFullname($fullname) { $this->fullname = $fullname; return $this; } /** * @return mixed */ public function getBio() { return $this->bio; } /** * @param mixed $bio * * @return User */ public function setBio($bio) { $this->bio = $bio; return $this; } } ``` You need to map JSON response to the PHP object. But how? You will need to know how to use [ReflectionClass](https://php.net/manual/en/class.reflectionclass.php), [PropertyAccess](https://symfony.com/doc/current/components/property_access.html), [AnnotationReader](https://www.doctrine-project.org/api/annotations/1.6/Doctrine/Common/Annotations/AnnotationReader.html). ### How do you map class properties to API response fields and returns an object? At first, you need to decode JSON string to PHP array or object. ```php $result = json_decode($response, true); ``` After that, create a Reflection class; ```php $reflectionObj = new \ReflectionClass(User::class); ``` Now you can access all properties ```php $properties = $reflectionObj->getProperties(); ``` You don't need to know your User Class has which properties anymore. Now, we need PropertyAccessor for manipulating our User object. ```php $propertyAccessor = PropertyAccess::createPropertyAccessor(); ``` ### How can manipulate an object property with PropertyAccess object? ```php $propertyAccessor->setValue( $userObject, $property->getName(), //eg: username $value //eg: emre ); ``` OK, we know how to access the property of an object and how to manipulate another object properties. Now we can start writing our data mapper. Create an annotation class to configure properties to json values. ```php use Doctrine\Common\Annotations\Annotation; /** * Class DataMapper. * * @Annotation * @Annotation\Target({"PROPERTY"}) */ class DataMapper { public $json_field; } ``` We will use this object to define a JSON field equal to an object property. We can update our User class property annotations like that: ```php /** * @var * @DataMapper(json_field="username") */ protected $username; /** * @var * @DataMapper(json_field="full_name") */ protected $fullname; /** * @var * @DataMapper(json_field="bio") */ protected $bio; ``` note: don't forget to add DataMapper class to the header. We are ready for writing data mapping logic. - Create an annotation reader object - Create property accessor - Create a new empty object (eg: User) - Create a reflection object for reach properties - Get object properties from reflection object - Foreach to properties - read property annotation for DataMapper annotation - get json_field value from annotation - access data from JSON with json_field value - set property of a new object with data - return new filled object :) ```php $reader = new AnnotationReader(); $propertyAccessor = PropertyAccess::createPropertyAccessor(); $user = new User(); $reflectionObj = new \ReflectionClass(User::class); $properties = $reflectionObj->getProperties(); foreach ($properties as $key => $property) { $propertyAnnotation = $reader->getPropertyAnnotation($property, DataMapper::class); $json_field = $propertyAnnotation->json_field; if(!$json_field) continue; $value = $result[$json_field]; $propertyAccessor->setValue( $user, $property->getName(), $value ); } var_dump($user); ``` Congrats, you can write as a function and use in your project.