Roll Your Own, Self-Hosted Image Gallery with Chevereto

For many people, Google Photos, Flickr, and other cloud-based image hosting services are perfect for backing up photos, sharing them, and organizing them into galleries. If you’d rather use a self-hosted solution you control, or maybe use one in addition to those cloud services, Chevereto is worth a look.

Chevereto has been around for a long time—it’s not new, really, but what’s interesting about it is that the developer offers both a paid, hosted service you can sign up for on their homepage, but also Chevereto Free, an open source version of the gallery software you can download from Github (linked below) and install and run on your own web host. Best of all, they offer an installer you can run from the web, or even installation services so you can make sure your gallery is locked up tight and installed properly.

Chevereto itself is a richly featured gallery tool. You get beautiful, responsive galleries that look just as good on mobile as they do on the desktop, profiles for multiple users, an image uploader so you don’t have to do things in small batches, social features for easy image sharing (and for easy login), and feature updates as they’re available. The whole service is worth a look if you’d rather take control of your own photo library, but don’t know where to start. There’s a paid version of the self-hosted solution as well that comes with support and a few more features, so check that out too, if you’re interested in supporting the project.

Chevereto Free | GitHub via Chevereto


via Lifehacker
Roll Your Own, Self-Hosted Image Gallery with Chevereto

A Startup with the Risk Profile of an Incubator? (A WhenHub Post)

Note: If you’re a business model nerd like me, this post is likely to interest you despite the fact that it also involves a transparent promotion for my startup. However, if the normal mechanisms of capitalism feel icky to you, I understand. Feel free to skip this one. But I promise it is interesting.

The big problem with startups is that most of them fail. Still, lots of people are willing to take that risk because the upside potential is so high. Also, failing makes your odds of succeeding with the next startup much higher. It turns out that failure is an excellent teacher. But any way you look at it, startups are risky business.

Startup incubators reduce their risk by pooling a bunch of startups together and hoping that at least one is a big winner that pays for all the losers. This is similar to the concept of investing in an index fund instead of picking individual stocks. Diversification is a great way to spread risk, but the tradeoff is that the upside potential is watered down by the losers in the pack.

In a perfect world you would have the upside potential of a startup with the risk profile of an incubator. The closest anyone gets to that perfect world is an initial product and a few pivots before running out of cash. A three-pivot startup is like a mini-incubator in itself. It takes three separate swings at the ball and hopes at least one of them connects. But three swings is not many when you consider how often startups fail. Is there a business model that does better?

I hope so, because my startup WhenHub is designed from the ground up to be similar to the risk profile of an incubator but in the form of a single startup. We accomplish that by creating useful products that have universal appeal across thousands of different applications. If the public gets excited about any one of those thousands of applications, we probably have a way to monetize. 

Our startup’s domain is time, including any kind of schedule, historical timeline, curriculum, itinerary, you name it. We take those “stories” of time and turn them into interactive visualizations you can share. That means literally every human over the age of 12 has dozens of potential uses for what we do. It’s good for families, businesses, schools, and any other kind of organization. 

We like to compare WhenHub to office applications such as Word, Excel, PowerPoint and the Google equivalents. If you ask me who the target market is for any of those applications, I would say the question makes no sense. People of all types use those products for thousands of distinct reasons. WhenHub is like that, by design. 

Obviously we can’t completely match the risk profile of an incubator because we have one team of people, and ideally you want to diversify both the people and the products to get the best risk control. But our team has happily worked together for a long time, no drama, and that’s all good news. I don’t see that changing unless the people change. And we all seem happy at the moment. (Thrilled, actually. This phase is the most fun.)

WhenHub is both a Studio product that you access with your web browser plus an app that does real-time travel visualizations. Both parts of WhenHub are designed to have thousands of potential uses. 

Before designing WhenHub we met in person with some of the smartest investors in the startup world. One well-known billionaire told us he only likes startups that have the so-called network effect, and so we designed to that. WhenHub gets more valuable as more people use it, and it is hard to leave once you are in it. (Like Facebook, for example.)

One of the most successful angel investors in the country told us he likes startups that can grow without advertising, so we designed to that standard too. Our “time stories” piggyback on any headline that is already viral and we add visual appeal to make sharing attractive. For example, at the end of this post is a Whencast of the NFL Playoff season. (Sports schedules are a tiny part of what we do.)

Another famous investor told me he doesn’t like to invest in anything that a teen wouldn’t use. The WhenHub app is perfect for teens heading to casual meet-ups. And the we expect schools to be big adopters of the WhenHub scheduling features. So teens will be all over it, we hope, once we get their attention. And their parents and teachers will do that for us. The Network Effect will drag them in.

