Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb
You can simplify your code a bit by leveraging the join function to add the commas for you :)

Adbot
ADBOT LOVES YOU

Agrikk
Oct 17, 2003

Take care with that! We have not fully ascertained its function, and the ticking is accelerating.

musclecoder posted:

it looks like you're trying to insert a null or non-numeric value into a double or float type field.

It turns out this is what it is. So why can't a null be inserted into float or double field? And how do I work around this?

(I might be floating into database territory here...)

Agrikk fucked around with this message at 00:32 on Aug 3, 2022

Ranzear
Jul 25, 2013

Looks like you fed it an empty string for a double precision field, not a null. Assuming you've no use for empty strings in any field, just cull any key:value with an empty string value before preparing the statement. There's no reason to mess with your column types, just understand that an empty string is not equivalent to NULL.

Agrikk
Oct 17, 2003

Take care with that! We have not fully ascertained its function, and the ticking is accelerating.
Oh drat! I completely forgot that
code:
,,,,
represents five empty string elements, not five NULL elements. I got it working after sanitizing the array. Weeee!

Also: PDO is so, so, so very much better and easier than pg_connect or mysql_connect. And the statement prep stuff owns.

Ranzear
Jul 25, 2013

Everything else is deprecate since like PHP 5.x but I've still had to carry the torch at times, just the same as having to continue the beatings until the InnoDB usage is complete. It's gotten better over time as sites have just died off, but there's still a ton of outdated garbage tutorials out there and far too much trust in them to start.

I'm from MariaDB land though, so you had me double checking that numeric types were still nullable in postgres, lol. Feeding it empty strings was a guess really.

Ranzear fucked around with this message at 00:54 on Aug 4, 2022

SpaceAceJase
Nov 8, 2008

and you
have proved
to be...

a real shitty poster,
and a real james
I'm in perpetual PHP5 refactor hell and I don't see the end in sight.

I'm so, so tired.

Zamujasa
Oct 27, 2010



Bread Liar
i just had to change $_GET['n'] ?? "default" to an isset($_GET['n']) ? $_GET['n'] : "default", so i feel you there

astral
Apr 26, 2004

SpaceAceJase posted:

I'm in perpetual PHP5 refactor hell and I don't see the end in sight.

I'm so, so tired.

:smugdog:

SpaceAceJase
Nov 8, 2008

and you
have proved
to be...

a real shitty poster,
and a real james
I'm trying to get up to speed on modern PHP since I haven't touched it in 15 years and probably would have made these same mistakes back then too.

I think laravel is probably going to be the quickest way to migrate and rewrite this trash fire, but I'm not sure how to put the old site behind the laravel authentication.

The old app is exactly what you'd expect. Include with a check login against php session.
I've been replacing the old db connections to pdo.. discovered that moving to MySQL 8 broke some hard coded queries that aren't compatible.
Oh yeah global variables too.

It isn't worth any more headaches to keep trying to fiddle with it.

I want to give the users a laravel login, find a way to also link it to their old authentication, and then tackle each page at a time.
I also want to refactor the old database tables into a new schema. I started making views to query instead, which renamed the columns to something more consistent.

And ultimately drop the old mysql when it's all in a framework and maintainable.

Any advice would be welcome. I've had a week of sleepless nights on this and I'm second guessing a lot of the little changes I've made.

EDIT: forgot to mention the best part. It's nearly impossible to build a local dev environment because it's all linked up to dozens of undocumented shell scripts that send data over serial cables on premises to old hardware in a factory. In unpredictable ways it will just fail if it can't receive data from them.

I didn't want to test in prod so I've got a virtualhost set up... on prod, but I feel like all I can do now is continue contributing bad decisions to this.

SpaceAceJase fucked around with this message at 04:48 on Nov 4, 2022

Pile Of Garbage
May 28, 2007



SpaceAceJase posted:

