Email:   Password:
Blog :: Technical Learning by Thomas Riemer
RSS 2.0   RSS 1.0   Atom
mongodb II   (PDF)
Posted April 12th, 2024

mongodb installation woes

Installation on aws 2023 /aws 2

So the general advice on the net is to do:

dnf install mongodb-org

When you get to mongosh ... you lose...

You'll get an error like:


[root@groupcorners /]# mongosh
mongosh: OpenSSL configuration error:
40C88FFB977F0000:error:030000A9:digital envelope routines:alg_module_init:unkno\
wn option:../deps/openssl/openssl/crypto/evp/evp_cnf.c:61:name=rh-allow-sha1-si\
gnatures, value=yes

And its all very sad!

So... to fix this:


dnf remove mongdb-org

dnf install ongodb-mongosh-shared-openssl3

dnf install mongodb-org


Somehow installing mongdb-org straight gets the wrong version of mongosh installed.

No one likes dependencies.

Now at least mongosh works.  Wish I knew where to send this bit so it gets fixed!

Inbound Mail AWS   (PDF)
Posted April 10th, 2024

Amazon AWS limits inbound smtp requests.

If you set up an aws EC2 instance and use an elastic IP - the incoming smtp is blocked.

Don't let anyone kid you - its a fact.    It doesn't matter if you adjust your security group

to allow incoming smtp.

So what is the alternative?

The answer I came up with today is

It allows you to assign mx servers and route your email.

It allows you to route to a specific mailbox AND, AND, AND it allows you to setup

a webhook to post to when emails are sent.

A webhook is a piece of code on a server that accepts a payload.

In this case its a json with the wad of an email each time that someone sends an email

to a particular domain.

The documentation from on the particular json packet sent is non

existent - but it doesn't matter once you see the json.

Ok - so once you get the wad of json - the next thing is to parse the email.

Again this is a piece of arcana that is a bit weak on documentation.

1. php has mailparse - this is a pecl addition to parse mime emails.

2. there is a library that uses the pecl library mailparse.

    php-mime-mail-parser is a php library that supposedly is supported for php 8+

And if you are going to mess with this stuff believe me, you want to be able to have

baseline to test emails with:

Here is a link to a really solid tool to send emails:

Ok, don't forget the implications of a) SPF b) DKIM C) DMARC D) Reverse DNS

Here is sample code for a webhook from that seems to work.

The code depends on a bunch of other stuff - but it should be a good start in

allowing you to grab the data.

function do_inject($path)
      header('Content-Type: application/json');
      $request = file_get_contents('php://input');

      $rand = rand(1000,2000);
      $raw ="/m/member/tmp/incoming.".$rand.".email";
      $parsed = "/m/member/tmp/incoming.".$rand.".parsed";
      require_once "parseinject.php";
      $pi = new parseinject();
      $fields = $pi->parse($request);
      $emailparsed = "";
      foreach ($fields as $key=>$value)
          $emailparsed .= $key."\n";
          $emailparsed .= $value."\n";
          $emailparsed .= "\n";
          $emailparsed .= "\n";
      require_once "background/injector/injectmail.php";
      $imail =new injectmail();
      $imail->source_email = $fields['from'];
      $imail->target_email = $fields['address'];
      $imail->email_content = $fields['raw'];
      $imail->email_size = strlen($fields['html']);
      $imail->queue_reference = $field['messageid'];
      echo "INJECTED";
      http_response_code(200); }

perl   (PDF)
Posted March 25th, 2024

perl is an old school language.
1. mod_perl