We’ll be looking for several million in funding in the next month or so. If you are a qualified investor and you want a sneak-peak at the pitch deck, you can contact me at Investor@WhenHub.com. We like advice too. 

Business reporters are welcome to use the same email if you want to hear more about our business model.

Here’s an example of how WhenHub piggybacks on current events that the public already cares about. This example is the NFL playoff schedule, but it could be any current event. You can add the schedule to your own calendar, or share with others via email, or on social media, and we will keep it updated throughout the playoffs. You can even embed it in your blog with a copy-paste to HTML, like I did below.

This map-style visualization is one of many options. click the icon in the lower right corner to see full screen. 

image

via Scott Adams’ Blog
A Startup with the Risk Profile of an Incubator? (A WhenHub Post)

US Appeals Court Revives Antitrust Lawsuit Against Apple

iPhone app purchasers may sue Apple over allegations that the company monopolized the market for iPhone apps by not allowing users to purchase them outside the App Store, leading to higher prices, a U.S. appeals court ruled. From a report on Reuters: The 9th U.S. Circuit Court of Appeals ruling revives a long-simmering legal challenge originally filed in 2012 taking aim at Apple’s practice of only allowing iPhones to run apps purchased from its own App Store. A group of iPhone users sued saying the Cupertino, California, company’s practice was anticompetitive. Apple had argued that users did not have standing to sue it because they purchased apps from developers, with Apple simply renting out space to those developers. Developers pay a cut of their revenues to Apple in exchange for the right to sell in the App Store.



Share on Google+

Read more of this story at Slashdot.

via Slashdot
US Appeals Court Revives Antitrust Lawsuit Against Apple

PHP and MySQL Basics III — Resulting Results

In the first two blogs entries on this series we set up a connection to MySQL and sent off a query. Now we need to get the data back from the database and into the application.

An Embarrassment of Riches

PHP has many options for what we want to do. But for the best place to start with was checking that rows were actually returned from a query. Below the results from a query are returned to a variable named $result. We can find out how many rows were returned from the server by examining $result->num_rows.

if (!$result = $mysqli->query($sql)) {

// Again, do not do this on a public site, but we'll show you how
// to get the error information
echo "Error: Our query failed to execute and here is why: \n";
echo "Query: " . $sql . "\n";
echo "Errno: " . $mysqli->errno . "\n";
echo "Error: " . $mysqli->error . "\n";
exit;
}

// succeeded, but do we have a result?
if ($result->num_rows === 0) {
// Oh, no rows! Sometimes that's expected and okay, sometimes
// it is not. You decide.
echo "No data returned.";
exit;
}

This is a case where a programmer needs to know their data. In some cases you will not have a record or records returned because there is no data. Other times no data returned is a sign of big problems. So you have to have some education on what you expect back, and what you do not expect back.

Example

<?php
$mysqli = new mysqli("localhost", "root", "hidave", "world_x");

/* check connection */
if ($mysqli->connect_errno) {
printf("Connect failed: %s\n", $mysqli->connect_error);
exit();
}

/* Select queries return a resultset */
$query="SELECT Name, CountryCode, District FROM city LIMIT 10";

if ($result = $mysqli->query($query)) {

if ($result->num_rows){
printf("Select returned %d rows.\n", $result->num_rows);

/* free result set */
$result->close();
} else {
echo "No data returned";
}
} else { // if ($result)
printf("Query failed: %s", $mysqli_error);
}

$mysqli->close();
?>

Sometime you just need the number of records, like number of outstanding customer orders. But in this case we are making sure we have some data to work with before proceedings.

So Now We Have Data

Now you have at least three choices — rare, medium, or well done. Err, make that an associative array, an array or an object. Each have their uses and it is okay to have a favorite you use more.

$query="SELECT Name, CountryCode, District FROM city LIMIT 10";

if ($result = $mysqli->query($query)) {

if ($result->num_rows){
printf("Select returned %d rows.\n", $result->num_rows);
$assoc = $result->fetch_assoc();
$row = $result->fetch_row();
$obj = $result->fetch_object();

} else {
echo "No data returned";
}
} else { // if ($result)
printf("Query failed: %s", $mysqli_error);
}

So you make you choice of method and take the results. Here we use fetch_assoc(), fetch_row(), or fetch_object(). Depending on how you want to refer to the data, you use the one that fits the situation. Of course they are similar in use.

//associated array keys = column name, data = data from DB
printf("Sample assoc array %s -> %s\n", $assoc['Name'], $assoc['CountryCode']);

// simple row
printf("Sample row array %s -> %s\n", $row[0], $row[1]);