EDIT: forgot to mention the best part. It's nearly impossible to build a local dev environment because it's all linked up to dozens of undocumented shell scripts that send data over serial cables on premises to old hardware in a factory. In unpredictable ways it will just fail if it can't receive data from them.

Correct me if I'm wrong but it sounds like the website you're uplifting is able to send commands directly to SCADA/PLC/OT devices in a way that may not be properly secured. Depending on what those devices are and the industry you're in this could present a massive security risk and subsequently large liability. If that's the case then you need to make sure that it is fully understood and agreed to in-writing by management that whatever you are doing to the website will not address those issues. Alternatively you could scrap the entire thing altogether and make them re-do it from the ground up.

SpaceAceJase
Nov 8, 2008

and you
have proved
to be...

a real shitty poster,
and a real james
Other than 443 https exposed to the world I'm not seeing any real security problems.
The shell scripts are running and parsing responses from some very old manufacturing equipment and obtuse old devices but this is the least of my issues with it.


I'll eventually rewrite it when I can document what is going on and why the webserver is even involved in something that should be cronjobs but I'm looking into the Chernobyl reactor core over here.


It's really just the PHP I'm trying to sort out.
I haven't slept for a couple of days dealing with this whole company and operation I've reluctantly inherited. I.e. I'm management and not spending any money on tech debt. Just the will to live

SpaceAceJase fucked around with this message at 12:21 on Nov 4, 2022

Pile Of Garbage
May 28, 2007



SpaceAceJase posted:

I haven't slept for a couple of days dealing with this whole company and operation I've reluctantly inherited. I.e. I'm management and not spending any money on tech debt. Just the will to live

You need a break buddy, don't let work destroy you.

A Real Happy Camper
Dec 11, 2007

These children have taught me how to believe.
Apologies if this belongs in the SQL questions thread, but it's more about the PHP end:

Is there a good baby's first guide to sanitizing inputs before sending an SQL query? I'm not handling any super sensitive information, this is mostly for an online bingo thing, but I'd like to at the very least learn the basics in case things go beyond this.

Right now I'm basically using
code:
...
  	$username = $_POST['username'];
  	$discord = $_POST['discord']; 
  	$contact = $_POST['contact']; //this is a checkbox
	$driver = $_POST['driver']; //this is a dropdown menu
	$team = $_POST['team']; //this is also a dropdown menu
	$saniUser = mysqli_real_escape_string($db, $username);
	$sanidiscord = mysqli_real_escape_string($db, $discord);
  	$sql_u = "SELECT * FROM users WHERE username='$saniUser'";
  	$sql_e = "SELECT * FROM users WHERE discord='$sanidiscord'";
  	$res_u = mysqli_query($db, $sql_u);
  	$res_e = mysqli_query($db, $sql_e);
...
Aside from this and removing DROP access on the user that's tied to this script, is there anything else I need to watch for? Or will this do what I need? I don't intend to use passwords, since that's not something I trust myself with at this point.

spiritual bypass
Feb 19, 2008

Grimey Drawer
Use a prepared statement instead of escaping. This tells the database which parts are code and which parts are variables to prevent injections. PDO makes this pretty easy. Consider using PDO instead of mysqli since that's what everyone else will be using in the wider world.

Ranzear
Jul 25, 2013

Use PDO. Period.

Manually escaping strings is caveman poo poo.

Agrikk
Oct 17, 2003

Take care with that! We have not fully ascertained its function, and the ticking is accelerating.
Nth-ing PDO.

I held on to mysqli for far too long because I couldn’t be assed to spend the hour to dig into the format and syntax of PDO but once I did I was angry at myself for not adopting it sooner.

It takes care of so many gotchas automatically that I had to manually deal with with mysqli.

Trust the thread when it says to adopt PDO.

Ranzear
Jul 25, 2013

If one gets their poo poo just right, PDO doesn't even need the field/column assignment boilerplate. Work within the data structure it gives you (from a SELECT ... FOR UPDATE in a transaction you heathen) and all crud involves just passing it back in.

Hence data objects. Something I wish I'd figured out sooner.