2. variables

   my $name = "value";
   my %hash = ( "blah"=>"foo",
   print $hash{"blah"};
   my @array = ("a","b","c");                
   print $array[1];

3. comparators:
# Numerical operators:  <,  >, <=, >=, ==, !=, <=>, +, *
# String operators:    lt, gt, le, ge, eq, ne, cmp, ., x


unless ($foo > 3)
      print "foo";
      print "blah";

5. if, elsif,else

   $foo = 10 if ($blah == 4);

6. ?:

   $blah =  ($foo==1) ? "one":"two";
7. for (my $i=0;$i<10;$i++)
   foreach my $blah (@reverse)
    print $blah."\n";

8. keys %hash - to get keys of hash

9. next, last can be used in loops..
   equivalent to continue, and break

10. pop,
11. my $rc = system "perl", "";
     $rc >>= 8;
    print "Status Code:".$c."\n";

    my @lines = `perl`;

    exit 37;

12. files
    my $filename= "text.txt";
    my $result = open my $handle, "<", $filename;

    if (!$result)
      die "Failed to open ".$filename." because, $!;

    open (my $handle, "<", $filename) || die "failed ".$!."\n";

13. while (!eof $handle)
    my $line = readline $fh;

14. while (my $line = readline $handle)

   while (my $line = <$handle>)

   while (<$handle>)
        print $_;

15. -e

16. regex
    if (  $hello =~ m/(\w+)\s+(\w)/)
         echo $1." ".$2;
    replace $foo =~ s/blah/foo/g;
       // g is global

17. modules.
    1) must return 1 in .pl file
    2) require "Demo::module_name";
         (comes from subdir Demo/
    3) PERL5LIBS=blah


Laravel II   (PDF)
Posted March 25th, 2024

Basic attempt to do a simple crud application.
1. So you can install laravel globally
composer global require laravel/installation
This installs the laravel binary in ${HOME}/.config/composer/vendor/bin
Its useful to put this as a separate user. I chose <b>composer</b>
useradd composer
su - composer
composer global require laravel/installation
chmod 777 /home/composer
So other users can use the laravel installation binary, add the location to
Path. edit /etc/profile.d/
export PATH=$PATH:/home/composer/.config/composer/vendor/bin

2. starter kits.   So following a tutorial for laravel, and as usual its out of data.   So to create a project:
laravel new posty
And now it asks me for a "starter kit"
None, Breeze, Jetstream.
I chose None

And now it asks me the testing framework
Pest, or PHPUnit
I chose Pest - it was the default
And now whether I want to initialize a git repository

And now it asks me for what database to use
Mysql, Mariadb, PostgresSQl, SQLite, SQL Server

3. <b>php artisan</b> lists all the various things you can
do with artisan e.g. laravel