//object
printf("Sample object %s -> %s\n", $obj->Name, $obj->CountryCode);

Yes, you need to know all three as you will be looking at old code or someone else code that does not use your favorite. And sometimes you may need an object rather than a simple row.

Full Listing

<?php
$mysqli = new mysqli("localhost", "root", "hidave", "world_x");

/* check connection */
if ($mysqli->connect_errno) {
printf("Connect failed: %s\n", $mysqli->connect_error);
exit();
}

/* Select queries return a resultset */
$query="SELECT Name, CountryCode, District FROM city LIMIT 10";

if ($result = $mysqli->query($query)) {

if ($result->num_rows){
printf("Select returned %d rows.\n", $result->num_rows);
$assoc = $result->fetch_assoc();
$row = $result->fetch_row();
$obj = $result->fetch_object();
} else {
echo "No data returned";
}
} else { // if ($result)
printf("Query failed: %s", $mysqli_error);
}
//associated array keys = column name, data = data from DB
printf("Sample assoc array %s -> %s\n", $assoc['Name'], $assoc['CountryCode']);

// simple row
printf("Sample row array %s -> %s\n", $row[0], $row[1]);

//object
printf("Sample object %s -> %s\n", $obj->Name, $obj->CountryCode);

$result->close();
$mysqli->close();
?>

via Planet MySQL
PHP and MySQL Basics III — Resulting Results

PHP and MySQL Basics II – Case Sense

Last time we set up a connection from a PHP program to a MySQL server. This time we will progress a little further in that direction.

Query

Data is asked for from the MySQL server by using a query written in a language named Structured Query Language (SQL). Now that we have a connection open to the server, we can pass out request to the server.

Manual Labor

The PHP Manual is wonderful 99% of time. If you take a peek at the page for mysqli::query there is a great example of a simple query. Many of learned to program by copying/pasting from books/manuals and this is a great us of the examples in the PHP manual. Except it may not work for you.

MySQL is usually case SeNsATiVe, so ‘A’ may not be the same thing as ‘a’. But this is dependent to some extent on your operating system where ‘A’ = ‘a’. I was using the example from the manual and … it did not work.

What Happened

Here is an excerpt of the code, somewhat cut down:


<?php
$mysqli = new mysqli("localhost", "user", "secret", "world_x");

/* check connection */
if ($mysqli->connect_errno) {
printf("Connect failed: %s\n", $mysqli->connect_error);
exit();
}

$mysqli->close();
?>

Run the program and … nothing.

So What Happened?

What happened is a subtle problem that novices will smack into very hard. Take a look at this section of the example.

/* Select queries return a resultset */
if ($result = $mysqli->query("SELECT Name FROM City LIMIT 10")) {
printf("Select returned %d rows.\n", $result->num_rows);

/* free result set */
$result->close();
}

If you try the query SELECT Name FROM City LIMIT 10; with the MySQL command line client program you will get the answer. And the answer is:

mysql> SELECT Name FROM City LIMIT 10;
ERROR 1146 (42S02): Table 'world_x.City' doesn't exist
mysql>

I am using the new world_x example database where the city is NOT capitalized instead of the old world database where it is! This lesson can be summed as check you schema/table/column names for case sensitivity. Except that there is another problem here.

In the real world occasional the database/table/column that you carefully double checked was spelled correctly and with the proper case sensitivity will go away. It may have been renamed, deleted, munged, or what have you. What is needed is a way to check to see if there was an error if the query can not run.

Lets change the code slightly:

/* Select queries return a resultset */
if ($result = $mysqli->query("SELECT Name FROM City LIMIT 10")) {
printf("Select returned %d rows.\n", $result->num_rows);

/* free result set */
$result->close();
} else {
printf("Query failed: %s\n", $mysqli->error);

}

Always Check for Return Codes

By simply adding about 40 characters, the reliability of the program shoots up immensely AND we get an exact answer if what went wrong.

Query failed: Table 'world_x.City' doesn't exist

Same error as when we tried by query by hand. But now our code can handle this issue. We could even try to catch the error, send a note via a message queue to the operations staff about the nature of the problem, and possible limp along until things are resolved. Or we could just call exit()

When you are offered a return code be sure to check it. Yes, it may be over kill in simple examples. But the payoff comes when things go bad and you are scrambling to find out eleven months from now why your program is suddenly not working.
via Planet MySQL
PHP and MySQL Basics II – Case Sense

Honest Princess Bride Trailer

Honest Princess Bride Trailer

Link

Screen Junkies digs 30 years into the vaults to pay tribute to one of our all-time favorites. It’s got adventure, dark humor, romance, and a wealth of memorable characters and lines we still quote to this day. Also, we felt exactly like Fred Savage as the story unfolded.