Agrikk
Oct 17, 2003

Take care with that! We have not fully ascertained its function, and the ticking is accelerating.
I am looking to generate and represent a mesh of interconnected nodes and I’m not quite sure how to do it.


I would like to generate a list of 10,000 nodes each with a random number of connections to each other. These connections would be two-way so a connection from node #100 to #200 would also be reflected as a connection from #200 to #100.

I was thinking about the following steps but am not sure how to do it programmatically:

1. Create array of 10000 nodes

2. For every node, generate an array of a random number of nodes between 1-20 and label them A-U.

3. Loop over all connections, starting with connection 1A through 10000U (or wherever) and create a random connection to a different connection point on a different node.

4. If the destination node does not have an available connection slot, then try again.


Obviously step three is doing the heavy lifting and involves creating a three element array containing [node_id, connection_point_number, connection_id] with a pair of nodes having the same connection_id.

But I’m not sure of the logic to assign connection IDs to a pair of connection points. Doing it randomly has the problem of taking a long time to generate the final links as the odds of finding a free connection slot on a mode decrease as the arrays gets filled.

How to I create a list of all available connection points and remove filled ones from the list?

Agrikk fucked around with this message at 16:25 on Feb 25, 2023

ModeSix
Mar 14, 2009

edit: nevermind, it didn't actually do it right.

ModeSix fucked around with this message at 21:42 on Feb 25, 2023

nielsm
Jun 1, 2009



Do you allow one pair of nodes to have multiple connections between them? (Or must there be at most one connection between any pair of nodes?)
Do you allow nodes to connect to themselves?
Do you allow the graph to have multiple "islands"? (Disconnected sets of nodes, where there is no possible path from a node in one island to a node in a different island.)
Do you allow any nodes to have zero connections (be a single-node island)?

The more "no" you have in the above, the harder the solution will be.

On the other hand, if you can say "yes" to all of the above, one way to do it is to determine the number of desired connections for each node ahead of time, put every node into an array as many times as it needs connections, shuffle that array, remove the two last nodes in the array and connect those with each other, repeat until you've exhausted the array.

Agrikk
Oct 17, 2003

Take care with that! We have not fully ascertained its function, and the ticking is accelerating.

nielsm posted:

Do you allow one pair of nodes to have multiple connections between them? (Or must there be at most one connection between any pair of nodes?)

No. One connection per node pair.

quote:

Do you allow nodes to connect to themselves?

Yes. As long as it wasn't the node's only connections.

quote:

Do you allow the graph to have multiple "islands"? (Disconnected sets of nodes, where there is no possible path from a node in one island to a node in a different island.)

No. This will be a single web.

quote:

Do you allow any nodes to have zero connections (be a single-node island)?

No. Every node will have at least one connection to somewhere.


I'd like this to be a single web, but I suppose that if there are multiple islands, the isolated islands would never be reachable and wouldn't be a part of the greater web. I supposer that wouldn't be bad per se, but then there would be a bunch of unreachable nodes in a list that would be distracting.

nielsm
Jun 1, 2009



If you're okay with getting Python code in the PHP thread, I tried writing something that generates a graph and at least tests whether it fulfills the entirely connected requirement.

Python code:
import random

class Node:
    def __init__(self, index):
        self.index = index
        self.edges = set()
        self.color = None

def allow_connection(n1, n2):
    # only allow connection if nodes are not already connected
    return n2 not in n1.edges and n1 not in n2.edges