4. So <b>blade</b> The laravel default template engine.
   First thing is to be introduced to Layouts....
   a. php artisan make:component Layout
      // this generates a Layout component with
      // resources/views/controller/layout.blade.php
    b. Here is a sample layout controller (resoure/views/controller/layout.blade.php
    <title>{{ $title ?? 'Example Website' }}</title>
    <link rel="stylesheet" href="{{ asset('/css/app.css') }}">
      <h3>Welcome to my website</h3>
    {{ $slot }}
      <hr />
      &copy; 2023

c. So a content php file is called a view.
    each file view is named viewname.blade.php
   example welcome.blade.php

d. Sample welcome.blade.php
   <x-slot name="title">
    Home | Example Website
    <h1>Hello World!</h1>
    <p>Lorem ipsum dolor sit amet consectetur adipiscing elit. Hic, aut?</p>
    <button class="btn">Get Started</button>
    the magic <b>x-layout</b> tag tells the template to use the layout
    the <b>x-slot</b> tag lets you pass alternate content to the layout
    the code {{ $title ?? 'Example Website' }} says to show the variable
    title if it exists otherwise "Example Website"
    The x-slot allows you to overlayout that.

5. tailwindcss.  Install via npm
npm install tailwindcss
So... an aside, you will see warnings on npm if you are pulling from
the http vs https registry.  You can configure your registry in npm

npm config set registry

6. I use emacs... but all the samples use code visual studio
 Download from

7. models, controllers and crud oh my.

   So by default the laravel resource code for controllers
   doesn't handle POSTs well.

   So - you make a model
   php artisan make:model Product
   php artisan make:controller ProductController --resource
   So if you use
   Router::resource("product", ProductController::class);
   you can't just use POST from your html form post.
   from the docs its supposed to be PUT method, but PUT method
   makes the fields passed as a url - which means you hit a limitation
   method on requests where the content is over a certain limit.

   So vendor/laravel/framework/src/Illuminate/Routing/ResourceRegistrar.php
   line 493, add "POST" in the methods that can match.

   So now you can use POST. really stupid.. I ended up having to chance
   down where it matches the code in laravel. 2 1/2 hours later.

   Unbelievable the number of simple projects that purport to show
   a simple crud example in laravel.   Half of them do not have
   the routing information provided.   Some clearly are from previous
   versions of laravel.

   It would be really nice if it wrote the actual functions in the
   controller when you do --resource

postgres   (PDF)
Posted March 22nd, 2024

postgres is a database server
1. install postgres
   dnf install postgresql-server
   dnf install postgresql-contribb
   dnf install postgresql-devel
2. >systemctl enable postgresql

3. need to initialize postgres
   >postgresql-setup --initdb --unit postgresql
4. start the server
   > systemctl start postgresql

5. Now get command line access
   sudo -u postgres psql

6. The command line now allows sql commands
     =# create user USERNAME with password 'PASSWORD';


   c. su postgres
      psql DBNAME

7. recomping php with flag --with-pgsql on configure script
   include --with-pdo-pgsql (laravel uses that)
laravel   (PDF)
Posted March 22nd, 2024

Laraval is a popular framework for php
1a. laravel required sqlite.
    > dnf install sqlite-devel
1b. To create a laravel project
    > composer create-project laravel/laravel:^11.0 project-name

2. So laravel when developing is generally done by running a local
   web server, which listens on port 8000.  From your project directory
   >  php artisan serve
   Now point your browser at http://localhost:8000

3. in the app:
   config directory - has configuration files.
       (app.php is main one)

4. So I chose to use postgres to use as a database.

A. create user and database
   > sudo -u postgres psql
   > create user foo password 'bar';
   > create database fubardb owner foo;

configure postgresql in .env in top level of project


configure /var/lib/pgsql/data/pg_hba.conf
change the line for for ipv4 to:
(ident needs to change to trust)
host    all             all               trust

5. So this doesn't work...
   need to compile pgsql, and/or mysql
   So php needs to be compiled with flags
   ./configure --with-pdo-mysql=mysqlnd \
       --with-pdo-pgsql=mysqlnd \
       --with-pgsql \

   // Laravel uses the PDO objects in its database access.

6. run php artisan migrate:fresh
   this generates the user account handling stuff for laravel

7. Routes are in the routes subdiretory

   To add an api
   php artisan install:api
   This generates routes/api.php
8. Creating a table in Laravel - Migration
   > php artisan make:migration migration_name

   This creates a php object datestamped, with the migration name in

   The object has an up and down function.
   So to create the table update the up function.
public function up(): void
        Schema::create('cave', function (Blueprint $table) {


node.js   (PDF)
Posted March 1st, 2024

node.js is a server that runs javascript on the server
1. bun is a replacement for node.js

2. generally nodejs is installed via yum, dnf, or whatever package
   manager you have

3. node.js is javascript engine that runs javascript on the server side

4. To setup a project
   npm init

5. install express server
   npm install express --save

6. Here is "Hello World!" using an express server
const express = require('express')
const app = express()
const port = 3000

## App get sets a route for /
app.get('/', (req, res) => {
  res.send('Hello World!')

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)

7. BUT - really nobody uses the simple version...
   we use express-generator
   # install express-generator
   >npm install -g express-generator
   # run install

   This generates a structure in the current directory including:

   a) public is for static html files

   b) routes defines how to route urls

   c) bin
      bin/www is what starts the server
8. nodemon - sets up node so that it will reread files
   upon change.
   > npm install --save-dev nodemon
9. Fetching data from the database.
   a) create an object that fetches data ( file con.js)
   var mysql = require('mysql2');
   var con = mysql.createConnection({
           user: 'xxxxxuser',

   con.connect(function(err) {
      if (err) throw err;

   async function sqlquery(sql)
      const results = await con.promise().query(sql);
     // returns a list of [data,meta]
      return results[0];

   module.exports = {

   b) from routes/index.js
     var con = require("../services/con");
     router.get('/fubar', async function(req,res,next) {
        let sql = 'show tables';                   
        res.json(await con.sqlquery(sql));                   

  c) await can only be used from an aync function
     the function being called needs to be async
     and we do an await on a promise from con.query...
     the results returned are a list of elements, data, and meta data
     This appears complex.
     basically the mysql query is run in the background unless
     we force nodejs to wait for the results

Upgrading Servers   (PDF)
Posted March 1st, 2024

Notes on upgrading to apache2.4.58/ php-8.3.1
Jan 11, 2024
- need to have knowledge
   a) laravel
   b) symphony
   c) codeigniter
   d) nosql
   e) reactjs
