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
musclecoder
Oct 23, 2006

I'm all about meeting girls. I'm all about meeting guys.
I would really avoid using just a simple token as part of the URL like https://example.com/auth.php?token=abc123

The reason is because often GET parameters are logged and between that request and the server there are lots of places that token could be logged (since even over an HTTPS connection the URL is obviously plaintext).

If you have to do authentication over a single link, I'd look into OAuth (though it's not very friendly), or making the request come as a POST request (over HTTPS of course) so the token is encrypted and not logged.

Adbot
ADBOT LOVES YOU

DholmbladRU
May 4, 2006
Yeah I can change it to pass the token in the post

v1nce
Sep 19, 2004

Plant your brassicas in may and cover them in mulch.

musclecoder posted:

The reason is because often GET parameters are logged and between that request and the server there are lots of places that token could be logged (since even over an HTTPS connection the URL is obviously plaintext)

I think I'm just reading this incorrectly, but I want to make sure my understanding is correct;

The URL and GET parameters are encrypted over an SSL (HTTPS) connection, so to anything between your client and the server, nothing can be read.
However, GET parameters will most likely be logged on the server by something like Varnish or Apache or whatever. This is where your sensitive information might end up getting stored, which is a bad thing.

Is that right?

Regardless I agree with the point about using OAuth, or using POST to avoid the logging issue.

musclecoder
Oct 23, 2006

I'm all about meeting girls. I'm all about meeting guys.
Well, the URL and query string parameters aren't secure in an HTTPS request. Hence, you can see https://example.com/auth.php?token=abc123. And that URL can be logged anywhere between the client and server. So yes, Apache logs, Varnish logs, router logs, ISP logs, anywhere those packets hop with that information can be logged.

With an HTTPS session, the POST data is encrypted so even if it were logged it would be meaningless.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

musclecoder posted:

Well, the URL and query string parameters aren't secure in an HTTPS request.

This is incorrect. HTTPS encrypts the entire HTTP connection, headers as well as the payload. The only thing an outside observer can see is things transmitted at a lower level - the IP:port number addresses at each end of the connection, the approximate amount of data sent in each direction, etc.

There are a bunch of reasons not to put the token as a URL parameter, but "people might sniff it even over https" isn't really one of them.

Impotence
Nov 8, 2010
Lipstick Apathy

Jabor posted:

This is incorrect. HTTPS encrypts the entire HTTP connection, headers as well as the payload. The only thing an outside observer can see is things transmitted at a lower level - the IP:port number addresses at each end of the connection, the approximate amount of data sent in each direction, etc.

There are a bunch of reasons not to put the token as a URL parameter, but "people might sniff it even over https" isn't really one of them.

Hostname of the site you're trying to access too

musclecoder
Oct 23, 2006

I'm all about meeting girls. I'm all about meeting guys.

Jabor posted:

This is incorrect. HTTPS encrypts the entire HTTP connection, headers as well as the payload. The only thing an outside observer can see is things transmitted at a lower level - the IP:port number addresses at each end of the connection, the approximate amount of data sent in each direction, etc.

There are a bunch of reasons not to put the token as a URL parameter, but "people might sniff it even over https" isn't really one of them.

Not if the payload is part of the URL, which in a GET request, it is. I know the headers and POST parameters are encrypted, but obviously the GET parameters aren't (GET requests can't have a payload body either).

Impotence
Nov 8, 2010
Lipstick Apathy

musclecoder posted:

Not if the payload is part of the URL, which in a GET request, it is. I know the headers and POST parameters are encrypted, but obviously the GET parameters aren't (GET requests can't have a payload body either).

GET is part of header. It's encrypted (at least the /path/x?y=69 is, not the Hostname).
You do a CONNECT first, pass host/handshake, then pass GET/POST encrypted

spacebard
Jan 1, 2007

Football~

musclecoder posted:

Not if the payload is part of the URL, which in a GET request, it is. I know the headers and POST parameters are encrypted, but obviously the GET parameters aren't (GET requests can't have a payload body either).

e;fb on this during preview, but ...
No, the entire HTTP request is encrypted per the spec. The client initiates SSL connection first, and then sends the HTTP request. The server, of course, will have the decrypted request and will probably log the URI any query parameters.

And the HTTP specification does not explicitly prohibit GET request from sending a body, but it is not specifically supported either. It's just understand that applications should behave as good citizens and respect GET semantics.