def initial_connect_nodes(count, min_connections, max_connections):
    # make initial array of nodes
    nodes = [Node(i) for i in range(count)]
    # make a list of a random number of references to every node, one ref for each connection desired from that node
    to_connect = [node for node in nodes for _ in range(random.randint(min_connections, max_connections))]
    # shuffle the connection order
    random.shuffle(to_connect)
    # ensure that there is an even number of nodes, since we need to connect them in pairs
    if len(to_connect) % 2 == 1: to_connect.append(to_connect[0])
    # generate connections
    for i in range(0, len(to_connect) - 1, 2):
        # pick the front two nodes in the list
        n1, n2 = to_connect[i], to_connect[i+1]
        # check if the nodes are allowed to connect, find another node if not
        j = i + 1
        while not allow_connection(n1, n2):
            j += 1
            # fail if we run out of nodes (none of the remaining nodes are allowed for connection)
            if j >= len(to_connect): return None
            # swap current n2 candidate backwards in the array and pick a new one
            to_connect[i+1], to_connect[j] = to_connect[j], to_connect[i+1]
            n2 = to_connect[i+1]
        # connect the nodes
        n1.edges.add(n2)
        n2.edges.add(n1)
    return nodes

def colorize_nodes(nodes):
    # wash the colors off
    for n in nodes:
        n.color = None
    # begin painting
    nextcolor = 0
    for start_node in nodes:
        # if node is already colored, don't process
        if start_node.color is not None: continue
        # otherwise assign the next available color to it
        start_node.color = nextcolor
        nextcolor += 1
        # now visit all reachable nodes and paint them too
        stack = list(start_node.edges)
        while len(stack) > 0:
            # grab one node from the stack
            n = stack.pop()
            # if it's already painted skip it
            if n.color is not None: continue
            # otherwise paint it
            n.color = start_node.color
            # and push all nodes connected to it too
            stack.extend(n.edges)
    # the nextcolor variable will also be the count of unique colors assigned
    return nextcolor

nodes = None
tries = 0
while nodes is None:
    tries += 1
    nodes = initial_connect_nodes(10000, 1, 20)
num_colors = colorize_nodes(nodes)

print(f"Generated initial graph with {len(nodes)} nodes in {tries} tries, it has {num_colors} colors")
#for n in nodes:
#    edgeindexes = ', '.join(str(e.index) for e in n.edges)
#    print(f"Node {n.index} (color {n.color}) is connected to nodes: {edgeindexes}")
This generates a graph in 0.1 seconds on my machine, and about 25% of the time that graph will be entirely connected, so you can just re-run it until you get something usable.
Otherwise, it would be possible to write some algorithm to attempt to connect the disconnected islands too, probably something like pick two islands, select the least connected nodes in each island, and connect them pairwise, and repeat until the entire graph is connected.

nielsm fucked around with this message at 23:08 on Feb 26, 2023

Ranzear
Jul 25, 2013

Agrikk posted:

3. Loop over all connections, starting with connection 1A through 10000U (or wherever) and create a random connection to a different connection point on a different node.

[...]

But I’m not sure of the logic to assign connection IDs to a pair of connection points. Doing it randomly has the problem of taking a long time to generate the final links as the odds of finding a free connection slot on a mode decrease as the arrays gets filled.

If you have 10k nodes numbered 0-9999, just pick a number. Additionally, why still be checking against filled nodes at all?

My method:

Put references to all nodes in an array, basically a temporary index mapped to their real index. This is the arena. Also create an empty array of 'purged' nodes.

Iterate the arena. For each reference:
  • If the current arena index is in the purge array, skip it (continue is your friend).
  • Pick a number between 0 and the arena length for a target to connect.
  • Check the target's arena index isn't in the purge array, else skip (rerolling might be slower, but also works).
  • Check references aren't already connected (or isn't self-connection), else make the two-way connection.
  • If current node has reached 20 connections or whatever other heuristic it has, push its arena index on the purge array.
  • If target node has reached its heuristic, push its arena index on the purge array.