- these are good blog topics
- more topics
    a) postgresql
    b) mongodb
    c) git

5:30pm - look at codeigniter

       Php Configuration:
        codeigniter requires a number of php extensions
     a) intl   = php configure --enable-intl
     b) mbstring = php configure --enable-mbstring
     c) json   = included by default
     d) mysqlnd = php configure --with-msqli=mysqlnd
     e) curl  = php configure --with-curl
     f) imagick = pecl install imagick
     g) gd = php configure --with-gd
           = php8 configure --enable-gd
     h) simplexml = enabled by default
     i) memcache = installed via pecl
     j) memcached = installed via pecl
     k) redis = installed via pecl
     l) dom   = enabled by default
     m) libxml = enabled by default
     n) xdebug = pecl install xdebug
5:33pm - need to upgrade dev2 to php 8
       I build php from source
       Latest php version is 8.3.1
       downloadable from
       pecl has a problem due to cacert.pem
       configure php.ini
       cd /usr/local/ssl
       This will download the cacert.pem with the update ca certs
       To see the cacert locations:
       php -r "print_r(openssl_get_cert_locations());"

6:30pm - apache is out of data.   Latest version is apache-2.4.58

7:11pm - so upgrade of php impacts the pearpkgs included
       by the software.
       Had to modify pearpkgs/
       Found bug in pearpkgs/MDB2/Mysqli.php

10:18pm - so it turns out that you can configure the php.ini to format
       the error outputs so its a little nicer in php.ini
       error_append_string = "

12:32am - so since I upgraded mariadb when I switched servers
       the database will not accept a blank string into an integer.
       This turns out to be a configuration set mariadb
       (mariadb is a version of mysql)
       select @@sql_mode
       edit /etc/my.cnf.d/mariadb-server.cnf

2:41am - recompiling php to include zlib
      ./configure --with-zlib

3:56am - added browscap ini item in php.ini
4:09am - build apache 2.4.58 and of course rebuild php-8.3.1

Jan 12, 2024
2:00pm - going to upgrade groupcorners to apache-2.4.58,php-8.3.1

2:42pm - php upgrade fails because its missing oniguruma-devel package.
       which apparently does not exist on redhat os 8.2

       to get it:
       download zip, and unzip it.  Probably ignore the INSTALL
       read file.

       to build it:
       yum install automake
       yum install autoconf
       autoreconf -fi
       make install

       then  modify your build script for php-8.3.1
       add before configure
       export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig

6:41pm - got php-8.3.1 to compile without mbstring
       had to add CFLAGS=-fPIC to configure statement
       and remove -enable-mbstring
       need to enable zip and imagick -*-*+90

Jan 13, 2024
4:33 pm  added zip to php
       pecl install zip

4:53pm   install imagick on
       so the standard install
       pecl install imagick - fails in php 8.3.0
       So get the source from
       unzip imagick-master
       cd imagick-master
       make install
       copy from no-debug* under /usr/local/lib/php/extensions
       to /usr/local/lib/php/extensions
10:06pm - so mbstring fails to compile in php.
        a) the LDFLAGS in configure is not honored, so you
       need to add any thing in CFLAGS
    b) gcc is used to compile php, gcc uses binutils to
       link the objecs. Apparently the binutils on
       redhat 8.9, which groupcorners is running is not
       high enough version.  Apparently I need a version
       higher that 2.32 (groupcorners is running 2.30)

       So.. the answer is recompile binutils, and recompile
       gcc - and use the new gcc to compile php.

