 They usually give me the right after-lunch slot, which is awesome because I can say anything because everybody doesn't sleep any night, so I can't even read the phone but I still get good reading. I hate the last slot of the day because you're the speaker and it's between the audience and the fear and that is a bad place to be. Would you do me a favor and close the door if I'm going to start again? Seriously, they don't lock, I just didn't want it to. I don't want to disrupt those people that are actually out there going to work. Hi there, my name is Cal Evans. We're going to talk about PHP for the CLI. First of all, who was in the last session in this room? Anybody? That was a good session. Emma did a great job but it was more of an intro to the command line in general. We're actually going to talk about PHP for the command line. Who out there has heard me speak before? All my jokes are new, awesome. Russ, you don't count. He's seen me talk. I have four jokes that I've been using since 2006. If you see him laugh, laugh. That means you're supposed to. It doesn't matter if you find it funny or not. I don't know what you're expecting. This is pretty much a beginner's talk. If you understand the basics of PHP, then you've got enough to go on to see this talk. If you've done PHP from the command line already, you might pick up something, but this is the very basics of how to get started doing that. I'm just setting some expectations here. The doors are not locked, I was kidding. So you can slip out. I will lock you after you leave. You can find something better. The code for this is available on GitHub. If you want to play with this, this is interesting to you at all. This project will get into in just a second. The sample project is fairly stupid. It's not going to be something you can go, hey, I can use this in one of my other projects. I hope it's not. If the talk is interesting to you at all, I encourage you to download the code and play with it. One of the things that's going to drive you up the wall is glasses. I'm old, but I'm new at being old, so I keep putting my glasses on. I can't see you. I take them off. I can't see the monitor. I do apologize in advance for that. I got to researching because I decided to do this talk. I was invited to speak at Midwest PHP in the U.S. I wonder. Okay. I was invited to do this at Midwest PHP. I might as well just pick the dang thing up and carry it with me. I sat down, I wrote this talk, and I said this sounds very familiar. I got to looking, and I've written this talk three times for three different audiences. The very first time I wrote this was for the IPC conference in Karlsruhe, Germany. At that time it was very Zen framework focused because I was doing an awful lot of work in Zen framework. This time we're actually going to use a symphony component, but it's not really a symphony talk. We're just going to use the symphony component because that's the easiest one to get started with. First of all, the question, why use the CLI? I'm going to give you a few reasons why I program from the CLI. The first one, and actually this is point number zero, is I am absolutely horrible at drawing anything. Graphics, color, theory, all of that escapes me totally. Now, I am blessed to be married to the lovely and talented Kathy. She is a graphics designer. If you see anything that has my name on it and it looks good, she did it. But the CLI, I don't have to worry about that. The example I'll show you, we got fancy here and I've actually got colors, but that's about it. And it's not very good colors. I had to change them today because it didn't work on my terminal anymore. Reason zero is I'm absolutely horrible at that. I'm much more comfortable and have always been more comfortable as a middleware or back-end developer. I don't like designing screens. I don't like doing anything like that. And so I have found my love now designing things at the command line and designing APIs because you don't have to worry about it. It becomes somebody else's problem. But that's number zero. Number one is I just find it easier to use. A lot of the stuff that I do, especially from the command line, is just hit pocket or one-off programs. We've all done that. We write something. I've just got to move stuff from this database to that database and change everything or change the capitalization in between. You're only going to do that once. And yes, you could write this as a web program and have it output HTML to the browser. But what's the point in that? It's just a script. It's much more at home just running from the command line. I find it much easier to use. Can everybody hear me, by the way, because I'm not up at the mic? Okay. I have a tendency to be loud and boisterous. The mic usually blows people's ears out. Number two, that's their problem. Not mine. No, I'm kidding. You're right. They can't hear me on the video. I will try to stay at least close to the mic. Number two is a properly written PHP command line script can be part of a larger tool chain. Most of you who have used the command line on Linux or OS X for any amount of time know how to pipe things and tree things and move things around like that. And the UNIX concept of you write one small command or one command that does one thing and one thing only and it takes an input and it outputs the output and you chain these together to get the desired results. Well, a properly written PHP script from the command line can be part of that tool chain. I usually find that I can get about 75% of the way there with the UNIX tool chain before I have to resort to something like SED or AUK and I hate SED and AUK. So I ended up just writing the rest of it in PHP. But that's fine because PHP gives me a lot more control. Another reason is for security. If you have commands or if you have things that have to be done to your web application that you don't want everybody to be able to do, clear the cache or reset the database or whatever you want to do, you can write them and put them out on a URL and hope to God nobody ever finds them, security through obscurity or what I like to call the TSA model of web security. That jokes funny in the U.S. Okay, y'all don't know who the TSA is and it just hit me that. The people in the video from the U.S. will be dying at this point. But security through obscurity is just hoping nobody finds the URL that's going to do something dangerous like wipe your database or you can implement a full blown off in that. You can implement a token or a login or OAuth or something like that but that's a lot more difficult just to put a command out on a URL. Or you can use a command line tool because quite honestly the only way they can run it from the command line is if they have access to your server through SSH or physical access. And if someone you don't want to run your scripts has physical access to your server you've got bigger problems than I can solve in this talk. So it is much more secure. You log in, you have to be super user to run this and that's the only way you can execute that command. But the most important reason, and I can't stress this enough, I'm lazy. I find that I can quickly hack out a command line script and I've done this several times. I copy a composer.json file over to a new directory. I modify two or three things. I install the packages with it and I'm up encoding within about 10 minutes and usually about 25 minutes after I've started, I've got what I need to get going, going. And it either works and I'm going to finish it up or it didn't work and I've already moved on to the next idea. I'm very lazy about this stuff. I have probably 20 different commands that I use on a regular basis that I've written doing this and they all started out with, hey, I wonder if I can do it this way. And this PHP gives me, or the PHP command line gives me very easy way to do that. Also, and this comes into play if you're working on larger applications. If you have a large web app that has models that encapsulate all of your business logic, congratulations because that is the proper way to build them, but you don't always have access to all of that business logic. And I can either, most of the stuff that I write, I could probably write in using just straight bash. I hate bash, but I could write it just using straight bash, but then I lose access to all my business logic. And that's usually important and comes into play in all of these. Well, if your business application is written in PHP and your models are properly built and framework agnostic, meaning they can be instantiated without any framework dependencies, then you can use them in just about any command line script that you execute or that you build. And so all of your friends are right there because this is PHP and you know how to use PHP. You've got access to all of this. You can just start building and extending things and making them do new things. So that's why you use the PHP. Now let's talk a little bit about the how. Way back in Gondar. PHP was originally written to work with Apache. Now if you're not familiar, we're going to do a little history here. PHP was originally written to work with Apache and it was encapsulated in mod PHP, which is inserted into Apache. And this is wonderful if you're using Apache. It really sucks if you're using IIS. So the core team, those brilliant people that have volunteered their time so that I can have a career doing things like speaking to you, the core team decided, well, let's abstract everything. Let's make the server application programming interface and then we will implement Apache as that, but we can also implement lesser web servers like IIS. And so IIS now has access to PHP. Actually, we have quite a few of them now available to us and this is not even a complete list of them. Yes, you see that right. PHP supports AOL server for the two people in the world still running it, but it still supports it. But we're really only interested in the CLI and it acts as a... it is a SAPI, so it is the same interface that a web server would use to access this, but it is some of the things, as we'll talk about, behave a little differently than if you're actually using a web server. And there are two major differences in that. The first, the header command does absolutely nothing. You can set headers in your CLI scripts all day long. It's not going to do anything. The header does not output anything. This is a good thing. We don't need headers when we're doing CLI, but it's also a good thing that it doesn't throw an error or anything. It sees that it's working in the CLI SAPI and it just ignores everything that you're sending to you. And the other one, and this hasn't always been true, but we now get plain text error messages. Back when we first got the CLI SAPI, we would get the same output when we got an error as we do on an error on the web, which means you get the HTML output, but it's output in a terminal window, so you've got to sit there and filter out all the HTML so you can figure out what the problem is. That was a real pain in the rear end. Thankfully, those days are gone. We now get just strained plain text for the error messages. Now, when we're talking about PHP from the CLI, there are two ways that we can do this. What I like to call freestyle, which is you put a page out on the web server and you use WGet or Curl or whatever your favorite command line tool is to hit that page and call it in and execute it. This is okay, but it's not really what we're looking for and the OCD programmer in me says that's using the web server. I've got all this overhead for a web server that I don't really need because I just want to execute this script. And you also, like we talked about earlier, you've got to put authorization checks in there or you've got to hide it and hope nobody finds it. This is not a good thing. The reason we would do this, though, is we know these tools. They're handy. They're right there. If you're working from the CLI, you've got WGet or Curl that you use on a regular basis and you understand them. You know these. They're your friends. It's easy to put a command into a cron by doing this, just WGet and the URL. You don't have to worry about pathing or anything like that. It just works for you. And you can use existing code as is. Your web framework already knows how to instantiate the model. Your controllers understand how to do this. You already have views that are outputting stuff, so your framework understands how to do this. You have access to all your tools. It's just easy. And it's a paradigm that every web developer understands whether you work at the command line or not. So most people, when they make the transition to working in the command line, initially start with bash scripts that are doing this and they will call a PHP script through a web server and output it. Hopefully, I will inspire you at least to move beyond that if that's what you're doing now. Because there is a better way. There's a better way to call our code from cron jobs. There's a better way to build maintenance scripts and I do an awful lot of that. I have a little side project that I have to work on on a monthly basis and it was one of those I'm having to move data from this service to this service and I have to update everybody's subscription data and stuff like that. It just got to the point where I was doing a lot of this stuff manually and I said, okay, I can take this and make it a script and I can take this and make it a script. Well, the project has grown to the point where I don't run it by myself. My wife runs most of it these days and she came to me the other day. She says, well, if you'll just show me how to do this, I'll run it myself. I said, oops, well, here comes the problem with it. It all sits on my local laptop. So there are a few downsides to this. If you do this, push it up into a get repo or something so that other people can get to it. She's not a programmer. She's a designer. So she was hoping for go to this URL, click this button. So that's going to be probably the next step or the next evolution of these. But there is a better way for us to be able to build or to build our maintenance scripts. That's not exactly a new way though. We got the CLI SAPI in PHP version 4.3. And the first time I saw that, I got really excited because I was like, cool, because now I don't have to worry about all the HTML stuff. I can just do the stuff that I'm interested in and I dove into it and in 4.3 I actually build an object-ish mail system handler, maintenance scripts. I can issue a command and add a domain name to my mail server. And I can add accounts and I can delete accounts and all this was stored in the database. And yes, I realized storing mail in the database is a bad idea. But that's a lesson you really only have to learn one time. But I built all of this and it was 4.3 so we didn't have true objects. But I had, it was object-based programming. And it was eye-opening to be able to do all of this. And that was where I fell in love with building more and more of these scripts. But there's actually several ways. How many of you actually use a framework for PHP? Okay. Chances are good if you're using a modern-day framework, they have CLI support built in. Laravel, Zen Framework 2, Symphony 2, we'll be using the Symphony 2 command. Aura. Yeah, Aura. Keep wanting to call it Aurora. Aura has it built in. All of these already have these built in. So the concepts that we talk about are still going to be applicable to you even if the commands that we're going to show or I'm going to show you here have to be changed. But in reality, this is not a I'm going to show you step-by-step how to do this. This is one of these. I want to show you what's possible, hopefully inspire you to take the next step. So the sample project. We're moving fast. I talk fast. We're going to get done early. So the sample project, I never like sample codes in talks to be useful code. And by useful, I mean something you could take and look at and say, heck, I can use that in my own project. Because every time I've done that, what I have found is that people get wrapped up more in what the code is doing than the concepts that we're implementing. So the sample project that I have for you today is a command line Twitter client. I know. I know. The first question you're asking is, how can I monetize this? Twitter's been asking that since they began. No. Thank you. Okay, you're awake. Good. As I tell all my audiences, the jokes don't get much better. But if you don't laugh, I will tell more. Okay? We need the blink tag to come back because this really needs to be blinking. We're going to do a Twitter client. But first, like any good programming project, let's shave a yak. Okay, we've got to do a little research. I'm going to have to explain a few, all the moving parts to you. We're going to set it all up, and then we'll play with it. So the first thing we need to do is set up our bootstrap. Now, the way Symphony operates is I have a batch script that has PHP set as the interpreter. Now, I had somebody, I did this talk at Drupalcon LA, and I had somebody ask, well, couldn't I just say PHP and the name of the script? And yes, you certainly can, but you don't have to. You're using Unix or OSX, and you have this set with the proper execute permissions, then you can run this script, and basically that first line tells Bash the rest of this should be interpreted with PHP. If you're running it with PHP, PHP just sees a comment, boom, we're done. So this is... Oh, I don't need that. I'm not going to go through all of this. I'm going to talk about a couple of pieces of it. The first thing is we use the Composer Autoloader. Now, how many of you are using Composer? Congratulations. The rest of you, please start. Composer is one of two or three tools that have changed the way PHP developers operate. It is a fantastic tool. I guarantee you, if you learn how to use it, it will change how you operate because the one thing it does for you is all of a sudden other people's code is very easy to incorporate into your code. I'm going to show you how to do that. But we have to bring in Composer's Autoloader. That's really all we have to do. It sets up everything so that it can autoload our classes. Now all we have to do is get the name spacing right, which is a pain to begin with, but get the name spacing right and we've got everything. And you can see I use a command... I use the command sub-directory. So PHP from the CLI slash command. By the way, the backslash for name spacing. Everybody from the PHP name spacing? Back a few years ago when we were just starting to talk about name spacing, the core put up a vote for everyone, not just the core developers. They put up a vote for everyone to see what to use as the backslash. Everybody eventually voted, and that was the one that got the most. If you go research on RSC.php.net, you can find that. You will see that there is one vote for colon closed parentheses. Because I wanted the smiley face. I set that up. I voted for it. Just think of how much more fun programming would be if that was our name space separator. But anyhow, we bring in the autoloader. We set up our configuration. Now I'm going to talk to you a little bit later about this, but that's all it takes to bring in my configuration settings. I'm using the .env package for my good friend, Vance Lucas. It's available out on GitHub. This is not a sales pitch for it. It's really starting to sound like one, but it's available out there. If you've ever had to do configuration options for either a command line script or for your web server, it is just a fantastic package to use. It's one of those, it does its job, it does it well, and it's not trying to do anything else. That's it. He's had people suggest, well, why don't you have this feature, and this feature is like, no, this is what it does. So Vance does a good job of curating that. And then once we set everything up, that's all it takes to actually set the wheels in motion, or as I like to say, do the deed. The very first time I spoke in Amsterdam was for the Dutch PHP conference 2007. It was the very first one. It was a single track where all in one little room, way over there, in one of the smaller areas of the ride. And I have had this bad habit all my programming career of when I don't know what to name a function, I name it do me. Well, that's fine if you're just writing your own code, but when you're showing it to 200 programmers and it says do me, no, that one went over well with the Dutch. Okay, so that's all it takes. That's our bootstrap. The next thing we need is a model. Now, I'm not going to use any models in this. This is a do as I say not as I do. All your business logic should be encapsulated in your models. All your controllers should do is be the traffic cops say, oh, we want to do this. We need this model. And once the output is done, you say, okay, here is to the view. And you hand it to the view. I don't do that. Everything is slammed in the controller in this example. But you know better how to program. This is where you would bring in your existing models. If you're working on a maintenance script for a larger application, this is where you would use your existing models instead of writing new ones. Then there's the view, because we're model view programmers, right? Model view controller programmers. But in reality, the view doesn't change with scripts like this. It's always going to output text to standard out. That's it. So in reality, yes, you could set up a view. You could use symphonies component or any of the other ones, templating engines to control your output. I have yet to find it necessary to do that when doing this with one exception. I used to have a command that when I would set up a new development area on my server, it would run everything for me. It would set up custom DNS for my local network and custom Apache config files. And I would use the Zend view to do that. But I would never output to the screen. I was using it basically as a templating engine. I would save off the output and write it to the right place. So you can use a view if you want. I don't recommend it. I've just found it's easier just to echo stuff out to the screen or in the case of the symphony command, use the right one, which will output it for you. Then we have to set up our controller. Now our controller in this, if you're using the symphony controller, they're not actually called controllers, they're called commands. But it's the same function. The command serves the function as the controller. And then the config. Now I told you a little bit earlier, I used .env just because that makes it easier. Basically all .env is, it reads in a text file, which is nothing more than a key equals value file. And it sets up environment variables for me with this name and whatever the value is. And if you understand how sessions operate in Unix, then you know that those environment variables are good only for the life of the program and as soon as the program dies, they go away. So they're not permanently set, nobody can get to them at a later date. One side note here. I did, I told you I did this talk, I've done this talk several times, one of the versions of this talk I did for the Dutch PHP conference here at the ride. And I had a script that would send a text message to a phone number. And I was using a service called Troco. A good friend of mine, Adam Kelsie, is one of the, you can see like a VP of development up there. When I uploaded it to GitHub, I mistakenly left my phone number as the test phone number. Just see where this is going. Three freaking years. I got, this is a test. And of course since I did it over here in Europe, the first year, most of those came in at two a.m. Check in a sample config file. That's what we got here. The important thing to note here is you see that my keys are all in uppercase. That is a convention that I use that is not required. The only thing you have to know is that when you're using these in your code, the case for the key has to match. So I use all uppercase, just makes it much easier. The only thing that is checked in is the sample config. You'll have to create your own config. You will need your own Twitter account. Do your friends a favor if you have a Twitter account, and if you have a Twitter account, I do expect you to be tweeting all my jokes that they're funny. It doesn't matter if you agree with me, just tweet out that they're funny. It helps me get into the next topic. But do your friends a favor, go out and get a different one, okay? Nobody wants to see this as a test 14 times in your Twitter stream. But I've got, at last count I have 12 Twitter accounts, and I'll use the one we're going to use on this one is one from a project that I've abandoned. So nobody should be watching it. But you will need to get it. You'll need to go to dev.twitter.com while you're logged into that account and get your API keys. When you do, it will tell you to read right. Do yourself a favor, set it to read right, because if you change it later it will give you new keys. You have to go through the whole process again. This application is read only. We're just going to search Twitter. But if you get ready to play around and do some more fun stuff with it, sending tweets and stuff like that, then you're going to have to read in those keys if you don't. So if you're setting up an account, I talked to you about Composer. We're going to need three components in Composer. So we go out, and I just issue these commands, require symphony console, that's going to install symphony console. I mean, it's very small, it's wonderful. Fabienne and them have done a wonderful job at breaking these things apart so that you're not sucking in everything. Then I'm going to need Vance Lucas' wonderful PHP.env. We said that we do that. We've got an environment, we're going to need Zen Framework, Zen Service, Twitter. When you issue that command, go get coffee because it's bringing in the whole Zen Framework. Actually, then bring in all of it. This will bring in probably 20, 30 different pieces. Whereas Fabienne and them have done a great job of breaking it apart. Mwap and them are still learning how to do that. And Mwap is, for those of you who don't know, Matthew Ware-Ofinney, the Allied Commander of Zen Framework and now Zen Framework too. He works for Zen, he's a great friend of mine. But that's going to bring in a ton of code. If you want to take a look at the code directories afterwards, you'll see just exactly how much cruft that Zen Framework's going to bring in. But it's the coolest Twitter client that I've found. I've been using it back when Twitter just had the basic auth. You could just log in to the API using basic auth. If you're working in APIs, it was just the easiest to work with. Nowadays, not so much. Okay, let's finish shaping the act. We're going to flesh out our directory structure, which means in my case, I have the directory that the project's in. I have a directory under that called amp. Which is just, that's where I put things. And then under that, I have PHP from the CLI. And I have to tell composer where things are located. So this is my composer, Jason. You can see that I've got my three pieces that I required. It's already built those in. The important thing right here is the auto loader. The PSR0 section, I tell it, everything for this this project is located in the PHP from the CLI directory, and that directory is located in app. That's all you have to do. You set that up, you get that right, you run composer update, it rebuilds its auto loader, everybody's happy. Don't worry about it. 30 minutes. Okay, we're not good. So let's look at some code. Oh, I said let's look at some code. Did that work? Yeah, okay. Can everybody see that? Big enough? Okay. That's the wrong point. Let's find my mouse. Oh, there it is. We have three commands that we're going to look at. I'm going to walk through in detail the first one. As you will see, the other two are basically there's a bunch of in each one that's exactly identical business and walking through detail on all three of them. So the other two I'll simply skip and show you the interesting parts. But this first one. First, I have a namespace that way, composer auto loader knows how to load this and then I load in the symphony step. And it's the symphony command, the inputs, the outputs, the requirements, all of that. But I create my class and it has to extend the command, which is the symphony command. And this one's just called test. And if you're doing this, I highly recommend you create a test class like this. Never ever check it in and push it to production. But create a test class that makes sure that you can connect to in this case, Twitter or your database or any important service. So if something goes wrong, the first thing I do is I pop back in run the test command and if Twitter is down, I know that never happens. But if Twitter is down, it will tell me that and that way I can say, okay, it's not my script. It's Twitter. Nine times out of ten, it is my script. But the test command, that's all this does, that first function laser pointer for the one configure has to be in there. Symphony's command module will look for this in a command and this is just how we set up the command. We give it a name, which is test, I actually typed in. We give it a short description and we give it a longer cut. That's the real basics of it. I did not know you were here. I saw you tweeting, but I did not know you were here. Sorry. The next one is execute. If you're familiar with Java, this is your run. This is what's going to happen after Symphony finishes setting everything up. Down to here. Now the output is one of your properties. I always save it off into a property of the class called output. I'm not going to show it to you, but if you check out the code you'll see that I actually have a trade call right line here that helps me with debugging and will only output certain things if I have a debug level set at a certain level. This kind of thing. It depends on this output being existing. I always save it off. This also means that no matter what method I'm executing this class, I have access to the output. So that's all that's doing. And then print to the CLI. That goes right down here, or print CLI. That calls PHP's staffing name. This should in every case output three letters CLI. If it outputs anything else, you're doing this way wrong. Because this is what PHP thinks it is operating in and it's just going to show us that we have the CLI. And then I call Twitter set up credentials. Now, I love the Zen Twitter client. I've been using it forever. But it is dependent upon this array being set up exactly this way. So it's just easier to put it in method. Now, you'll notice over here I'm using the $env command because .end has already pulled all my configuration in and put them into environment variables. So I'm just pulling it out with PHP's .end or underscore .env. Notice uppercase. Token, secret, consumer key, consumer secret. Got to be uppercase because that's what I specified in my file. And then we're going to create the Twitter client using those options and we're going to call verify credentials. And then I'm going to call response to value. And response to value is going to give me output. Output is going to be the just do a print R on that. It's going to be the largest output you've ever seen. For some reason, Zen Framework sucks in everything and the kitchen sink when it's outputting this object. It's a Zen Twitter response object and it's freaking huge. We're really not interested in anything in that except for the fact are do we have errors? If we have errors, output the first one because there's only one. They put it in an array. Output the first one. Otherwise, if there's no errors, output, credentials succeeded for and the account name. I'm going to show you what this looks like because this is just so dang exciting. Console test. CLI Woohoo! That also means the network's up. If the network was not up, this is a very short talk because we're almost done at that point. So, credentials ceded for Nomad Ruby which is an abandoned Twitter account that I just have laying around and then done. I always output done. I don't know why. It's just I want to know that the program succeeded or made it all the way to the end. So I just put that line there at the end. That's it. As you can see, there are two required functions, configure and execute. You have to have now in the UC that it's certainly okay to put other functions in there or other methods in your object. And by default, all of my methods are protected unless there's a reason not to be. I usually don't use public unless I want somebody else to be using them and I find private just to be offensive because that means that me as the program decided that you don't ever need to use this and that's just, I find that bad. So, but I stick with protected functions and everything and they just do the output for or they just take care of the necessary functions but I'm very big on breaking things up. I've got a friend of mine, some of you might know him, Rafael Domes. Anybody a member of Amsterdam PHP? Nobody. Anybody here from Amsterdam? Okay. Amsterdam PHP is one of the coolest PHP groups out there and I know most of the user group leaders in PHP groups in North America and Europe. But Rafael has a great talk that's available on protalk.tv called Your Code Sucks Let's Fix It and one of the things he talks about is we have a tendency just to keep putting things into the main function and he says the way you can tell this is if your code starts indenting and indenting and indenting and indenting then you need to break that up into smaller and smaller functions. I think his rule of thumb is if you have more than two levels of indent you need to break it up into another function. So that's what I'm trying to do. I'm trying to make Rafael proud so I keep breaking things up into smaller functions. Okay. That's the test. The test works. The network's still working. We're good. Okay. You can see I used my right line trait but here we also we define a few extra things. For my Twitter client I've got several options. The first is do I want English only tweets? The default is no but I can specify yes because quite honestly non-English tweets don't do me any good. But it defaults to no. Then the count. Twitter allows us to specify between one and 20 tweets to be returned. So if you don't specify it's going to default to 20 but and that's set somewhere else. But if you don't specify it'll return to full 20 but you can specify I only need two for this instance. And then only names and I'll show you why in a little bit but we have the option to only output the names of the people they're tweeting. So I set those as properties because I'm going to bring them in using command line properties but I need to store them in my object. Now, you'll notice in the configure that this is new. Let's see if I can scroll that over a little bit. Nope. Okay. We're defining an array called definition and this is the definition of our command line arguments. Now the test didn't have any command line arguments that they specified and the command itself did not specify any. It actually has about 10 of those symphonies of console predefined about 10 of course and this will eventually if you do this a lot it predefining all of these will drive you up the wall because it's taking all the good letters. The single letter things in dash E or something like that. Well it's got dash B so you can forget about using that for version for your script. It'll eventually drive you up the wall but for right now we're just going to find these and this one is set to value none just a flag. If you say dash E is specifying a flag it's only going to give me the English back. Only names is a flag count. It's an optional argument but it will take a parameter and search term. Now by default if we specify this it's going to search for pound PHP because that's usually what I'm looking for. However I can specify search term with anything. It is optional. I use the dash S although it says value required and you can't see it at the end of that. That last little there we go so I've got search term is the long command S is the short so I can do dash dash search term or dash S and then in my help if I specify help for the command it's going to say the term to search for default is PHP. It is required but there at the end I'm setting a default to pound PHP so it is required but it is getting a value even if I don't specify one. Back over here. We build that array and then this looks exactly the same with the exception of we now have set definition and that's it. Let's come down here I pick up my properties from get an input, get option. I do not save off input like I save off output because once you get through with it right here you usually don't ever need it again but I do save off, I use get option to get my my English, my only names and my count and if you didn't specify account then it's going to use null which if you don't specify Twitter will automatically use 20. I come on down, I set my search options if you specified English then we're going to use language, if you specified account we're going to use account. The search options is an array that I'm going to hand to Zen's search component and say input, get options, search term whatever my search term is and then the search options which is the array that we do with these two properties that's all the properties that are there and then we're going to process the response. We're going to do the deed and we're going to process the response and again tweet is a freaking huge thing and we're really only interested in a subset of what's the statuses. So we're going to send it to value and then we're going to pull out the statuses array and that's what we're going to spin through here and we're simply using the right one to say single tweet username and if you get down to it I'm just outputting it to the screen using the right one this is harder than you think when you're doing it this way. There we go I'm outputting the username and then two dashes and then the text. The text is optional. If you specify only names it will skip that. Okay. And then I set up Twitter just like I did last time and then set output which is just the way of setting the colors if you're interested in how that works with symphony check out the code. It gives you an example of that. Let's see this in action. Console Okay. Just a basic search. Basic search spelled correctly. There you go. The green is the username the rest of it is the tweet. Okay. Just to give you an idea if I say O and E. Those are only the names of the people that have tweeted something in English. I know. You know. I see the stunt. Half the room is stunned. I didn't know you could do this. The other half is I can monetize it. You can't. Okay. But Twitter can't. But that's what it does. That by itself not that stunning. Okay. But again the point of this is to show you what's possible and this is going to be a little more fun. Now I'm going to skip all the cruft. This one is called Echo. As you can see it takes standard in. Everybody knows that you have a standard in file handle that's already open. If you don't. PHP has STDIN. You can do any file options on them any reads of them. You can't write the standard in. Okay. It's not going to work. But you can do anything. It's already open for you. It's a constant and basically if anything's piped into this script it's going to come out of standard in. So I'm saying while I can get stuff out of standard in, echo it out with a counter, call in and content. It just echoes things and it's going to echo them back out and it's going to number them for us. The point is not to do something stunning with the code. The point is to be able to do something like this. Console search only English. Let's pipe this to sort pipe it to unique Told you. I always output done. I never want done into my list. So let's get rid of done. There we have it. We have outputted. We've taken all of them. We've written our script and our script is now a first class citizen in a Unix tool chain. We can even go one step further than that and pipe this back into console echo and now they're numbered. The amazing thing is not that Twitter has not failed in the past hour. The amazing thing is we've written code that now works with a Unix tool chain. So if you're writing your own command line script you don't have to write it all. Now I know a lot of some PHP do enjoy reinventing the wheel. I've got a stack of them in my project but we don't have to because Unix already gives us a way to sort things and a way to only pull out the unique things. And then we can pipe it back in. Now I have to show you this because I gave this talk at Drupalcon LA and in the audience was Ms. Sarah Goldman. Sarah if you do not know is a core developer. She now works at Facebook. She's working on the Hack and HHBM project but she wrote the SSH and SSHLib implementation for PHP. So if you use SSH or SSL in PHP, you owe Sarah a thank you tweet or something. She's a wonderful person. Good friend of mine I'm lucky to have a friend like her but she said, hey Cal that's cool but I'm going to copy and paste here. I've got these one here. I thought I was going to copy and paste. There we go. Okay, console. Let's get rid of all of this. And let's pipe it back into PHP. Can I screw that up? You're right. Sorry. Thank you. Congratulations, pair programming taken to the extreme. This isn't nearly as embarrassing as being on I used to do a two week tour where I would give the same talk over and over for two weeks and being in the last session at the last city and they point out, you know you got a spelling error in your slides. Nobody else could have told me that. Okay, so here's what we're going to do. We're still doing the search with only names in English and we're going to grep out the done. And if you don't know the dash V for grep, that's just exclude any line that says done. Okay. And then we're going to sort it and we're going to pipe it to unique but then we're going to take it instead of piping it back into echo, we're going to pipe it back into PHP with the capital R and what capital R does is says for anything coming into PHP execute this so since I'm piping it in as long as it's got input it's going to spin through this file. Now this is a really stupid piece of code. It's going to print the name colon and then print the name with string reverse. Again, the point is not to wow you with my coding abilities, it's to show you what's possible. Okay. The dash R is a very powerful tool. PHP, you can pipe things straight into it. Again, we're using fdits on standard N. And we can tell it as long as you've got input, execute this. It's a very powerful tool. This is also fun for those times when your in-laws ask you, well what do you do? Well here, let me show you. Guarantee you they will never ask you that question. Okay. Thus end the code portion. How am I doing on time? Oh, I've got 15 minutes. Okay. We're about done. We're going to be done early, I told you that. I talk fast. Let's wrap it up. First, I'm going to take a sip of what I really had hoped was wine. They really ought not put it in bottles like that. Got my hopes up because I have found that my talks when I have had some alcohol, not a lot of alcohol, but I found that I enjoy them a lot more. It doesn't matter if you do anymore. I'm very funny drunk in my own head. Anyhow, wrap it up. Why do we do this? Because it's easy. I find this so much easier than writing a web-based tool because I don't have to deal with the HTML and all of that kind of stuff. I can use JSON and PHP. XML if I have to, but I charge more for using XML. But if you require it, I can do that. I don't accept jobs that require soap, and those of you who got close to me know that. No, I can't stand so if I use REST. But it's easy. All my friends are there. I use this for maintenance scripts of wine. I run a project right now where literally I have 10 or 15 of these that I run on a monthly basis just to keep everything flowing. The very first time I did this commercially, and not the mail script because that was not really commercially. It was from my own server, but I was setting up email accounts for my friends and family. But the very first time I did this commercially was I used to run DevZone for Zen if you've ever been there. It used to be a community site. Now it's mainly Zen stuff. That's not saying anything bad. But when I was running it, it was all community stuff. And we kept adding to it and making things and we had tag clouds and all this kind of fun stuff. And the tag clouds were dynamic. Which means they would load in via JavaScript. It was fun. But I got to realizing the more stuff we added, the slower it got. And it got to the point where it was taking 10, 15 seconds just to load the page which everybody knows that's unacceptable. So I started digging into the script. I used the Zen cache component. And I started caching the cache not out of everything. But the problem I found is every now and then I would run into an edge case where my caching rules did not work. Now my caching rules were if I posted a new article, clear the home page cache so that it would pick up the next time. And my tag cloud was cached for five minutes and all this kind of stuff. But every now and then I ran into a situation that I just needed to wipe the cache. I made that script. I just right, I did. It took 20 original lines of code plus the Zen framework crux that went around it. And I could just anytime I wanted to I could log in to the server, boom, clear the cache. Not only did it clear that cache but it would notify the other two because it was a distributed server. It notified the other two caches to clear themselves as well. They come in handy and you're going to find more and more uses for it. If you get comfortable doing this you'll find more and more uses. All of your, if you use an IDE you should not have any problem. I don't. I use sublime text these days simply because it'll open dang near anything and trust me I've tried. I've actually opened a JPEG with it. You don't want to do that. But it'll open anything. I just enjoy that more. I don't use an IDE. But if use an IDE like PSP storm or anything it's going to work with this. You don't have any problem. Find a project and just write a script for it. See if it works. It doesn't work for you. Don't worry about it. But I think you'll find that you're going to find ways to make it useful. Up until recently we could not have long running scripts in PHP. By long running scripts I mean anything's going to run for a minute or more. Most PHP scripts execute in sub second. But there are times when you want to process something large. I used to do this. I had a client that had 300 web servers that would generate a gigabyte log file every night. Apache Web servers. And he wanted to be able to search these. So I said okay fine. I'll write a script and we'll suck them into MySQL. Dumb idea. But that's not the point of this story. I wrote the script. I ran it on a 10 mag file and it worked beautifully. I mean you were processing two 300 lines per second. And I've got timers showing me that it's working and it's doing and how fast it's running. I said okay fine. I pointed it to the director. At 5 o'clock I hit the button and I went home. I come in the next morning. Not only is it not finished, but it's processing one line every 60 second. There's a memory bug in PHP up through 5.3. 5.3 they can clear it up. We can have long running processes. I have one, I have a little matmini at home that I like to pretend is my development server but I don't really do much unless I'm running classes or sessions anymore. But it's my development server. I do have a script that has been running on that for 3 months. I have no intention of stopping it. Now it's not constantly doing something. It will go to sleep for 10 minutes. It'll wake up. It'll check something. Hey, there's something I need to do. So it'll process. Sometimes it'll process for 2-3 hours and then it'll go back to sleep. But I don't have to keep running it. I don't have to put it in a crime job and say run this every hour. It's just a long running process. We've been running it for 3 months. We can now have these long running processes. I am not saying write daemons in PHP. Please don't tweet that out. At Drupal Camp LA they give. And one of the core developers who did not have contacts, he's a friend of mine wrote the facts as you're kidding, right? You would never suggest asking. No! I wasn't suggesting that. Don't write daemons. PHP is not the answer to everything. But if you've got something that needs to process for a long time, we now have the option to do that. And you don't have to run it in a web browser and keep that connection alive. You run a maintenance script, you run a PHP script from the command line, fire it up, let it run for as long as you want. It's absolutely wonderful. PHP is not the answer for everything. I do not believe that. I keep wanting to learn Ruby and Node and all these other things. And as soon as I find a project that I have to do, that I can't do well in PHP, I'm going to learn one of those. The problem is all the problems that I have to solve run very nicely in PHP, so I just don't have the reason to do that. Anyhow, that's all I've got for you. My name is Cal Evans. You can find my blog at blog.calevans.com if you do, stop by, leave a comment because it's basically me and my mom, so I'd love to hear from you. You can follow me on Twitter if you didn't get enough of me here, but most of you probably did. I'm at Cal Evans. I work for a wonderful company called Pantheon. That's getpantheon.com We do workflow and hosting for Drupal and WordPress sites. If you are in the market, come by the booth. I would love to talk to you. They've got a little demo. We can run you through. We'll give you a free t-shirt. It's all kind of fun. If you have any questions, PHP, Drupal not so much because I do not have the deep inroads into Drupal, the Drupal community that I have in the PHP community, but I've been banging around the PHP community for 13 years. I know a lot of people there. If you're stuck on something, drop me an email. Chances are I don't know the answer. I'm not that smart, but I probably do know who does know the answer and I'm happy to introduce you. And that's the one thing about the PHP community. All of us realize that we're standing on the shoulders of giants, that we're using programs and things like Drupal that others have graciously volunteered for, so it's up to us to volunteer our time to help the next person down the line. So, that's me. If you have any questions, I'll be floating around at the booth. Thank you for your attention. You've been a wonderful audience.