Once iterated, remove all the purged nodes from the arena, empty the purge array, and run again (PHP's unset() can just take the purge array directly iirc, could be some black magic needed.)
When the arena is empty (or manages to run without making a new connection, could be a weird case,) you're done. There's still some 'dead hits' in each loop but they all get consumed eventually.

It shouldn't be necessary to shuffle the arena at each step, but low indexes might get a little bias if you reroll in the iteration instead of skipping so throw it in if you do. Searching the purge list should be fast enough to not worry about because it isn't carried across iterations. This doesn't guarantee full connectivity, but I think that's a way harder problem.

Changing the heuristic is now easier too; it can just be a function call defined by whatever type of node itself, and you can even mix node heuristics in the same connection map. And for instance: If you want a variable limit on number of connections for a node, store the max connections in the node and the heuristic checks against that.

Ranzear fucked around with this message at 23:55 on Feb 26, 2023

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
How "random" does this need to be? Do you need to generate the number of connections at each node according to some distribution, or is it enough that it just looks arbitrary?

How I'd go about it:
- For each node, add a link to a random node lower than it. This guarantees the graph is connected.
- Randomly add links between two nodes that aren't already linked (randomly pick a node, randomly pick a node that it's not already connected to) until you've reached the desired density of links.
- Shuffle the order of nodes in the list, if you need to hide the structure introduced in the first step.

Ranzear
Jul 25, 2013

Jabor posted:

- For each node, add a link to a random node lower than it. This guarantees the graph is connected.

I like this a lot. I retract my statement about it being hard, though I think this generates fewer loops and looks more linear or tree like in the end as it consumes the connection limit of lower indexes early. Maybe linearity is necessary to be complete.

I also like the final shuffle, but I was under the impression the nodes had to hold their own connections in the end for things to be traversable instead of a list of edges. I suppose this matches my arena shuffling and just plug the edges in at the end.

Ranzear fucked around with this message at 00:14 on Feb 27, 2023

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
This is why I was asking about the distribution of number-of-connections - the problem gets much easier if you can just generate links randomly and trust that the final distribution will be good enough for your purposes. Generating a random distribution up-front and then trying to generate a network that exactly fits that distribution while also meeting your other criteria is a lot trickier.

ModeSix
Mar 14, 2009

Here's a solution ChatGPT gave me after a bit of massaging.

php:
<?php

// Step 1: Create an array of 10,000 nodes
$nodes = array();
for ($i 0$i 10000$i++) {
    $nodes[$i] = array();
}

// Step 2: Generate random connections for each node
$letters range('A''U');

// Step 2a: Create the "main group" of nodes
$main_group = array();
for ($i 0$i 1000$i++) {
    $main_group[] = rand(09999);
}
shuffle($main_group);
foreach ($main_group as $i => $node) {
    $num_connections min(count($main_group) - 1rand(120));
    $available_connections array_diff($main_group, array($node));
    shuffle($available_connections);
    for ($j 0$j $num_connections$j++) {
        $connection_letter $letters[$j];
        $connection_node $available_connections[$j];
        $nodes[$node][$connection_letter] = $connection_node;
        $nodes[$connection_node][$connection_letter] = $node;
    }
}

// Step 2b: Connect the remaining nodes to the main group
$remaining_nodes array_diff(array_keys($nodes), $main_group);
foreach ($remaining_nodes as $i => &$node) {
    $num_connections rand(120);
    $available_connections array_merge($main_grouparray_diff($remaining_nodes, array($node)));
    shuffle($available_connections);
    for ($j 0$j $num_connections$j++) {
        $connection_letter $letters[$j];
        $connection_node $available_connections[$j];
        $nodes[$node][$connection_letter] = $connection_node;
        $nodes[$connection_node][$connection_letter] = $node;
    }
}
?>

It appears to work.

ModeSix fucked around with this message at 03:01 on Feb 27, 2023

Agrikk
Oct 17, 2003

Take care with that! We have not fully ascertained its function, and the ticking is accelerating.

ModeSix posted:

Here's a solution ChatGPT gave me after a bit of massaging.

php:
<?php

// Step 1: Create an array of 10,000 nodes
$nodes = array();
for ($i 0$i 10000$i++) {
    $nodes[$i] = array();
}

// Step 2: Generate random connections for each node
$letters range('A''U');