11:54pm   rebuilt php-8.3.1 with new gcc successfully.
        mbstring now compiles.

bootstrap   (PDF)
Posted March 1st, 2024

bootstrap is a css framework
Basic Bootstrap Cheatsheet:
Get Bootstrap css from:

Start container css:

Button CSS classes:
btn (every button gets this)
btn-default btn-info btn-danger (various colors set)
btn-block (block instead of inline)

Shading classes:

Text css:








container has class row
row as 12 cols
col-xs-3 - means column, extra small, 3 columns

Full Cheat Sheet:

react   (PDF)
Posted February 22nd, 2024

react is a frontend javascript implementation
1. you can run react direct in a standard html file

2. Or create a react.js app
   -- npm install -g create-react-app
   -- npx create-react-app my-app-name
   -- npm start - will start app on port 3000
   -- edit package.json to redirect port
        under scripts section in package.json
    change "start": "PORT=9561 react-scripts start",
   -- this is a development version
   -- can redirect apache with
      ProxyPass / http://localhost:9561/
   -- the sample app created expects the app to be at the top level
      The paths are not set up to allow a subdir app.

react.js cheatsheet

From facebook.

Babel transpiler translates react.js to html/css

Command that puts JSX on DOM
ReactDOM.render(JSX, document.getElementById('root'))

When defining a JSX must return a complete element

{/* comments here  */}

ReactDOM api renders JSX to HTMLDOM
ReactDOM.render(componentToRender, targetNode)

use className instead of class on elements