Doh004
Apr 22, 2007

Mmmmm Donuts...
I'm trying to update an old rear end php/mysql application of mine. Anyone have any suggestions for handling deployment to various environments? Any suggested tools? I have my apache web server with the main domain and a test environment.

Do I need to write a script that ssh's onto the remote server, clones the repo and moves those files into the proper location?

Heskie
Aug 10, 2002

Doh004 posted:

I'm trying to update an old rear end php/mysql application of mine. Anyone have any suggestions for handling deployment to various environments? Any suggested tools? I have my apache web server with the main domain and a test environment.

Do I need to write a script that ssh's onto the remote server, clones the repo and moves those files into the proper location?

I'd just use Capistrano.

A PHP-based alternative I've used before is Deployer if you'd rather not add Ruby deps to your repo, but personally I'd go with Capistrano as its well maintained, widely used etc.

musclecoder
Oct 23, 2006

I'm all about meeting girls. I'm all about meeting guys.

spacebard posted:

e;fb on this during preview, but ...
No, the entire HTTP request is encrypted per the spec. The client initiates SSL connection first, and then sends the HTTP request. The server, of course, will have the decrypted request and will probably log the URI any query parameters.

And the HTTP specification does not explicitly prohibit GET request from sending a body, but it is not specifically supported either. It's just understand that applications should behave as good citizens and respect GET semantics.

Got it, I stand corrected then. Thanks for the heads up, spacebard and Biowarfare and v1nce.

Doh004 posted:

I'm trying to update an old rear end php/mysql application of mine. Anyone have any suggestions for handling deployment to various environments? Any suggested tools? I have my apache web server with the main domain and a test environment.

Do I need to write a script that ssh's onto the remote server, clones the repo and moves those files into the proper location?

That's actually something I do know about! Yes, use Capistrano. I wrote a whole book on the subject - https://leftnode.org/posts/expert-php-deployments.html (though it could probably use some updates).

Doh004
Apr 22, 2007

Mmmmm Donuts...

Heskie posted:

I'd just use Capistrano.

A PHP-based alternative I've used before is Deployer if you'd rather not add Ruby deps to your repo, but personally I'd go with Capistrano as its well maintained, widely used etc.

Capistrano was perfect, thanks! Barring some stupid server related configurations, I got it working so I can easily deploy to my test environment. This project is 6 years old and I just now put it into git. Previously it was just in my dropbox account.

Oh boy.

musclecoder posted:

That's actually something I do know about! Yes, use Capistrano. I wrote a whole book on the subject - https://leftnode.org/posts/expert-php-deployments.html (though it could probably use some updates).

Awesome! Bookmarked and thank you :)

Peanut and the Gang
Aug 24, 2009

by exmarx

musclecoder posted:

That's actually something I do know about! Yes, use Capistrano. I wrote a whole book on the subject - https://leftnode.org/posts/expert-php-deployments.html (though it could probably use some updates).

It's a good book. I read it and now I have a beastly setup where I can do atomic deploys with one command.

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

Jabor posted:

There are a bunch of reasons not to put the token as a URL parameter, but "people might sniff it even over https" isn't really one of them.

Another one is that it shouldn't be so easy for somebody to compromise their session simply by copying and pasting a link.

Impotence
Nov 8, 2010
Lipstick Apathy

fletcher posted:

Another one is that it shouldn't be so easy for somebody to compromise their session simply by copying and pasting a link.

Do they not hash any part of user agent or a few IP octets or whatever as part of the session?

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

Biowarfare posted:

Do they not hash any part of user agent or a few IP octets or whatever as part of the session?

Both of those can be spoofed, no? User agent can of course, I'm not positive about the IP address though.

Impotence
Nov 8, 2010
Lipstick Apathy

fletcher posted:

Both of those can be spoofed, no? User agent can of course, I'm not positive about the IP address though.
The point is more that if someone "accidentally" links their session ID across, when someone else clicks it initially or accesses it, it will destroy the session and log out all of the account's sessions with a notice, or ignore their "login"; if you are getting cookies or urls stolen via XSS you have larger problems

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

Biowarfare posted:

The point is more that if someone "accidentally" links their session ID across, when someone else clicks it initially or accesses it, it will destroy the session and log out all of the account's sessions with a notice, or ignore their "login"; if you are getting cookies or urls stolen via XSS you have larger problems