// Step 2a: Create the "main group" of nodes
$main_group = array();
for ($i 0$i 1000$i++) {
    $main_group[] = rand(09999);
}
shuffle($main_group);
foreach ($main_group as $i => $node) {
    $num_connections min(count($main_group) - 1rand(120));
    $available_connections array_diff($main_group, array($node));
    shuffle($available_connections);
    for ($j 0$j $num_connections$j++) {
        $connection_letter $letters[$j];
        $connection_node $available_connections[$j];
        $nodes[$node][$connection_letter] = $connection_node;
        $nodes[$connection_node][$connection_letter] = $node;
    }
}

// Step 2b: Connect the remaining nodes to the main group
$remaining_nodes array_diff(array_keys($nodes), $main_group);
foreach ($remaining_nodes as $i => &$node) {
    $num_connections rand(120);
    $available_connections array_merge($main_grouparray_diff($remaining_nodes, array($node)));
    shuffle($available_connections);
    for ($j 0$j $num_connections$j++) {
        $connection_letter $letters[$j];
        $connection_node $available_connections[$j];
        $nodes[$node][$connection_letter] = $connection_node;
        $nodes[$connection_node][$connection_letter] = $node;
    }
}
?>

It appears to work.

Well drat. I just ran this and it looks pretty good.

chatGPT is now something I need to look into more closely.

Ranzear
Jul 25, 2013

You'll spend more time futzing with it and then vetting what it spits out than it would take to write it yourself, cleaner to read, faster, and more expansible, in the first place.

My post above can be extended, relying on having both temporary and real indexes available, to make a fully connected graph:

Create a second empty array, call this the core.

Add these steps to iterating:
    At start:
  • If core is empty, add this node's real index to core (not arena index)
    After connecting nodes but before heuristic:
  • If this node's real index is in core , add real indexes of all connected nodes to core
    Integrate with heuristic functions:
  • If node not yet in core list, don't pass heuristic.

In this form it'll add additional connections until the graph is complete, or the heuristic can be checked early and the connection rerolled until it finds a core node if there's only one slot left. It's just important that connected nodes are added to core before the parent node is removed from arena. This is also now a case where a pass can go without making a new connection, all core nodes already being saturated, and I'd just start it over. In most any other language core should be a tree for decent speed.

Ranzear fucked around with this message at 00:55 on Feb 28, 2023

ModeSix
Mar 14, 2009

Ranzear posted:

You'll spend more time futzing with it and then vetting what it spits out than it would take to write it yourself, cleaner to read, faster, and more expansible, in the first place.

I definitely agree with this statement and can attest I had to get it to redo a few things a few times to get it to a useable state.

The code I put up above is by no means optimal or easy to read. It gets the job done, sub optimally, but as Ranzear said how expandable or flexible it is is likely low.

Agrikk
Oct 17, 2003

Take care with that! We have not fully ascertained its function, and the ticking is accelerating.
The reason I'm generating the list of exits early is because I want the average count of exits to be around 4, with a steep dropoff at 1 exit (less than 5% of nodes will have only 1 exit, 30% will have 3-4 exits and there will be a long tail out to a 1% chance each of a node having 16,17,18,19 or 20 exits. With a completely random system, each node will have around ten exits and will make the mesh rather uniform instead of having "super connector" nodes which is more appealing to me for ~reasons~.


I've been noodling with different methods, because why not, and I tried Ranzear's method:

code:
create two identical data sets in two arrays, ArrayA[node_id][list_of_exit_slots] and ArrayB[node_id][list_of_exit_slots]

While count(ArrayA[node_id] > 0)
   Using array_rand, pick a node_id from ArrayA and a node from ArrayB
       if 
            ArrayA[node_id] = ArrayB[node_id] then go back and try again
       else 
            populate connectionArray with [nodeA_id][nodeA_highest_numbered_exit_slot] and [nodeB_id][nodeB_highest_numbered_exit_slot]
            unset ArrayA[nodeA_id][nodeA_highest_numbered_exit_slot]
            unset ArrayB[nodeB_id][nodeB_highest_numbered_exit_slot]
	    if count(ArrayA[node_id][list_of_exit_slots] is zero)
                     unset(ArrayA[node_id])
	    if count(ArrayB[node_id][list_of_exit_slots] is zero)
                     unset(ArrayB[node_id])