1. components start with Capital letter
2. must return element or null
3. stateless
const MyComponent = function () {
    return (

4. ES6 format - extend from React.Component
class MyComponent extends React.Component {
  constructor(props) {

  render() {
    return (

const ChildComponent = () => {
    return (

Once you define a component, compose with <NameComponent arg="foo" />
    ${} is the value.

import PropTypes from 'prop-types';

jquery   (PDF)
Posted February 22nd, 2024

jquery is a javascript library that simplifies DOM management.
Basic Jquery Cheatsheet:

Get it from:

Run on Load
$(document).ready(function() {

Reference a type (e.g. a button)

Reference a class:

Reference an id:

css - add css rule to element
   Sample $(#myid).css('background-color','red');
   Note that its a comma between elements, not a colon
addClass - adds a class to an element
removeClass -removes a class from an element
html - sets body of element
text - set element text without evaluating
remove - removes an element
appendTo - appends selected element to new target
      Sample: $("#myid").appendTo("#target2");
clone - create a clone
     Sample: $("#myid").clone().appendTo("#target2");
parent - finds parent element of element selected.
children - finds children elements of element selected.
nth-child - finds nth child of element

sass   (PDF)
Posted February 22nd, 2024

sass - syntactically awesome style sheets
SASS Cheat Sheet - Syntactically Awesome Style Sheets

Use type: text/scss on the style tag

<style type='text/scss'>

Define a variable:
$varname: value;
  Sample:  $text-color:red

Nesting css elements
.foo {
     p {

@mixin funcname($arg1, $arg2) {
@include funcname("blah","blah2");

In mixins - conditionals
@if $val == foo
@else if $val == blah

@for $var from 1 through 6 {
   .classname-#{$var} { font-size: 15 * $var}
loop over list:
@each $var in blue,green,red {
   .#{$var}-text { color: $var; }

while statement:
$var : 0;
@while $var < foo {
   .column-#{$var} { font-size: 12 * $var;}
    $var: $var +1;

import partials:
@import "filename"
_filename.scss would be file.

@extends .otherrule

Python   (PDF)
Posted February 22nd, 2024

Python is a popular language used for web development

1. build python
   make install

2. install gunicorn
   pip3 install gunicorn

3. in apache enable proxy modules
LoadModule proxy_module modules/
LoadModule proxy_http_module modules/

4. add ProxyPass entry in vhost
ProxyPass "/pybase/" ""

5. configure gunicorn.service file in  /usr/lib/systemd/system/gunicorn.service

===== Start gunicorn.service File ======
Description=The Apache HTTP Server

MAINPID = /run/cmdb/
WorkingDirectory = /m/member/pybase
ExecStartPre = /bin/mkdir /run/cmdb
ExecStart=/usr/local/bin/gunicorn --workers=4 myapp:app --chdir="/m/member/pybase" --pid /run/cmdb/
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s HUP $MAINPID
ExecStopPost = /bin/rm -rf /run/cmdb



===== End gunicorn.service File ======

A) definition of a function
  def funcname(arg1,arg2):

B) spacing matters - indentation defines block

C) definition of if statement
  if (a == 1):
     a += 1;

D) for statement
   for (x in environ):
       data += x+environ[x];

E) Templates
   Jinja2 is the most prevalent template engine
   sample code to load from file:

   import jinja2
   def display_template():
      templateLoader = jinja2.FileSystemLoader(searchpath="./templates")
      templateEnv = jinja2.Environment(loader=templateLoader)
      templateFile = "template.html"
      template = templateEnv.get_template(templateFile)
      return template.render();

F) getting data from the database
   - basic level method (cursor)
   import mysql.connector
   def get_data(sql):
     cnx = mysql.connector.connect(

    data = "<table>\n"
    if cnx and cnx.is_connected():
       with cnx.cursor() as cursor:
          result = cursor.execute(sql)
          rows = cursor.fetchall()
          for row in rows:
              data += "<tr>\n"
              for col in row:
                  data += "   <td>"+col+"</td>\n"
              data += "</tr>\n"
    data += "</table>\n\n"
    return data
   ---- end code --------
   -More sophisticated is to use pandas to load the data to a grid
   pandas can output the data in a number of formats
   pandas is a library that allows data to be loaded into a grid
   that can then be displayed.
def get_table(sql):
       cnx = mysql.connector.connect(
       results = pd.read_sql(sql,cnx)
       # html table has systables as a css class systables in addition to
       # dataframe... e.g. <table class='dataframes systables'>
       return results.to_html( classes= "systables")
   except Exception as e:
    return str(e)
---- end code -----

G) Get an argument from command line
   import sys
   def main():
      if (len(sys.argv)>=2:
          print("ARG 1:",sys.argv[1]);

    if __name__ == '__main__':

H) repeat string... * syntax

I) From the command line - help(keyword)

J)To convert numbers to strings
    mystring = str(10);

K) numbers:
   1. no ++ - can't do a++
   2. integer division is two // e.g. 2.4 // 2 = 1

L) raw strings
   raw= r'this\t\n and that'
   multi= """ hello
      world """

M) slices
   something = s[1:4]
   >>> 'ell'
   >> 'o'
N) strings
   [f strings]
    value = 2.791514
    print(f'approximate value = {value:.2f}')

O) if statements
    if a==b:
        print("a equals b")
    elif c==d
        print("c equals d")

P) and/or  ( there is no && or || )
   if a and b:
   if a or b

Q) for/in
   for key in list:
     iterate here
   if "moe" in list:
       do if moe is in list

R) dict
   mydict = {key1:value1,key2:value2}
   mydict = {}
   usage: myvar = mydict[key1];
   mykeys = mydict.keys();
   myvalues = mydict.values();
   myitems = mydict.items();  // tuple
   for k,v in myitems : print (k,"=",v)
   s = : %(word)s %mydict
   del mydict[0];
   del mydict[-2:0]

S) files
   #open file
   f = fopen("filaneme.txt", "rt", encoding='utf-8')
   for line in f:
       print (line, end='')

T) regular expressions
   import re
   mystr = " hello 123 456";
   mymatch =, '\d+');
   mymatch = re.findall(mystr, "\d+");
   mymatch = re.sub(mystr, "123", "\d+");

U) major important libraries
   os lib: os.listdir(dir), os.path.join(dir,filename), os.path.abspath(filename), os.path.dirname(filename)
          os.path.basename(filename), os.path.exists(filename), os.mkdir(path), os.mkdirs(path1)
   shutil lib: shutil.copy(source,target)
       output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) -
   urilib lib:
      ufile = urllib.request.urlopen(url);
      text =
      info =
      baseurl = ufile.geturl()
      urllib.request.urlretrieve(url, filename)
      urllib.parse.urljoin(baseurl, url)
      from urllib.request import urlopen
   uriparse lib:

mongodb   (PDF)
Posted February 22nd, 2024

Mongodb is a popular nosql server

To install:
a) set up yum repo
  /etc/yum.repos.d/mongodb-org-7.0.repo file should contain
name=MongoDB Repository

b) mongodb runs a user mongod, systemctl start mongod
   /var/lib/mongo is repository
   /var/log/mongodb is logging directory
c) mongosh = mongo shell
   test> use mydb         // change to database
   mydb> show collections  // show collections


d) So install on amazon 2023 doesn't work for mongosh
   > dnf remove mongodb-mongosh
   > dnf install -qy mongodb-mongosh-shared-openssl3

e) For PHP, install mongodb extension
   -- Install the mongodb extension to php
   >pecl install mongodb
   (I chose all the defaults)
   > cd /usr/local/lib/php/extensions
   mongodb built in subdir... copy up one level
   >add to php.ini (/usr/local/lib/php.ini)

   -- now install php library
   in your php project where composer.json is
   composer require mongodb/mongodb

f) basic code to initiate mongodb from php
     require_once "lib/vendor/autoload.php";
     $serverApi = new ServerApi(ServerApi::V1);
     $client = new MongoDB\Client('mongodb://',[],['serverApi'=>$serverApi]);

  CRUD operations:
  define the collection:
  $collection = $client->test->users  ( creates a users table in test database)
  $result =$client->insertOne(['username'=>'admin',email=>']);
  Get Count: echo $result->getInsertedCount();
  Get Inserted Id: echo $result->getInsertedId();
  $result = $client->insertMany(
  Get Count: echo $result->getInsertedCount();
  Get Inserted Ids: echo $result->getInsertedIds();

  $cursor = $collection->find(['username'=>'admin',
        'last_name'=> MongoDB\BSON\Regex('^garden', 'i')
  // Mix and match options
     $options = ['projection'=>
         'sort'=>['pop' => -1],

   $result = $collection->updateOne(
    ['$set'=>['address'=>'123 test way']]
    $count = $result->getMatchedCount();
    $modified = $result->getModifiedCount();

   $result = $colletion->updateMany(
   ** Updated only updates the fields mentioned **

   $result = $collection->replaceOne(
        ['name'=>'Tom'],    // filter
    ['username'=>'thomas',  // new document
    $count = $result->getMatchedCount();
    $modified = $result->getModifiedCount();

  /* This replaces all fields */

    $updateResult = $collection->updateOne(
    ['name' => 'Bob'],
    ['$set' => ['state' => 'ny']],
    ['upsert' => true]
    ** updates the table if exists, creates if not */

  foreach ($collection->listIndexes() as $indexInfo) {
  $collection->dropIndexes(); // drops all indexes on collection
installation on rhel 8.9

Then follow commands above to install pecl and library

Enable authentiction
1. create an admin user
   use admin
   createUser( { user:"myUserAdmin", pwd:"mypath",
      roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]

2. configure /etc/mongod.conf

3. now create user in the database
   user admin
   use mydb
   createUser( { user:"fancyuser", pwd:"mypass",
           roles: [ { role: "readWrite", db:"mydb"}]
4. in php configure the url for the collection connection
   $collection = new MongoDB\Client('mongodb://fancyuser:mypass@');
   e.g. mongodb://user:password@
Creating a database
Bit weird here...
1. authorize with myUserAdmin
  > use admin
  > db.auth("myUserAdmin","mypath")
  > use newdb
  >    createUser( { user:"fancyuser", pwd:"mypass",
           roles: [ { role: "readWrite", db:"newdb"}]

2. the database will not show up in user databases
   until something is written to it.

3. BUT the authorization works.

TypeScript   (PDF)
Posted February 9th, 2024

TypeScript is typed javascript that compiles to javascript It reduces errors in javascript.
These are basic takeaways from reading about typescript
So typescript is compiled javascript with strict typing.

1) Install typescript
npm i -g typescript
2) Check version
tsc -v
3) Compile stuff in .ts files to .js files
tsc -w

4) Defining variables
     let varname: type = default_value;
   types can be string, number, bigint, bool, null, undefined, symbol
   wrappers String,Number,BigInt, Boolean, Symbol
   union type: example : let foo: string|number=5;

   "any" type - not recommended - reverts to straight javascript
   const foo = document.querySelector('a')!;
   ! - indicates - non-null assertion to inform compiler
   type casting:
   const foo = document.getElementById('foobar') as HTMLFormElement;
   let flavors: 'chocolate'|'strawberry'|'blueberry';
5) reference types - arrays, objects, functions
  a) arrays
      let myarray: number[] = [1,2,4,5];
      let myarray: (number|boolean)[] = [1,true,2];
  b) tuples
      let mytuple: [string,number,boolean] = ['Danny,1,true];
  c) objects
     let person: {
          name: string;
     alive: boolean;
     person = { name:"Tom"; alive:true}; = "Mike";
  3) interfaces
     interface Person
        name: string;
    sayBye(name:string) => string;

     let something:Person {
        sayHi: function (name:string)
        return 'Hi ${name}';
       let person1:Person { name:"mike",alive:true};
  d) functions
     function funcname(arg1:type,arg2?:type):return_type
     or with es6
          const funcname = (arg1:type,arg2?:type):return_type =>
     ? means optional argument.   
     let funcname: (arg1:type):null;
  e) types
      type PersonObject= {
     age: number;

  f) classes
        class classname {
       private name: string;
        protected age: number;
        constructor(n:string,a:number) {
 = n;
          this.age = a;
        display() {
            return "Name: ${} age:${this.age}";

     let people: Person[] = [person1,person2];

    definition of scope of variables:
     readonly name: string; // This property is immutable - it can only be read
     private isCool: boolean; // Can only access or modify from methods within this class
     protected email: string; // Can access or modify from this class and subclasses
      public pets: number; // Can access or modify from anywhere - including outside the class

   g) generics
      const addID = (obj: T) => {
      let id = Math.floor(Math.random() * 1000);

      return { ...obj, id };
     interface hasLength {
      length: number;

     function logLength(a: T) {
       return a;

  h) enums
      enum states { AL="AL",


6. typescript interacts with multiple react platforms:

  •     create-react-app (TS setup)
  •     Gatsby (TS setup) Next.js
  •     Next.js (TS setup)
  • Concise tutorial:

    StarLink   (PDF)
    Posted January 10th, 2024

    A satellite internet service.

    I recently upgraded to StarLink.   I purchased the hardware through Amazon.

    It took 2-3 weeks from when I ordered it before I received the hardware.

    StarLink is an internet service run via satellites.    

    It has matured in the last several years to the point where it is usable for a developer.

    Before ordering you should check to see if its available in your area.

    Go to

    Some technical notes:

    1) I have android, and you want to set up your account on the starlink website first.

        The android setup of accounts is slightly broken... essentially when you begin

       to identify locations, the android app ends up with a blank screen.

       If you have an existing account, you can skip the blank screen issue.

    2) Once you have activated your dish, is actually

        the router on your local net.  Its useful because you can test the speed

        of the dish from the router.   In my case 83 Mbs down, 14 mbs up.

    Docker   (PDF)
    Posted December 17th, 2023

    Docker is a tool used to manage the development/QA/release process

    The term docker is often thrown around.   It turns out to be fairly complex as a it crosses

    across the developer, qa, release, and system admin roles.

    Its supposed to make all these easier and more consistent.


    1. Docker is a unix/linux/macos command line utility

        It provides utilies to push, pull images, start up the image, stop the image , remove the image. 

    2. Dockerfile is a file that specifies how to create an image for distribution.

        This is used at the point of release. 

    3. docker-compose is a command line utility that processes the file docker-compose.y[a]ml

        docker-compose.yml defines a development environment that  developer can use

        to edit/add/manage code.

    Copyright © 2024 Mind Contract, Inc.   All Rights Reserved
    For more information call or email 720-883-1866
    Powered By: Build a Member