That's assume the other person clicking on it isn't clever and malicious. If they are, maybe they know to spoof the user agent and IP before attempting to hijack the session.

v1nce
Sep 19, 2004

Plant your brassicas in may and cover them in mulch.

musclecoder posted:

That's actually something I do know about! Yes, use Capistrano. I wrote a whole book on the subject - https://leftnode.org/posts/expert-php-deployments.html (though it could probably use some updates).

I meant to quote this before. I love this book/tutorial and I'm pushing hard to get this kind of setup for our multi-server deployment which is currently managed by hand by one guy.

You say it could use some updates - If they're significant (and not just nit-pick version differences) i'd be happy to read them as a foot-note update to the post. Any more information on "stuff to look out for" is always useful.

musclecoder
Oct 23, 2006

I'm all about meeting girls. I'm all about meeting guys.

v1nce posted:

I meant to quote this before. I love this book/tutorial and I'm pushing hard to get this kind of setup for our multi-server deployment which is currently managed by hand by one guy.

You say it could use some updates - If they're significant (and not just nit-pick version differences) i'd be happy to read them as a foot-note update to the post. Any more information on "stuff to look out for" is always useful.

Thanks Peanut and the Gang and v1nce. Two big updates I want to issue is updating to Capistrano 3 (and providing a lot more information on deployments, database rollbacks, build process, etc) and using an automated server management tool (I'm learning Chef so it would most likely be it). Those have been the two biggest requests.

I'll post in this thread when I eventually get around to making them.

IT BEGINS
Jan 15, 2009

I don't know how to make analogies
Outside of using an ORM, are there any best practices for loading complex objects from the front-end into their schemas in the back-end? My current situation is this: customers provide me with CSV invoice data that I need to load into a particular database schema. A simple version of it is the following:

code:
Invoice
  id
  field_1
  field_2

Address
  invoice_id
  id
  street
  zip_code

Charge
  invoice_id
  id
  type
  amount
I receive lines from the front-end that look like this:

code:
invoice_id,field_1,field_2,street_1,zip_code_1,street_2,zip_code_2,charge_type,charge_amount
1, x, x, High Street, 38402, Low Street, 48934, Freight, $30.00
1, x, x, High Street, 38402, Low Street, 48934, Fuel, $10.00
Is there a particular library that could help me work with this kind of stuff? Should I be using an ORM (I may not be able to use an ORM)?

McGlockenshire
Dec 16, 2005

GOLLOCKS!

IT BEGINS posted:

Outside of using an ORM, are there any best practices for loading complex objects from the front-end into their schemas in the back-end? My current situation is this: customers provide me with CSV invoice data that I need to load into a particular database schema. A simple version of it is the following: [...] Is there a particular library that could help me work with this kind of stuff? Should I be using an ORM (I may not be able to use an ORM)?

Unless each of those invoice line items are already objects in your system, then an ORM is not immediately helpful here.

You might still want them to be data objects, if they aren't. Look up the Data Mapper pattern. Doctrine is an implementation. Heavyweight, but well regarded. I've enjoyed my time with Spot, but it causes the data objects to break the SRP and it's still immature. Defining and using relationships is distinctly weird.

Avoid ActiveRecord-based ORMs and any ORM that uses static methods.

substitute
Aug 30, 2003

you for my mum
Help! I'm trying to work out proper dependency injection. Does the following seem logical in any way, or is it one step too many, not enough, etc?? I don't know anymore...


php:
<?
// App.php
class App
{
    public function __construct(PDO $pdo)
    {
        // create db handle
        $this->db = $pdo;

        // etc...
    }

    // more general App methods/properties, etc...
    
    public function butts()
    {
        // stuff ... 
        return $this->db->somePDOfunc($whatevs);
    }
}



// Derp.php
Class Derp
{
    public function __construct(App $app)
    {
        $this->app = $app;
    }

    
    // methods using App's stuff via $this->app...

    // ex.
    public function derp($blah)
    {
        if ($blah == true) {
            return $this->app->butts();
        }
    }

}



// SomeScript.php

// define $dsn, $db_user, $db_pass, $db_opts

$PDO = new PDO($dsn, $db_user, $db_pass, $db_opts);

$App = new App($PDO);

$Derp = new Derp($App);

var_dump($Derp->app->derp());

?>

v1nce
Sep 19, 2004

Plant your brassicas in may and cover them in mulch.
Yeah, that looks about accurate. You're passing the classes the things they depend on (PDO, App) via the constructors, which is basic dependency injection.
One of the keys to DI is looking at your class and seeing if you can use it just by itself, provided you pass in the things it needs. You normally do this because then you can actually unit test your code.
If you take DI to the Nth degree, you'll be passing in Factories/Services that can produce other types of classes, meaning you don't use new ClassName() unless you're in a factory class.

You don't have any kind of service manager, which isn't the end of the world for code this basic; right at the end you're just thowing together your classes in the order they need to be, which is basically the just of the service manager, and something that might happen by configuration in frameworks like Symfony. There's a few stand-alone DI classes out there, but they're not exactly "simple" implementations:
http://pimple.sensiolabs.org/
http://php-di.org/

There's arguments out there about pros/cons of using getter/setter functions for DI, too. A basic rule of thumb is this; if your class needs a dependency in order for it to work at all, it should be passed into the constructor. If it's an optional dependency, use a public setter. If you decide to use a getter to access your dependency rather than just a protected/private member, that's entirely up to personal taste. Personally, I avoid this method because people tend to make getters public and then that encourages DI to be broken further down the track.

Here's a quick example to echo your own:
php:
<?

class UserController
{
    /** @var EmailService */
    protected $emailService;

    /** @var RenderService */
    protected $renderService;

    /** @var UserService */
    protected $userService;

    /**
     * @param EmailService $emailService
     * @param RenderService $renderService
     * @param UserService $userService
     */
    public function __construct(EmailService $emailService, RenderService $renderService, UserService $userService)
    {
        $this->emailService = $emailService;
        $this->renderService= $renderService;
        $this->userService= $userService;
    }

    /**
     * @param string $name
     * @param string $email
     * @return RenderThingie
     */
    public function createUserAction($name, $email)
    {
        $user = $this->userService->addUser($name, $email);
        $this->emailContainer->sendWelcomeEmail($user);

        $renderer = $renderService->getHtmlRenderer();
        $renderer->setParameter('user', $user);
        return $renderer;
    }
}

class UserService
{
    /** @var PDO */
    protected $pdo;

    /**
     * @param PDO $pdo
     */
    public function __construct(PDO $pdo)
    {
        $this->pdo= $pdo;
    }

    /**
     * @param string $name
     * @param string $email
     */
    public function addUser($name, $email)
    {
        // Build a user class
        $user = new User();
        $user->setName($name);
        $user->setEmail($email);

        // TODO: PDO save
        // $this->pdo->doAThing($user);
        return $user;
    }
}


// Without a DI container
// TODO: Email and Render services etc
$pdo = new PDO();
$userService = new UserService($pdo);
$controller = new UserController($emailService, $renderService, $userService);

// With a DI container (TODO: DI configuration elsewhere)
// The main point is, you don't have to sort out the dependency chain where you're calling your service.
$controller = $container->get('controller.user');

$output = $controller->addUser('jeff', 'jeff@example.com');
$output->render();
?>
There's a lot wrong with this example; like building the User object in the User service, lack of validation, not using interfaces or blah blah blah. But for DI, you get the idea.

IT BEGINS
Jan 15, 2009

I don't know how to make analogies

McGlockenshire posted:

Unless each of those invoice line items are already objects in your system, then an ORM is not immediately helpful here.

You might still want them to be data objects, if they aren't. Look up the Data Mapper pattern. Doctrine is an implementation. Heavyweight, but well regarded. I've enjoyed my time with Spot, but it causes the data objects to break the SRP and it's still immature. Defining and using relationships is distinctly weird.

Avoid ActiveRecord-based ORMs and any ORM that uses static methods.

Thanks. I've been looking at Doctrine to see how it builds object graphs but it's a bit more complex than I need it to be. Spot looks like it will be very helpful, at the very least to get a better understanding of things.

I'm surprised that I'm not able to find many resources on creating object graphs. I imagined it would be a problem that's been tackled quite often. :shrug:

substitute
Aug 30, 2003

you for my mum

v1nce posted:

Yeah, that looks about accurate. You're passing the classes the things they depend on (PDO, App) via the constructors, which is basic dependency injection.
One of the keys to DI is looking at your class and seeing if you can use it just by itself, provided you pass in the things it needs. You normally do this because then you can actually unit test your code.
If you take DI to the Nth degree, you'll be passing in Factories/Services that can produce other types of classes, meaning you don't use new ClassName() unless you're in a factory class.

You don't have any kind of service manager, which isn't the end of the world for code this basic; right at the end you're just thowing together your classes in the order they need to be, which is basically the just of the service manager, and something that might happen by configuration in frameworks like Symfony. There's a few stand-alone DI classes out there, but they're not exactly "simple" implementations:
http://pimple.sensiolabs.org/
http://php-di.org/

There's arguments out there about pros/cons of using getter/setter functions for DI, too. A basic rule of thumb is this; if your class needs a dependency in order for it to work at all, it should be passed into the constructor. If it's an optional dependency, use a public setter. If you decide to use a getter to access your dependency rather than just a protected/private member, that's entirely up to personal taste. Personally, I avoid this method because people tend to make getters public and then that encourages DI to be broken further down the track.

Here's a quick example to echo your own:
php:
<?
...?>
There's a lot wrong with this example; like building the User object in the User service, lack of validation, not using interfaces or blah blah blah. But for DI, you get the idea.

Thanks, that helped. While I basically understand the concept and why, the things I've read on DI always seemed to add more layers pretty quickly. That has been the struggle for me.

itskage
Aug 26, 2003


I have a Dev out for a couple weeks with some family issues so I am tackling some of our website bugs to help the web team while they are crunching on a project.

Now I am not a PHP guy. I tend to live in Microsoft land.

So anyway this is blowing my mind:

code:
$var = $_GET['value'];

if (!$var){
    // Do something
};
Doesn't work.

code:
$var = $_GET['value'];

if (!$var || $var == ''){
    // Do something
};
No dice.


code:
$var = $_GET['value'];

if (!$var || $var == '' || $var == 'undefined'){
    // Do something
};
works?!

Let's var_dump that $var:

Var_dump posted:

string 'undefined' (length=9)

The value of the get data is literally a string with the value 'undefined'? Let's go check out what the gently caress it is that's calling this.

code:
var x = field('.item').find('.select_some_value:selected').val();

 var data = 'production_code='+x;

  // Make AJAX request
  $.ajaxRequest('/index.php?dispatch=thing_im_working_on&' + data, {
    hidden: true,
    full_render: 0,
    result_ids: 'result'+result,
    skip_result_ids_check: true
  });
So it's a radio button. Uses AJAX to call the PHP I'm using and update some stuff based on the selection. I'm trying to handle what happens if they select nothing, or if say their client is loving up and sends the request with nothing.

Why the hell is my GET data set to a string with the value undefined and not actually a null string?

Edit: Another dev is suggesting I try:
code:
if (!array_key_exists('var', $_GET)) { do something );
Will see...

Edit2: Yup that works. Still makes no sense why == 'undefined' works. gently caress web development. gently caress loosely typed languages. :colbert:

itskage fucked around with this message at 16:50 on Jan 28, 2015

Mogomra
Nov 5, 2005

simply having a wonderful time

itskage posted:

I have a Dev out for a couple weeks with some family issues so I am tackling some of our website bugs to help the web team while they are crunching on a project.

Now I am not a PHP guy. I tend to live in Microsoft land.

So anyway this is blowing my mind:

code:
$var = $_GET['value'];

if (!$var){
    // Do something
};
Doesn't work.

code:
$var = $_GET['value'];

if (!$var || $var == ''){
    // Do something
};
No dice.


code:
$var = $_GET['value'];

if (!$var || $var == '' || $var == 'undefined'){
    // Do something
};
works?!

Let's var_dump that $var:


The value of the get data is literally a string with the value 'undefined'? Let's go check out what the gently caress it is that's calling this.

code:
var x = field('.item').find('.select_some_value:selected').val();

 var data = 'production_code='+x;

  // Make AJAX request
  $.ajaxRequest('/index.php?dispatch=thing_im_working_on&' + data, {
    hidden: true,
    full_render: 0,
    result_ids: 'result'+result,
    skip_result_ids_check: true
  });
So it's a radio button. Uses AJAX to call the PHP I'm using and update some stuff based on the selection. I'm trying to handle what happens if they select nothing, or if say their client is loving up and sends the request with nothing.

Why the hell is my GET data set to a string with the value undefined and not actually a null string?

Edit: Another dev is suggesting I try:
code:
if (!array_key_exists('var', $_GET)) { do something );
Will see...

If x is undefined in javascript, it will be converted to the string 'undefined' when it's added to the data variable. Everything is working as intended. :pwn:

But for real,
code:
var x = field('.item').find('.select_some_value:selected').val() || '';

Impotence
Nov 8, 2010
Lipstick Apathy
code:
<?php
$var = $_GET['value'];

if (!$var){
        echo "test\n";
}

quote:

Notice: Undefined index: value in /root/1.php on line 2
test

It's not a php thing from what I can see?

Video Nasty
Jun 17, 2003

Since you're looking for a GET request, the value should get appended to your site's URL once you submit the form. Mogomra covered things pretty well.

itskage
Aug 26, 2003


Mogomra posted:

If x is undefined in javascript, it will be converted to the string 'undefined' when it's added to the data variable. Everything is working as intended. :pwn:

But for real,
code:
var x = field('.item').find('.select_some_value:selected').val() || '';

Using your suggestion works pretty well. Thanks a lot.

lunar detritus
May 6, 2009


This is more of an architecture question than a PHP one but...

I'm working on a giant form made in CodeIgniter that has very distinct steps that are enabled for only certain users after the 'stage' has been reached. Right now the code is a huge mess so I've been thinking of refactoring, as it has a lot of bugs too.


Example of current code in the 'form' controller. It's basically this repeated 15 times. Each one is a separate form inside the same page.

php:
<?
if($orden['suborders'][$key]['stage'] == 'design'): // stage
    if(!in_array('assignation',$this->body_files)) $this->body_files[] = 'assignation';
    if($this->ion_auth->in_group(4) || $this->ion_auth->in_group(14) || $this->ion_auth->in_group(15)): // Check user group
        $this->body_vars['analyst_design']['enabled_'.$key] = ($orden['suborders'][$key]['analyst_design']['id'] == $this->ion_auth->user()->row()->id) ? true : false; // Enable form for certain users
    endif;
    if(!in_array('analyst',$this->body_files))
        $this->body_files[] = 'analyst'; // Add form stage to view array if it hasn't been added by a previous stage.
endif;

if($orden['suborders'][$key]['stage'] == 'respuesta'): // stage
    if(!in_array('assignation',$this->body_files)) $this->body_files[] = 'assignation';
    if(!in_array('analyst',$this->body_files))
            $this->body_files[] = 'analyst';
    if(!in_array('analyst-assignation',$this->body_files)) $this->body_files[] = 'analyst-assignation';
    if(!in_array('assignation-boss',$this->body_files)) $this->body_files[] = 'assignation-boss';
    $this->body_files[] = 'analyst-recommendation';
    if($orden['suborders'][$key]['measurement-incharge']):
        if(!in_array('measurement-quality',$this->body_files)) $this->body_files[] = 'measurement-quality';
    endif;
    if(!in_array('factilibity-connection',$this->body_files)) $this->body_files[] = 'factilibity-connection';
    if($orden['requirement_wifi']):
        if(!in_array('project_wifi',$this->body_files)) $this->body_files[] = 'project_wifi';
    endif;
    if(!in_array('authorization',$this->body_files)) $this->body_files[] = 'authorization';
    $this->body_vars['responsibles'] = $this->ordenes_model->get_all_involved($id);
    if($this->ion_auth->in_group(17)):
        $this->body_vars['preimplementation_enable'][$key] = true;
    endif;
endif;
?>
Submitting the form works almost the same, with another controller checking what subform was sent and massaging the data for the model.

What would be the best way to organize this mess?

raej
Sep 25, 2003

"Being drunk is the worst feeling of all. Except for all those other feelings."
Background (from General programming thread):
I have a RateBeer API key and I'm trying to get Brewery and Beer information from the site.

From their API Doc, the key can be used to access information via HTTP (http://www.ratebeer.com/json/ratebeerapi.asp)

What gets returned is a JSON object such as below:
code:
[{"BeerID":2598,"BeerName":"Black Diamond Hefe-Weizen","BrewerID":452,"BrewerName":"Black Diamond Brewing Company","OverallPctl":30.3348072349412,"StylePctl":33.3880116250839,"BeerStyleName":"German Hefeweizen","Alcohol":5,"IBU":null,"Description":"A traditional Bavarian unfiltered refreshing wheat beer. A unique German yeast strain which imparts the fruit and spicy, clove-like character.\r\n","IsAlias":false}]
What I need is this for be in CSV form, so:
code:
2598,Black Diamond Hefe-Weizen,452,Black Diamond Brewing Company,30.3348072349412,33.3880116250839,German Hefeweizen,5,null,A traditional Bavarian unfiltered refreshing wheat beer. A unique German yeast strain which imparts the fruit and spicy, clove-like character.\r\n,false
Is there an easy way to do this?

Also, when I try doing a large amount in a loop, I get a gateway timeout. Is there a way to output each one to a file and set up a new session each time?


Trying to get file_get_response() working, but I get a 'Failed to Open Stream' error.

code:
<?php

$list = array (
    file_get_contents("http://www.ratebeer.com/json/bff.asp?k=tTmwRTWT-W7tpBhtL&bd=2598")
);

$fp = fopen('file.csv', 'w');

foreach ($list as $fields) {
    fputcsv($fp, $fields);
}

fclose($fp);
?>
I think I'll be able to sort out how to increment the $list to loop through a range of numbers, but for now, I'm trying to get the JSON from the HTTP request converted to CSV and put into a file.

revmoo
May 25, 2006

#basta
This is really ugly and I'm sure there's a better way, but this works:

code:
<?php

$list = (array) json_decode(
            file_get_contents("http://www.ratebeer.com/json/bff.asp?k=tTmwRTWT-W7tpBhtL&bd=2598")
    );
$fp = fopen('file.csv', 'w');

foreach ($list as $fields) {
            fputcsv($fp, (array) $fields);
}

fclose($fp);
2598,"Black Diamond Hefe-Weizen",452,"Black Diamond Brewing Company",30.334807234941,33.388011625084,"German Hefeweizen",5,,"A traditional Bavarian unfiltered refreshing wheat beer. A unique German yeast strain which imparts the fruit and spicy, clove-like character.

spiritual bypass
Feb 19, 2008

Grimey Drawer
Does this work on your machine?

php:
<?php

var_dump(file_get_contents("http://www.ratebeer.com/json/bff.asp?k=tTmwRTWT-W7tpBhtL&bd=2598"));

karms
Jan 22, 2006

by Nyc_Tattoo
Yam Slacker

gmq posted:

This is more of an architecture question than a PHP one but...

I'm working on a giant form made in CodeIgniter that has very distinct steps that are enabled for only certain users after the 'stage' has been reached. Right now the code is a huge mess so I've been thinking of refactoring, as it has a lot of bugs too.


Example of current code in the 'form' controller. It's basically this repeated 15 times. Each one is a separate form inside the same page.

php:
<?
if($orden['suborders'][$key]['stage'] == 'design'): // stage
    if(!in_array('assignation',$this->body_files)) $this->body_files[] = 'assignation';
    if($this->ion_auth->in_group(4) || $this->ion_auth->in_group(14) || $this->ion_auth->in_group(15)): // Check user group
        $this->body_vars['analyst_design']['enabled_'.$key] = ($orden['suborders'][$key]['analyst_design']['id'] == $this->ion_auth->user()->row()->id) ? true : false; // Enable form for certain users
    endif;
    if(!in_array('analyst',$this->body_files))
        $this->body_files[] = 'analyst'; // Add form stage to view array if it hasn't been added by a previous stage.
endif;

if($orden['suborders'][$key]['stage'] == 'respuesta'): // stage
    if(!in_array('assignation',$this->body_files)) $this->body_files[] = 'assignation';
    if(!in_array('analyst',$this->body_files))
            $this->body_files[] = 'analyst';
    if(!in_array('analyst-assignation',$this->body_files)) $this->body_files[] = 'analyst-assignation';
    if(!in_array('assignation-boss',$this->body_files)) $this->body_files[] = 'assignation-boss';
    $this->body_files[] = 'analyst-recommendation';
    if($orden['suborders'][$key]['measurement-incharge']):
        if(!in_array('measurement-quality',$this->body_files)) $this->body_files[] = 'measurement-quality';
    endif;
    if(!in_array('factilibity-connection',$this->body_files)) $this->body_files[] = 'factilibity-connection';
    if($orden['requirement_wifi']):
        if(!in_array('project_wifi',$this->body_files)) $this->body_files[] = 'project_wifi';
    endif;
    if(!in_array('authorization',$this->body_files)) $this->body_files[] = 'authorization';
    $this->body_vars['responsibles'] = $this->ordenes_model->get_all_involved($id);
    if($this->ion_auth->in_group(17)):
        $this->body_vars['preimplementation_enable'][$key] = true;
    endif;
endif;
?>
Submitting the form works almost the same, with another controller checking what subform was sent and massaging the data for the model.

What would be the best way to organize this mess?

Biggest problem here is not so much the logic, but the messy layout. I reduced some redundancy and am judicous with whitespace to make it less cluttered:

php:
<?
protected function addToBody($keys)
{
    if(!is_array($keys)) $keys = [$keys];
    foreach($keys as $key)
    {
        if (!in_array($key, $this->body_files))
        {
            $this->body_files[] = key;
        }
    }
}

$suborder = $orden['suborders'][$key];

if($suborder['stage'] == 'design')
{
    $this->addToBody('assignation');
    
    // Enable form for certain users
    if ($this->ion_auth->in_group(4) || $this->ion_auth->in_group(14) ||  $this->ion_auth->in_group(15))
    { 
        $analyst_design_id = $orden['suborders'][$key]['analyst_design']['id'];
        $ion_auth_user_id = $this->ion_auth->user()->row()->id;
        $this->body_vars['analyst_design']['enabled_' . $key] = $analyst_design_id == $ion_auth_user_id;
    }
    
    $this->addToBody('analyst');
}

if($suborder['stage'] == 'respuesta')
{
    $this->addToBody([
        'assignation',
        'analyst',
        'analyst-assignation',
        'assignation-boss',
    ]);

    $this->body_files[] = 'analyst-recommendation';

    if ($suborder['measurement-incharge'])
    {
        $this->addToBody('measurement-quality');
    }

    $this->addToBody('factilibity-connection');
    
    if ($orden['requirement_wifi'])
    {
        $this->addToBody('project_wifi');
    }

    $this->addToBody('authorization');

    $this->body_vars['responsibles'] = $this->ordenes_model->get_all_involved($id);
    if ($this->ion_auth->in_group(17))
    {
        $this->body_vars['preimplementation_enable'][$key] = true;
    }

}
?>
It's never going to be perfect (forms have a way of doing that) but at least it's a bit easier to read.

karms fucked around with this message at 21:00 on Jan 29, 2015

Sereri
Sep 30, 2008

awwwrigami

itskage posted:

code:
$var = $_GET['value'];

if (!$var || $var == '' || $var == 'undefined'){
    // Do something
};
works?!

Let's var_dump that $var:


The value of the get data is literally a string with the value 'undefined'? Let's go check out what the gently caress it is that's calling this.

It could also be that the get value is 0, because every string you compare to 0 with == will result in true. There's also other fun stuff with String comparison like NULL is '' and so on. When it comes to Strings in PHP always use === .

raej
Sep 25, 2003

"Being drunk is the worst feeling of all. Except for all those other feelings."

revmoo posted:

This is really ugly and I'm sure there's a better way, but this works:

code:
<?php

$list = (array) json_decode(
            file_get_contents("http://www.ratebeer.com/json/bff.asp?k=tTmwRTWT-W7tpBhtL&bd=2598")
    );
$fp = fopen('file.csv', 'w');

foreach ($list as $fields) {
            fputcsv($fp, (array) $fields);
}

fclose($fp);
2598,"Black Diamond Hefe-Weizen",452,"Black Diamond Brewing Company",30.334807234941,33.388011625084,"German Hefeweizen",5,,"A traditional Bavarian unfiltered refreshing wheat beer. A unique German yeast strain which imparts the fruit and spicy, clove-like character.

When I put this into a loop (seen below) I'm getting a Fatal error: Maximum execution time of 30 seconds exceeded error.

Also, it looks like it's overwriting the same line. How would I go about going to a new line each time, then appending each iteration to the file instead of over what existed?

code:
<?php
for ($i = 1; $i < 11; $i++) {
	$list = (array) json_decode(
				file_get_contents("http://www.ratebeer.com/json/bff.asp?k=tTmwRTWT-W7tpBhtL&bd={$i}")
		);
	$fp = fopen('file.csv', 'w');

	foreach ($list as $fields) {
				fputcsv($fp, (array) $fields);
	}

	fclose($fp);
}
?>

Adbot
ADBOT LOVES YOU

Master_Odin
Apr 15, 2010

My spear never misses its mark...

ladies
You want to use pagination or something where you have
code:

$i = (isset ($_GET['i'])) ? intval($_GET['i']) : 1;
// get api
header('Location: index.php?i='. ($i+1));

You'd also want to use 'a' in the fopen if using the same file.

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