By removing an exit slot each time one is used, and by removing the node when it not longer has any available slots, I ensure that a node won't link to itself and every node is connect to at least another node. The problem of course is that the posibility exists of islands forming due to the randomness of the selection process (A could link to B which could linkto C which could linkback to A).


Which now raises another question: How to write the code to walk this mesh, finding the most direct path between two randomly chosen nodes?

Agrikk fucked around with this message at 17:00 on Mar 1, 2023

nielsm
Jun 1, 2009



Agrikk posted:


Which now raises another question: How to write the code to walk this mesh, finding the most direct path between two randomly chosen nodes?

Look up "single source shortest path algorithm", there are multiple famous algorithms for it.

Agrikk
Oct 17, 2003

Take care with that! We have not fully ascertained its function, and the ticking is accelerating.

nielsm posted:

Look up "single source shortest path algorithm", there are multiple famous algorithms for it.

Thanks for this. Little did I realize that my little project would dive so deep into trees and “weird math”. :)

kiwid
Sep 30, 2013

I'm using Laravel and have to work with a database from another piece of software using a read-only connection to pull in various data.

I want to model some of the tables(views) so I can use eloquent relationships but the problem is that this database makes heavy usage of composite keys which eloquent doesn't support.

So I find myself doing poo poo like this where I concat all of the keys to one column. It's working... but I'm wondering if I'll run into any issues doing this that I'm not aware of.

SQL code:
        DB::statement(
            <<<SQL
                CREATE OR ALTER VIEW [mixers]
                AS
                SELECT
                    CONCAT_WS('-', LOWER([prd_mixer].[plc_id]), LOWER([prd_mixer].[mixer_id])) AS [id],
                    LOWER([prd_mixer].[plc_id]) AS [location_id],
                    [prd_mixer].[mixer_id] AS [name],
                    [prd_mixer].[description],
                    [prd_mixer].[mixer_size] AS [size],
                    [prd_mixer].[uom_code]
                FROM [{$agtech_database}].[dba].[prd_mixer] WITH (NOLOCK)
                WHERE [prd_mixer].[plc_id] IN ('seed', 'seed-palm');
            SQL
        );
SQL code:
        DB::statement(
            <<<SQL
                CREATE OR ALTER VIEW [batch_tickets]
                AS
                SELECT
                    CONCAT_WS('-', LOWER([prd_batch_ticket_entry].[plc_id]), [prd_batch_ticket_entry].[ticket_nbr]) AS [id],
                    LOWER([prd_batch_ticket_entry].[plc_id]) AS [location_id],
                    [prd_batch_ticket_entry].[ticket_nbr],
                    [prd_batch_ticket_entry].[revision_nbr],
                    [prd_batch_ticket_entry].[order_status],
                    [prd_batch_ticket_entry].[order_qty],
                    [prd_batch_ticket_entry].[order_uom],
                    [prd_batch_ticket_entry].[number_of_batches],
                    [prd_batch_ticket_entry].[comments],
                    [prd_batch_ticket_entry].[printed_flag],
                    [prd_batch_ticket_entry].[required_date],
                    [prd_batch_ticket_entry].[status_change_date],
                    LOWER([prd_batch_ticket_entry].[commodity_id]) AS [commodity_id],
                    CONCAT_WS('-', LOWER([prd_batch_ticket_entry].[plc_id]), LOWER([prd_batch_ticket_entry].[mixer_id])) AS [mixer_id],
                    CONCAT_WS('-', LOWER([prd_batch_ticket_entry].[plc_id]), LOWER([prd_batch_ticket_entry].[formula_id]), [prd_batch_ticket_entry].[revision_nbr]) AS [formula_id]
                FROM [{$agtech_database}].[dba].[prd_batch_ticket_entry] WITH (NOLOCK)
                WHERE [prd_batch_ticket_entry].[plc_id] IN ('seed', 'seed-palm');
            SQL
        );