via The Awesomer
Honest Princess Bride Trailer

PHP and MySQL Basics

PHP and MySQL have had a long intertwined path together. I have been talking with a lot of newbies in the past several months who are trying to become PHP developers but are amazed at all the ancillary parts that go along with PHP such as unit testing, databases, JavaScript, continuous integration, and much more. Add in that there are two MySQL APIs — PDO & MySQLi — and an older deprecated mysql API still often found in the wild. This blog is the start of a series for new PHP developers to learn to program with a database.

Client Server Model

The PHP code when it seeks to talk to a MySQL (or most other databases) will make a connection to a port at an IP address. Usually MySQL is listening on port 3306. If you are developing an accessing a database on your local computer the IP address used will generally be at 127.0.0.1. The software that goes between the PHP application and the database is called a connector.

So your code on you local system an be talking to a database server on your local system or through a network connection. It does not matter which.

Can’t connect to MySQL server on ‘x.x.x.x’ (111)

The Can’t connect error can be especially frustrating. An experienced developer will know what to check from tears of experience. But this is a column on basics so we need to spell out the steps.

  1. Is the IP address correct? It is easy to fat finger IP address and ironically 127.0.01 on many Linux boxes will connect up to 127.0.0.1.
  2. Is there a instance of MySQL running at that IP address?
  3. Is that instance listening on the generic port 3306? Is may be running someplace else and you will have to chance down that port number.
  4. Can the MySQL command line shell or other tool connect to the instance? MySQL Workbench, PhPMyAdmin, the cli tools, and everything else authenticate through the same steps so if they work and your PHP program does not then most likely the fault is in the PHP code.

Setting up the client server connection

The PHP Manual is worth its weight in gold and you should refer to it often. Its examples are clear, or usually as clear as can be, and concise. Below is an excerpt example from the manual.


<?php

$mysqli = new mysqli("127.0.0.1", "user", "password", "database", 3306);
if ($mysqli->connect_errno) {
echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}

echo $mysqli->host_info . "\n";
?>

Note that the IP address, user name of "user", password of "password", and the port of 3306 will need to be changed to fit the installation. The mysqli call sets up the connection between the application and the MySQL database server.

Please note that you should protect usernames and password or any other information that could allow someone to compromise the server and data.

The if statement is invoked when there is an error code is returned from the $mysql->connect_errono call. Subsequently the error message from the server can be printed out using $mysqli->error. The error message itself can be terse but often points out what is wrong in the code.

Bad arguments

What follows below are three bad connection strings.

// Bad IP address
$mysqli = new mysqli("19.10.0.3", "root", "barfoo", "world_x", 3306);
if ($mysqli->connect_errno) {
echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}

// Bad account information
$mysqli = new mysqli("127.0.0.1", "root", "foobar", "world_x", 3306);
if ($mysqli->connect_errno) {
echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}

// Bad database specified
$mysqli = new mysqli("127.0.0.1", "root", "foobar", "world_xx\", 3306);
if ($mysqli->connect_errno) {
echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}

Part of mastering any computer programming language is learning to understand the error messages. The three examples above return similar but distinctly different messages.

The first of the trip provides the following error:


PHP Warning: mysqli::__construct(): (HY000/2002): Network is unreachable in /home/dstokes/php/m02.php
Failed to connect to MySQL: (2002) Network is unreachable

It would be nice to get more information than ‘Network in unreachable’ but it provides a starting point to diagnose the problem. Generally the more specific the problem, the more specific the error message.

The third of the trio attempts to connect to a database named ‘world_xx’ when we really wanted ‘world_x’.

PHP Warning: mysqli::__construct(): (HY000/1049): Unknown database 'world_xx' in /home/dstokes/php/m02.php
Failed to connect to MySQL: (1049) Unknown database 'world_xx'

Sadly for beginners it takes time and experience to get to the point where you can instantly look at an error and know what has gone wrong (or have a pretty good idea of what has gone wrong). But do not worry as many of us learn by correcting OUR mistakes and learning not to repeat them.

Connection Good

So after establishing a good connection to the MySQL server, we can now query it for data.

Next Time — what happened to my query??

via Planet MySQL
PHP and MySQL Basics

Cinder Speakers

Cinder Speakers

Link

Designer Daniel Ballou and Dashdot are working on this cool DIY audio system which lets you take ordinary cinder blocks and turn them into speakers. Apparently, the concrete minimizes vibration and coloration of sound. Ballou hopes to retail the kit for about $150.

via The Awesomer
Cinder Speakers