SpaceAceJase
Nov 8, 2008

and you
have proved
to be...

a real shitty poster,
and a real james
Is Laravel Livewire worth looking at? I tried a few demo apps hosted remotely and performance didn't seem great on a simple toggle switch

kiwid
Sep 30, 2013

SpaceAceJase posted:

Is Laravel Livewire worth looking at? I tried a few demo apps hosted remotely and performance didn't seem great on a simple toggle switch

I love it, I use it in all my apps. As for performance, it's just Ajax behind the scenes so I'm not sure why you'd be having issues. I've used it on toggles that respond instantly.

Agrikk
Oct 17, 2003

Take care with that! We have not fully ascertained its function, and the ticking is accelerating.
How do I delete multiple spaces in a row but leave a single whitespace in a string?

Given a file containing this:

code:
  Status | (#)Sensor                |      Reading | Low Limit | High Limit |
  ------ | ---------                |      ------- | --------- | ---------- |
  OK     | (4) CPU Temp             |     44C/111F |    0C/32F |   98C/208F |
  OK     | (71) System Temp         |     41C/106F |   -7C/19F |   85C/185F |
  OK     | (138) Peripheral Temp    |     38C/100F |   -7C/19F |   85C/185F |
  OK     | (205) PCH Temp           |     57C/135F |   -8C/18F |   95C/203F |
  OK     | (272) FAN 1              |     1050 RPM |   450 RPM |  19050 RPM |
         | (339) FAN 2              |          N/A |       N/A |        N/A |
         | (406) FAN 3              |          N/A |       N/A |        N/A |
         | (473) FAN 4              |          N/A |       N/A |        N/A |
         | (540) FAN A              |          N/A |       N/A |        N/A |
  OK     | (607) Vcore              |       0.88 V |    0.51 V |     1.52 V |
  OK     | (674) 3.3VCC             |       3.31 V |    2.88 V |     3.64 V |
  OK     | (741) 12V                |      12.08 V |    10.6 V |    13.19 V |
  OK     | (808) VDIMM              |       1.51 V |    1.21 V |     1.77 V |
  OK     | (875) 5VCC               |       5.05 V |    4.32 V |      5.6 V |
  OK     | (942) CPU VTT            |       1.06 V |    0.89 V |     1.36 V |
  OK     | (1009) VBAT              |       3.23 V |    2.88 V |     3.64 V |
  OK     | (1076) VSB               |       3.34 V |    2.88 V |     3.64 V |
  OK     | (1143) AVCC              |       3.31 V |    2.88 V |     3.64 V |
  OK     | (1210) Chassis Intru     |                  OK                   |
Right now I'm collecting each line with fgets and then exploding on '|' but that leaves me with array values with lots of leading and trailing white spaces. For each line, or each array item, I'd like to strip out all of the white spaces betweeb the pipe delimiters, but keep the white space between the number and the unit.

Agrikk fucked around with this message at 22:38 on Sep 26, 2023

spacebard
Jan 1, 2007

Football~

Agrikk posted:

How do I delete multiple spaces in a row but leave a single whitespace in a string?

The function trim will remove leading and trailing white space characters from a string. Similar to other programming languages.

Mind_Taker
May 7, 2007



I'd just do a regex replace using preg_replace to get it done in a single line of code.

Adbot
ADBOT LOVES YOU

duz
Jul 11, 2005

Come on Ilhan, lets go bag us a shitpost


PHP has functions specifically for dealing with CSV data. Combine it with array_map and you're set.

php:
<?php

$handle fopen($filename"r");
while (false !== ($data fgetcsv($handle1000"|"))) {
    $clean_row array_map("trim"$data);
    // Recombine it, display it, do whatever with it
}
fclose($handle);

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply